From a75091ca92d1fb5911b60c93e278c353651b37a9 Mon Sep 17 00:00:00 2001 From: ioxde <228087182+ioxde@users.noreply.github.com> Date: Tue, 14 Apr 2026 10:21:18 -0700 Subject: [PATCH 01/24] Update codama dependencies --- package.json | 8 +- pnpm-lock.yaml | 235 +++++++++++++++++++++++++++---------------------- 2 files changed, 134 insertions(+), 109 deletions(-) diff --git a/package.json b/package.json index 4e9bca1..162c4a0 100644 --- a/package.json +++ b/package.json @@ -41,10 +41,10 @@ "test:unit": "vitest run" }, "dependencies": { - "@codama/errors": "^1.5.0", - "@codama/nodes": "^1.5.0", + "@codama/errors": "^1.6.0", + "@codama/nodes": "^1.6.0", "@codama/renderers-core": "^1.3.5", - "@codama/visitors-core": "^1.5.0", + "@codama/visitors-core": "^1.6.0", "@iarna/toml": "^2.2.5", "@solana/codecs-strings": "^6.0.0", "nunjucks": "^3.2.4", @@ -53,7 +53,7 @@ "devDependencies": { "@changesets/changelog-github": "^0.5.1", "@changesets/cli": "^2.29.7", - "@codama/nodes-from-anchor": "^1.3.6", + "@codama/nodes-from-anchor": "^1.4.1", "@solana/eslint-config-solana": "^5.0.0", "@solana/prettier-config-solana": "0.0.5", "@types/node": "^25", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 0146059..41dcce3 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -9,17 +9,17 @@ importers: .: dependencies: '@codama/errors': - specifier: ^1.5.0 - version: 1.5.0 + specifier: ^1.6.0 + version: 1.6.0 '@codama/nodes': - specifier: ^1.5.0 - version: 1.5.0 + specifier: ^1.6.0 + version: 1.6.0 '@codama/renderers-core': specifier: ^1.3.5 version: 1.3.5 '@codama/visitors-core': - specifier: ^1.5.0 - version: 1.5.0 + specifier: ^1.6.0 + version: 1.6.0 '@iarna/toml': specifier: ^2.2.5 version: 2.2.5 @@ -40,8 +40,8 @@ importers: specifier: ^2.29.7 version: 2.29.8(@types/node@25.2.3) '@codama/nodes-from-anchor': - specifier: ^1.3.6 - version: 1.3.6(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) + specifier: ^1.4.1 + version: 1.4.1(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) '@solana/eslint-config-solana': specifier: ^5.0.0 version: 5.0.0(@eslint/js@9.39.1)(@types/eslint__js@8.42.3)(eslint-plugin-jest@29.0.1(@typescript-eslint/eslint-plugin@8.43.0(@typescript-eslint/parser@8.43.0(eslint@9.39.1)(typescript@5.9.3))(eslint@9.39.1)(typescript@5.9.3))(eslint@9.39.1)(jest@30.1.3(@types/node@25.2.3))(typescript@5.9.3))(eslint-plugin-react-hooks@5.2.0(eslint@9.39.1))(eslint-plugin-simple-import-sort@12.1.1(eslint@9.39.1))(eslint-plugin-sort-keys-fix@1.1.2)(eslint-plugin-typescript-sort-keys@3.3.0(@typescript-eslint/parser@8.43.0(eslint@9.39.1)(typescript@5.9.3))(eslint@9.39.1)(typescript@5.9.3))(eslint@9.39.1)(globals@14.0.0)(jest@30.1.3(@types/node@25.2.3))(typescript-eslint@8.43.0(eslint@9.39.1)(typescript@5.9.3))(typescript@5.9.3) @@ -314,40 +314,40 @@ packages: '@changesets/write@0.4.0': resolution: {integrity: sha512-CdTLvIOPiCNuH71pyDu3rA+Q0n65cmAbXnwWH84rKGiFumFzkmHNT8KHTMEchcxN+Kl8I54xGUhJ7l3E7X396Q==} - '@codama/errors@1.4.4': - resolution: {integrity: sha512-XC86H5X+zGTi0cSRKLc+wFkeXNsvnh+ttOgVnVHIljmXOJWbUt9wXhKding3UftipLWwlHPuoswERJ0vS0mO2A==} - hasBin: true - '@codama/errors@1.5.0': resolution: {integrity: sha512-i4cS+S7JaZXhofQHFY3cwzt8rqxUVPNaeJND5VOyKUbtcOi933YXJXk52gDG4mc+CpGqHJijsJjfSpr1lJGxzg==} hasBin: true - '@codama/node-types@1.4.4': - resolution: {integrity: sha512-uUeIz34Id/TTAMi4k5OVl9FByM/PawnlNIIVqgpooH9AS0UlniICZ+KJ/mdHZidJs/AGo6bSRoOPS1BLtMajyw==} + '@codama/errors@1.6.0': + resolution: {integrity: sha512-Evj9wO5lqvxvbjxG856ITY5lhRN7SqoYfRX4tMMBjs8J/kT+pKQ8qL0hz9OynOOv/5mWn9Q/sPCNzQ6CUscibQ==} + hasBin: true '@codama/node-types@1.5.0': resolution: {integrity: sha512-Ebz2vOUukmNaFXWdkni1ZihXkAIUnPYtqIMXYxKXOxjMP+TGz2q0lGtRo7sqw1pc2ksFBIkfBp5pZsl5p6gwXA==} - '@codama/nodes-from-anchor@1.3.6': - resolution: {integrity: sha512-614DZS9H5gW16Rkeu0ES8BHnDvbd8M9FLqPWnp9QUE0b+wCvWB36yZiRylJ4fw8gRDSc+FR7C2i3NXKycpvBEg==} + '@codama/node-types@1.6.0': + resolution: {integrity: sha512-atIJW2/3MjPYey0bNlE86W9Gvq9aq8bud7zT7PMyyhj98mbmLqPwT4wclPdbFua0fROLkq17z3bXaaJy5FqSEw==} - '@codama/nodes@1.4.4': - resolution: {integrity: sha512-JzlY5qLk3rhsnu0nerC/Vkc9/2HjdsLtEpBtST0dxC1j9kpfHvIc2uyIj+5hlB1YIBRJIDNo+UOHGla8hidkaA==} + '@codama/nodes-from-anchor@1.4.1': + resolution: {integrity: sha512-2RuLk/pCn+KXYSZoSA1k/sP1C4VzlbNFtMu2AxiBMXyyR8WYKFkrRghjI4IR+otwhknV7QhdFr8h5tuD+TSQ4g==} '@codama/nodes@1.5.0': resolution: {integrity: sha512-yg+xmorWiMNjS3n19CGIt/FZ/ZCuDIu+HEY45bq6gHu1MN3RtJZY+Q3v0ErnBPA60D8mNWkvkKoeSZXfzcAvfw==} + '@codama/nodes@1.6.0': + resolution: {integrity: sha512-F6Hy3REfl+Ih5R3jldPqEMjFqaPj871iBWX/LV0EtNK0xn7E4DG/3XCK4wlbHrOT9Z1NsiA70e0M1uChzmIrsw==} + '@codama/renderers-core@1.3.5': resolution: {integrity: sha512-MuZLU+3LZPQb1HuZffwZl+v5JHQDe5LYHGhA1wTMNlwRedYIysSxBjogHNciNIHsKP3JjmqyYmLO5LCEp3hjaQ==} - '@codama/visitors-core@1.4.4': - resolution: {integrity: sha512-vk/4tczViAUHa7c8PF7FxN+JWbuTcDB0pIdrDbbO6eBPKDPQGZCUCEp6rXIYBVxfO129jWrNf2+CuyYre/c/vA==} - '@codama/visitors-core@1.5.0': resolution: {integrity: sha512-3PIAlBX0a06hIxzyPtQMfQcqWGFBgfbwysSwcXBbvHUYbemwhD6xwlBKJuqTwm9DyFj3faStp5fpvcp03Rjxtw==} - '@codama/visitors@1.4.4': - resolution: {integrity: sha512-3w2aRNvGV6/rXTfRDynXR82zoAqX0P4tlfQ/zT4I4Bby4xTobKgDZLyAstodmA0D878eKW7sMg4Gb1m1R5dOig==} + '@codama/visitors-core@1.6.0': + resolution: {integrity: sha512-YG0rExvLbBCDAzXnZX6Imu4KwDoZrZz9NF232/nzs9Dr8uQuEWJ81x4VR9UxIcANHcF0+XwJzHamSwhZroAtjQ==} + + '@codama/visitors@1.6.0': + resolution: {integrity: sha512-11/adC2WiH3+iMWluXkb+ae46sjoDm2xztI+CBEeIcBQd6mm4iuJTTRS0yrGfDwAJE1XzI/nc2MrR0Pvn+Rvvw==} '@emnapi/core@1.7.1': resolution: {integrity: sha512-o1uhUASyo921r2XtHYOHy7gdkGLge8ghBEQHMWmyJFoXlpU58kIrhhN3w26lpQb6dspetweapMn2CSNwQ8I4wg==} @@ -1125,11 +1125,14 @@ packages: '@sinonjs/fake-timers@13.0.5': resolution: {integrity: sha512-36/hTbH2uaWuGVERyC6da9YwGWnzUZXuPro/F2LfsdOsLnCojz/iSH8MxUt/FD2S5XBSVPhmArFUXcpCQ2Hkiw==} - '@solana/codecs-core@5.0.0': - resolution: {integrity: sha512-rCG2d8OaamVF2/J//YyCgDqNJpUytVVltw9C8mJtEz5c6Se/LR6BFuG8g4xeJswq/ab4RFk5/HFdgbvNjKgQjA==} + '@solana/codecs-core@5.5.1': + resolution: {integrity: sha512-TgBt//bbKBct0t6/MpA8ElaOA3sa8eYVvR7LGslCZ84WiAwwjCY0lW/lOYsFHJQzwREMdUyuEyy5YWBKtdh8Rw==} engines: {node: '>=20.18.0'} peerDependencies: - typescript: '>=5.3.3' + typescript: ^5.0.0 + peerDependenciesMeta: + typescript: + optional: true '@solana/codecs-core@6.0.1': resolution: {integrity: sha512-OnUQk94qfvfE0nVveZ638aNUL3tyRJoorUFiAG0ICTGUo3c6fkYb8vH23o/5O2qmuSmYND1sn+UCaldNMVkFpg==} @@ -1140,17 +1143,23 @@ packages: typescript: optional: true - '@solana/codecs-data-structures@5.0.0': - resolution: {integrity: sha512-y503Pqmv0LHcfcf0vQJGaxDvydQJbyCo8nK3nxn56EhFj5lBQ1NWb3WvTd83epigwuZurW2MhJARrpikfhQglQ==} + '@solana/codecs-data-structures@5.5.1': + resolution: {integrity: sha512-97bJWGyUY9WvBz3mX1UV3YPWGDTez6btCfD0ip3UVEXJbItVuUiOkzcO5iFDUtQT5riKT6xC+Mzl+0nO76gd0w==} engines: {node: '>=20.18.0'} peerDependencies: - typescript: '>=5.3.3' + typescript: ^5.0.0 + peerDependenciesMeta: + typescript: + optional: true - '@solana/codecs-numbers@5.0.0': - resolution: {integrity: sha512-a2+skRLuUK02f/XFe4L0e1+wHCyfK25PkyseFps1v1l4pvevukFwth/EhSyrs6w5CsTJRVoR7MuE3E00PM4egw==} + '@solana/codecs-numbers@5.5.1': + resolution: {integrity: sha512-rllMIZAHqmtvC0HO/dc/21wDuWaD0B8Ryv8o+YtsICQBuiL/0U4AGwH7Pi5GNFySYk0/crSuwfIqQFtmxNSPFw==} engines: {node: '>=20.18.0'} peerDependencies: - typescript: '>=5.3.3' + typescript: ^5.0.0 + peerDependenciesMeta: + typescript: + optional: true '@solana/codecs-numbers@6.0.1': resolution: {integrity: sha512-ZrI1NjUsf4I+Klue/2rlQbZLcGRom/G2E4VB/8x4IEHGOeFLQhXcxmnib8kdgomQRYOzF1BjVDmCYxvZr+6AWA==} @@ -1161,12 +1170,17 @@ packages: typescript: optional: true - '@solana/codecs-strings@5.0.0': - resolution: {integrity: sha512-ALkRwpV8bGR6qjAYw0YXZwp2YI4wzvKOJGmx04Ut8gMdbaUx7qOcJkhEQKI6ZVC3lAWSIS1N1wGccUZDwvfKxw==} + '@solana/codecs-strings@5.5.1': + resolution: {integrity: sha512-7klX4AhfHYA+uKKC/nxRGP2MntbYQCR3N6+v7bk1W/rSxYuhNmt+FN8aoThSZtWIKwN6BEyR1167ka8Co1+E7A==} engines: {node: '>=20.18.0'} peerDependencies: fastestsmallesttextencoderdecoder: ^1.0.22 - typescript: '>=5.3.3' + typescript: ^5.0.0 + peerDependenciesMeta: + fastestsmallesttextencoderdecoder: + optional: true + typescript: + optional: true '@solana/codecs-strings@6.0.1': resolution: {integrity: sha512-OmMIfMFbbJVIxveBeATKCj9DsmZ8l4vJPnOLHUop0hLWRiYHTQ1qokMqfk/X8PCmUjXmbXnlp63BikGtdKN3/g==} @@ -1180,18 +1194,24 @@ packages: typescript: optional: true - '@solana/codecs@5.0.0': - resolution: {integrity: sha512-KOw0gFUSBxIMDWLJ3AkVFkEci91dw0Rpx3C6y83Our7fSW+SEP8vRZklCElieYR85LHVB1QIEhoeHR7rc+Ifkw==} + '@solana/codecs@5.5.1': + resolution: {integrity: sha512-Vea29nJub/bXjfzEV7ZZQ/PWr1pYLZo3z0qW0LQL37uKKVzVFRQlwetd7INk3YtTD3xm9WUYr7bCvYUk3uKy2g==} engines: {node: '>=20.18.0'} peerDependencies: - typescript: '>=5.3.3' + typescript: ^5.0.0 + peerDependenciesMeta: + typescript: + optional: true - '@solana/errors@5.0.0': - resolution: {integrity: sha512-gTuhzO6E+ydfAAzqmqdPcvFyJwAzFKKIrqtnZPpgAuomcPYu+HSo0tuwSM/cTX0djmHt+GoOsf/julph+nvs2w==} + '@solana/errors@5.5.1': + resolution: {integrity: sha512-vFO3p+S7HoyyrcAectnXbdsMfwUzY2zYFUc2DEe5BwpiE9J1IAxPBGjOWO6hL1bbYdBrlmjNx8DXCslqS+Kcmg==} engines: {node: '>=20.18.0'} hasBin: true peerDependencies: - typescript: '>=5.3.3' + typescript: ^5.0.0 + peerDependenciesMeta: + typescript: + optional: true '@solana/errors@6.0.1': resolution: {integrity: sha512-sMe5GCsXto8F1KDeq9GbZR0+m841SqEYep3NAcYlC0lqF2RG4giaaPQHgrWI5DJR/L7yc8FzUIQfTxnaN7bwOQ==} @@ -1219,11 +1239,14 @@ packages: typescript: ^5.6 typescript-eslint: ^8.11.0 - '@solana/options@5.0.0': - resolution: {integrity: sha512-ezHVBFb9FXVSn8LUVRD2tLb6fejU0x8KtGEYyCYh0J0pQuXSITV0IQCjcEopvu/ZxWdXOJyzjvmymnhz90on5A==} + '@solana/options@5.5.1': + resolution: {integrity: sha512-eo971c9iLNLmk+yOFyo7yKIJzJ/zou6uKpy6mBuyb/thKtS/haiKIc3VLhyTXty3OH2PW8yOlORJnv4DexJB8A==} engines: {node: '>=20.18.0'} peerDependencies: - typescript: '>=5.3.3' + typescript: ^5.0.0 + peerDependenciesMeta: + typescript: + optional: true '@solana/prettier-config-solana@0.0.5': resolution: {integrity: sha512-igtLH1QaX5xzSLlqteexRIg9X1QKA03xKYQc2qY1TrMDDhxKXoRZOStQPWdita2FVJzxTGz/tdMGC1vS0biRcg==} @@ -1781,10 +1804,6 @@ packages: color-name@1.1.4: resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} - commander@14.0.1: - resolution: {integrity: sha512-2JkV3gUZUVrbNA+1sjBOYLsMZ5cEEl8GTFP2a4AVz5hvasAMCQ1D2l2le/cX+pV4N6ZU17zjUahLpIXRrnWL8A==} - engines: {node: '>=20'} - commander@14.0.2: resolution: {integrity: sha512-TywoWNNRbhoD0BXs1P3ZEScW8W5iKrnbithIl0YH+uCmBd0QpPOA8yc82DS3BIE5Ma6FnBVUsJ7wVUDz4dvOWQ==} engines: {node: '>=20'} @@ -3628,66 +3647,66 @@ snapshots: human-id: 4.1.3 prettier: 2.8.8 - '@codama/errors@1.4.4': - dependencies: - '@codama/node-types': 1.4.4 - commander: 14.0.2 - picocolors: 1.1.1 - '@codama/errors@1.5.0': dependencies: '@codama/node-types': 1.5.0 commander: 14.0.2 picocolors: 1.1.1 - '@codama/node-types@1.4.4': {} + '@codama/errors@1.6.0': + dependencies: + '@codama/node-types': 1.6.0 + commander: 14.0.3 + picocolors: 1.1.1 '@codama/node-types@1.5.0': {} - '@codama/nodes-from-anchor@1.3.6(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)': + '@codama/node-types@1.6.0': {} + + '@codama/nodes-from-anchor@1.4.1(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)': dependencies: - '@codama/errors': 1.4.4 - '@codama/nodes': 1.4.4 - '@codama/visitors': 1.4.4 + '@codama/errors': 1.6.0 + '@codama/nodes': 1.6.0 + '@codama/visitors': 1.6.0 '@noble/hashes': 2.0.1 - '@solana/codecs': 5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) + '@solana/codecs': 5.5.1(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) transitivePeerDependencies: - fastestsmallesttextencoderdecoder - typescript - '@codama/nodes@1.4.4': - dependencies: - '@codama/errors': 1.4.4 - '@codama/node-types': 1.4.4 - '@codama/nodes@1.5.0': dependencies: '@codama/errors': 1.5.0 '@codama/node-types': 1.5.0 + '@codama/nodes@1.6.0': + dependencies: + '@codama/errors': 1.6.0 + '@codama/node-types': 1.6.0 + '@codama/renderers-core@1.3.5': dependencies: '@codama/errors': 1.5.0 '@codama/nodes': 1.5.0 '@codama/visitors-core': 1.5.0 - '@codama/visitors-core@1.4.4': - dependencies: - '@codama/errors': 1.4.4 - '@codama/nodes': 1.4.4 - json-stable-stringify: 1.3.0 - '@codama/visitors-core@1.5.0': dependencies: '@codama/errors': 1.5.0 '@codama/nodes': 1.5.0 json-stable-stringify: 1.3.0 - '@codama/visitors@1.4.4': + '@codama/visitors-core@1.6.0': + dependencies: + '@codama/errors': 1.6.0 + '@codama/nodes': 1.6.0 + json-stable-stringify: 1.3.0 + + '@codama/visitors@1.6.0': dependencies: - '@codama/errors': 1.4.4 - '@codama/nodes': 1.4.4 - '@codama/visitors-core': 1.4.4 + '@codama/errors': 1.6.0 + '@codama/nodes': 1.6.0 + '@codama/visitors-core': 1.6.0 '@emnapi/core@1.7.1': dependencies: @@ -4338,9 +4357,10 @@ snapshots: dependencies: '@sinonjs/commons': 3.0.1 - '@solana/codecs-core@5.0.0(typescript@5.9.3)': + '@solana/codecs-core@5.5.1(typescript@5.9.3)': dependencies: - '@solana/errors': 5.0.0(typescript@5.9.3) + '@solana/errors': 5.5.1(typescript@5.9.3) + optionalDependencies: typescript: 5.9.3 '@solana/codecs-core@6.0.1(typescript@5.9.3)': @@ -4349,17 +4369,19 @@ snapshots: optionalDependencies: typescript: 5.9.3 - '@solana/codecs-data-structures@5.0.0(typescript@5.9.3)': + '@solana/codecs-data-structures@5.5.1(typescript@5.9.3)': dependencies: - '@solana/codecs-core': 5.0.0(typescript@5.9.3) - '@solana/codecs-numbers': 5.0.0(typescript@5.9.3) - '@solana/errors': 5.0.0(typescript@5.9.3) + '@solana/codecs-core': 5.5.1(typescript@5.9.3) + '@solana/codecs-numbers': 5.5.1(typescript@5.9.3) + '@solana/errors': 5.5.1(typescript@5.9.3) + optionalDependencies: typescript: 5.9.3 - '@solana/codecs-numbers@5.0.0(typescript@5.9.3)': + '@solana/codecs-numbers@5.5.1(typescript@5.9.3)': dependencies: - '@solana/codecs-core': 5.0.0(typescript@5.9.3) - '@solana/errors': 5.0.0(typescript@5.9.3) + '@solana/codecs-core': 5.5.1(typescript@5.9.3) + '@solana/errors': 5.5.1(typescript@5.9.3) + optionalDependencies: typescript: 5.9.3 '@solana/codecs-numbers@6.0.1(typescript@5.9.3)': @@ -4369,11 +4391,12 @@ snapshots: optionalDependencies: typescript: 5.9.3 - '@solana/codecs-strings@5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)': + '@solana/codecs-strings@5.5.1(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)': dependencies: - '@solana/codecs-core': 5.0.0(typescript@5.9.3) - '@solana/codecs-numbers': 5.0.0(typescript@5.9.3) - '@solana/errors': 5.0.0(typescript@5.9.3) + '@solana/codecs-core': 5.5.1(typescript@5.9.3) + '@solana/codecs-numbers': 5.5.1(typescript@5.9.3) + '@solana/errors': 5.5.1(typescript@5.9.3) + optionalDependencies: fastestsmallesttextencoderdecoder: 1.0.22 typescript: 5.9.3 @@ -4386,21 +4409,23 @@ snapshots: fastestsmallesttextencoderdecoder: 1.0.22 typescript: 5.9.3 - '@solana/codecs@5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)': + '@solana/codecs@5.5.1(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)': dependencies: - '@solana/codecs-core': 5.0.0(typescript@5.9.3) - '@solana/codecs-data-structures': 5.0.0(typescript@5.9.3) - '@solana/codecs-numbers': 5.0.0(typescript@5.9.3) - '@solana/codecs-strings': 5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) - '@solana/options': 5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) + '@solana/codecs-core': 5.5.1(typescript@5.9.3) + '@solana/codecs-data-structures': 5.5.1(typescript@5.9.3) + '@solana/codecs-numbers': 5.5.1(typescript@5.9.3) + '@solana/codecs-strings': 5.5.1(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) + '@solana/options': 5.5.1(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) + optionalDependencies: typescript: 5.9.3 transitivePeerDependencies: - fastestsmallesttextencoderdecoder - '@solana/errors@5.0.0(typescript@5.9.3)': + '@solana/errors@5.5.1(typescript@5.9.3)': dependencies: chalk: 5.6.2 - commander: 14.0.1 + commander: 14.0.2 + optionalDependencies: typescript: 5.9.3 '@solana/errors@6.0.1(typescript@5.9.3)': @@ -4425,13 +4450,14 @@ snapshots: typescript: 5.9.3 typescript-eslint: 8.43.0(eslint@9.39.1)(typescript@5.9.3) - '@solana/options@5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)': + '@solana/options@5.5.1(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)': dependencies: - '@solana/codecs-core': 5.0.0(typescript@5.9.3) - '@solana/codecs-data-structures': 5.0.0(typescript@5.9.3) - '@solana/codecs-numbers': 5.0.0(typescript@5.9.3) - '@solana/codecs-strings': 5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) - '@solana/errors': 5.0.0(typescript@5.9.3) + '@solana/codecs-core': 5.5.1(typescript@5.9.3) + '@solana/codecs-data-structures': 5.5.1(typescript@5.9.3) + '@solana/codecs-numbers': 5.5.1(typescript@5.9.3) + '@solana/codecs-strings': 5.5.1(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) + '@solana/errors': 5.5.1(typescript@5.9.3) + optionalDependencies: typescript: 5.9.3 transitivePeerDependencies: - fastestsmallesttextencoderdecoder @@ -5039,8 +5065,6 @@ snapshots: color-name@1.1.4: {} - commander@14.0.1: {} - commander@14.0.2: {} commander@14.0.3: {} @@ -5355,7 +5379,8 @@ snapshots: fast-levenshtein@2.0.6: {} - fastestsmallesttextencoderdecoder@1.0.22: {} + fastestsmallesttextencoderdecoder@1.0.22: + optional: true fastq@1.19.1: dependencies: From 4ed6a60442612c24f81ad541dfdf848ce9e3bd43 Mon Sep 17 00:00:00 2001 From: ioxde <228087182+ioxde@users.noreply.github.com> Date: Tue, 14 Apr 2026 14:32:03 -0700 Subject: [PATCH 02/24] Add Raydium CPMM e2e fixture --- Cargo.lock | 18 + e2e/raydium-cpmm/Cargo.toml | 24 + e2e/raydium-cpmm/idl.json | 2115 +++++++++++++++++ .../src/generated/accounts/amm_config.rs | 150 ++ .../src/generated/accounts/mod.rs | 14 + .../generated/accounts/observation_state.rs | 140 ++ .../src/generated/accounts/pool_state.rs | 174 ++ e2e/raydium-cpmm/src/generated/errors/mod.rs | 10 + .../src/generated/errors/raydium_cp_swap.rs | 52 + .../instructions/collect_fund_fee.rs | 806 +++++++ .../instructions/collect_protocol_fee.rs | 810 +++++++ .../instructions/create_amm_config.rs | 484 ++++ .../src/generated/instructions/deposit.rs | 850 +++++++ .../src/generated/instructions/initialize.rs | 1177 +++++++++ .../src/generated/instructions/mod.rs | 28 + .../generated/instructions/swap_base_input.rs | 853 +++++++ .../instructions/swap_base_output.rs | 853 +++++++ .../instructions/update_amm_config.rs | 370 +++ .../instructions/update_pool_status.rs | 349 +++ .../src/generated/instructions/withdraw.rs | 897 +++++++ e2e/raydium-cpmm/src/generated/mod.rs | 15 + e2e/raydium-cpmm/src/generated/programs.rs | 11 + e2e/raydium-cpmm/src/generated/shared.rs | 21 + e2e/raydium-cpmm/src/generated/types/mod.rs | 10 + .../src/generated/types/observation.rs | 20 + e2e/raydium-cpmm/src/lib.rs | 4 + e2e/test.sh | 3 +- 27 files changed, 10257 insertions(+), 1 deletion(-) create mode 100644 e2e/raydium-cpmm/Cargo.toml create mode 100644 e2e/raydium-cpmm/idl.json create mode 100644 e2e/raydium-cpmm/src/generated/accounts/amm_config.rs create mode 100644 e2e/raydium-cpmm/src/generated/accounts/mod.rs create mode 100644 e2e/raydium-cpmm/src/generated/accounts/observation_state.rs create mode 100644 e2e/raydium-cpmm/src/generated/accounts/pool_state.rs create mode 100644 e2e/raydium-cpmm/src/generated/errors/mod.rs create mode 100644 e2e/raydium-cpmm/src/generated/errors/raydium_cp_swap.rs create mode 100644 e2e/raydium-cpmm/src/generated/instructions/collect_fund_fee.rs create mode 100644 e2e/raydium-cpmm/src/generated/instructions/collect_protocol_fee.rs create mode 100644 e2e/raydium-cpmm/src/generated/instructions/create_amm_config.rs create mode 100644 e2e/raydium-cpmm/src/generated/instructions/deposit.rs create mode 100644 e2e/raydium-cpmm/src/generated/instructions/initialize.rs create mode 100644 e2e/raydium-cpmm/src/generated/instructions/mod.rs create mode 100644 e2e/raydium-cpmm/src/generated/instructions/swap_base_input.rs create mode 100644 e2e/raydium-cpmm/src/generated/instructions/swap_base_output.rs create mode 100644 e2e/raydium-cpmm/src/generated/instructions/update_amm_config.rs create mode 100644 e2e/raydium-cpmm/src/generated/instructions/update_pool_status.rs create mode 100644 e2e/raydium-cpmm/src/generated/instructions/withdraw.rs create mode 100644 e2e/raydium-cpmm/src/generated/mod.rs create mode 100644 e2e/raydium-cpmm/src/generated/programs.rs create mode 100644 e2e/raydium-cpmm/src/generated/shared.rs create mode 100644 e2e/raydium-cpmm/src/generated/types/mod.rs create mode 100644 e2e/raydium-cpmm/src/generated/types/observation.rs create mode 100644 e2e/raydium-cpmm/src/lib.rs diff --git a/Cargo.lock b/Cargo.lock index da4d9bb..ff5c422 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -753,6 +753,24 @@ dependencies = [ "thiserror 1.0.69", ] +[[package]] +name = "codama-renderers-rust-e2e-raydium-cpmm" +version = "0.0.0" +dependencies = [ + "anchor-lang", + "borsh 1.5.7", + "num-derive", + "num-traits", + "solana-account 3.0.0", + "solana-account-info 3.1.0", + "solana-address 2.2.0", + "solana-client", + "solana-cpi 3.1.0", + "solana-instruction 3.2.0", + "solana-program-error 3.0.0", + "thiserror 1.0.69", +] + [[package]] name = "codama-renderers-rust-e2e-system" version = "0.0.0" diff --git a/e2e/raydium-cpmm/Cargo.toml b/e2e/raydium-cpmm/Cargo.toml new file mode 100644 index 0000000..d1b615d --- /dev/null +++ b/e2e/raydium-cpmm/Cargo.toml @@ -0,0 +1,24 @@ +[package] +name = "codama-renderers-rust-e2e-raydium-cpmm" +version = "0.0.0" +edition = "2021" + +[features] +anchor = ["dep:anchor-lang"] +anchor-idl-build = ["anchor", "anchor-lang?/idl-build"] +test-sbf = [] +fetch = ["dep:solana-client"] + +[dependencies] +anchor-lang = { workspace = true, optional = true } +borsh = { workspace = true } +num-derive = { workspace = true } +num-traits = { workspace = true } +solana-account = { workspace = true } +solana-account-info = { workspace = true } +solana-address = { workspace = true, features = ["borsh", "copy", "curve25519", "decode"] } +solana-client = { workspace = true, optional = true } +solana-cpi = { workspace = true } +solana-instruction = { workspace = true } +solana-program-error = { workspace = true } +thiserror = { workspace = true } diff --git a/e2e/raydium-cpmm/idl.json b/e2e/raydium-cpmm/idl.json new file mode 100644 index 0000000..5a93905 --- /dev/null +++ b/e2e/raydium-cpmm/idl.json @@ -0,0 +1,2115 @@ +{ + "address": "CPMMoo8L3F4NbTegBCKVNunggL7H1ZpdTHKxQB5qKP1C", + "metadata": { + "name": "raydium_cp_swap", + "version": "0.2.0", + "spec": "0.1.0", + "description": "Raydium constant product AMM, supports Token2022 and without Openbook" + }, + "instructions": [ + { + "name": "collect_fund_fee", + "docs": [ + "Collect the fund fee accrued to the pool", + "", + "# Arguments", + "", + "* `ctx` - The context of accounts", + "* `amount_0_requested` - The maximum amount of token_0 to send, can be 0 to collect fees in only token_1", + "* `amount_1_requested` - The maximum amount of token_1 to send, can be 0 to collect fees in only token_0", + "" + ], + "discriminator": [ + 167, + 138, + 78, + 149, + 223, + 194, + 6, + 126 + ], + "accounts": [ + { + "name": "owner", + "docs": [ + "Only admin or fund_owner can collect fee now" + ], + "signer": true + }, + { + "name": "authority", + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 118, + 97, + 117, + 108, + 116, + 95, + 97, + 110, + 100, + 95, + 108, + 112, + 95, + 109, + 105, + 110, + 116, + 95, + 97, + 117, + 116, + 104, + 95, + 115, + 101, + 101, + 100 + ] + } + ] + } + }, + { + "name": "pool_state", + "docs": [ + "Pool state stores accumulated protocol fee amount" + ], + "writable": true + }, + { + "name": "amm_config", + "docs": [ + "Amm config account stores fund_owner" + ] + }, + { + "name": "token_0_vault", + "docs": [ + "The address that holds pool tokens for token_0" + ], + "writable": true + }, + { + "name": "token_1_vault", + "docs": [ + "The address that holds pool tokens for token_1" + ], + "writable": true + }, + { + "name": "vault_0_mint", + "docs": [ + "The mint of token_0 vault" + ] + }, + { + "name": "vault_1_mint", + "docs": [ + "The mint of token_1 vault" + ] + }, + { + "name": "recipient_token_0_account", + "docs": [ + "The address that receives the collected token_0 fund fees" + ], + "writable": true + }, + { + "name": "recipient_token_1_account", + "docs": [ + "The address that receives the collected token_1 fund fees" + ], + "writable": true + }, + { + "name": "token_program", + "docs": [ + "The SPL program to perform token transfers" + ], + "address": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA" + }, + { + "name": "token_program_2022", + "docs": [ + "The SPL program 2022 to perform token transfers" + ], + "address": "TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb" + } + ], + "args": [ + { + "name": "amount_0_requested", + "type": "u64" + }, + { + "name": "amount_1_requested", + "type": "u64" + } + ] + }, + { + "name": "collect_protocol_fee", + "docs": [ + "Collect the protocol fee accrued to the pool", + "", + "# Arguments", + "", + "* `ctx` - The context of accounts", + "* `amount_0_requested` - The maximum amount of token_0 to send, can be 0 to collect fees in only token_1", + "* `amount_1_requested` - The maximum amount of token_1 to send, can be 0 to collect fees in only token_0", + "" + ], + "discriminator": [ + 136, + 136, + 252, + 221, + 194, + 66, + 126, + 89 + ], + "accounts": [ + { + "name": "owner", + "docs": [ + "Only admin or owner can collect fee now" + ], + "signer": true + }, + { + "name": "authority", + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 118, + 97, + 117, + 108, + 116, + 95, + 97, + 110, + 100, + 95, + 108, + 112, + 95, + 109, + 105, + 110, + 116, + 95, + 97, + 117, + 116, + 104, + 95, + 115, + 101, + 101, + 100 + ] + } + ] + } + }, + { + "name": "pool_state", + "docs": [ + "Pool state stores accumulated protocol fee amount" + ], + "writable": true + }, + { + "name": "amm_config", + "docs": [ + "Amm config account stores owner" + ] + }, + { + "name": "token_0_vault", + "docs": [ + "The address that holds pool tokens for token_0" + ], + "writable": true + }, + { + "name": "token_1_vault", + "docs": [ + "The address that holds pool tokens for token_1" + ], + "writable": true + }, + { + "name": "vault_0_mint", + "docs": [ + "The mint of token_0 vault" + ] + }, + { + "name": "vault_1_mint", + "docs": [ + "The mint of token_1 vault" + ] + }, + { + "name": "recipient_token_0_account", + "docs": [ + "The address that receives the collected token_0 protocol fees" + ], + "writable": true + }, + { + "name": "recipient_token_1_account", + "docs": [ + "The address that receives the collected token_1 protocol fees" + ], + "writable": true + }, + { + "name": "token_program", + "docs": [ + "The SPL program to perform token transfers" + ], + "address": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA" + }, + { + "name": "token_program_2022", + "docs": [ + "The SPL program 2022 to perform token transfers" + ], + "address": "TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb" + } + ], + "args": [ + { + "name": "amount_0_requested", + "type": "u64" + }, + { + "name": "amount_1_requested", + "type": "u64" + } + ] + }, + { + "name": "create_amm_config", + "docs": [ + "# Arguments", + "", + "* `ctx`- The accounts needed by instruction.", + "* `index` - The index of amm config, there may be multiple config.", + "* `trade_fee_rate` - Trade fee rate, can be changed.", + "* `protocol_fee_rate` - The rate of protocol fee within trade fee.", + "* `fund_fee_rate` - The rate of fund fee within trade fee.", + "" + ], + "discriminator": [ + 137, + 52, + 237, + 212, + 215, + 117, + 108, + 104 + ], + "accounts": [ + { + "name": "owner", + "docs": [ + "Address to be set as protocol owner." + ], + "writable": true, + "signer": true, + "address": "GThUX1Atko4tqhN2NaiTazWSeFWMuiUvfFnyJyUghFMJ" + }, + { + "name": "amm_config", + "docs": [ + "Initialize config state account to store protocol owner address and fee rates." + ], + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 97, + 109, + 109, + 95, + 99, + 111, + 110, + 102, + 105, + 103 + ] + }, + { + "kind": "arg", + "path": "index" + } + ] + } + }, + { + "name": "system_program", + "address": "11111111111111111111111111111111" + } + ], + "args": [ + { + "name": "index", + "type": "u16" + }, + { + "name": "trade_fee_rate", + "type": "u64" + }, + { + "name": "protocol_fee_rate", + "type": "u64" + }, + { + "name": "fund_fee_rate", + "type": "u64" + }, + { + "name": "create_pool_fee", + "type": "u64" + } + ] + }, + { + "name": "deposit", + "docs": [ + "Deposit lp token to the pool", + "", + "# Arguments", + "", + "* `ctx`- The context of accounts", + "* `lp_token_amount` - Pool token amount to transfer. token_a and token_b amount are set by the current exchange rate and size of the pool", + "* `maximum_token_0_amount` - Maximum token 0 amount to deposit, prevents excessive slippage", + "* `maximum_token_1_amount` - Maximum token 1 amount to deposit, prevents excessive slippage", + "" + ], + "discriminator": [ + 242, + 35, + 198, + 137, + 82, + 225, + 242, + 182 + ], + "accounts": [ + { + "name": "owner", + "docs": [ + "Pays to mint the position" + ], + "signer": true + }, + { + "name": "authority", + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 118, + 97, + 117, + 108, + 116, + 95, + 97, + 110, + 100, + 95, + 108, + 112, + 95, + 109, + 105, + 110, + 116, + 95, + 97, + 117, + 116, + 104, + 95, + 115, + 101, + 101, + 100 + ] + } + ] + } + }, + { + "name": "pool_state", + "writable": true + }, + { + "name": "owner_lp_token", + "docs": [ + "Owner lp token account" + ], + "writable": true + }, + { + "name": "token_0_account", + "docs": [ + "The payer's token account for token_0" + ], + "writable": true + }, + { + "name": "token_1_account", + "docs": [ + "The payer's token account for token_1" + ], + "writable": true + }, + { + "name": "token_0_vault", + "docs": [ + "The address that holds pool tokens for token_0" + ], + "writable": true + }, + { + "name": "token_1_vault", + "docs": [ + "The address that holds pool tokens for token_1" + ], + "writable": true + }, + { + "name": "token_program", + "docs": [ + "token Program" + ], + "address": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA" + }, + { + "name": "token_program_2022", + "docs": [ + "Token program 2022" + ], + "address": "TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb" + }, + { + "name": "vault_0_mint", + "docs": [ + "The mint of token_0 vault" + ] + }, + { + "name": "vault_1_mint", + "docs": [ + "The mint of token_1 vault" + ] + }, + { + "name": "lp_mint", + "docs": [ + "Lp token mint" + ], + "writable": true + } + ], + "args": [ + { + "name": "lp_token_amount", + "type": "u64" + }, + { + "name": "maximum_token_0_amount", + "type": "u64" + }, + { + "name": "maximum_token_1_amount", + "type": "u64" + } + ] + }, + { + "name": "initialize", + "docs": [ + "Creates a pool for the given token pair and the initial price", + "", + "# Arguments", + "", + "* `ctx`- The context of accounts", + "* `init_amount_0` - the initial amount_0 to deposit", + "* `init_amount_1` - the initial amount_1 to deposit", + "* `open_time` - the timestamp allowed for swap", + "" + ], + "discriminator": [ + 175, + 175, + 109, + 31, + 13, + 152, + 155, + 237 + ], + "accounts": [ + { + "name": "creator", + "docs": [ + "Address paying to create the pool. Can be anyone" + ], + "writable": true, + "signer": true + }, + { + "name": "amm_config", + "docs": [ + "Which config the pool belongs to." + ] + }, + { + "name": "authority", + "docs": [ + "pool vault and lp mint authority" + ], + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 118, + 97, + 117, + 108, + 116, + 95, + 97, + 110, + 100, + 95, + 108, + 112, + 95, + 109, + 105, + 110, + 116, + 95, + 97, + 117, + 116, + 104, + 95, + 115, + 101, + 101, + 100 + ] + } + ] + } + }, + { + "name": "pool_state", + "docs": [ + "PDA account:", + "seeds = [", + "POOL_SEED.as_bytes(),", + "amm_config.key().as_ref(),", + "token_0_mint.key().as_ref(),", + "token_1_mint.key().as_ref(),", + "],", + "", + "Or random account: must be signed by cli" + ], + "writable": true + }, + { + "name": "token_0_mint", + "docs": [ + "Token_0 mint, the key must smaller than token_1 mint." + ] + }, + { + "name": "token_1_mint", + "docs": [ + "Token_1 mint, the key must grater then token_0 mint." + ] + }, + { + "name": "lp_mint", + "docs": [ + "pool lp mint" + ], + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 112, + 111, + 111, + 108, + 95, + 108, + 112, + 95, + 109, + 105, + 110, + 116 + ] + }, + { + "kind": "account", + "path": "pool_state" + } + ] + } + }, + { + "name": "creator_token_0", + "docs": [ + "payer token0 account" + ], + "writable": true + }, + { + "name": "creator_token_1", + "docs": [ + "creator token1 account" + ], + "writable": true + }, + { + "name": "creator_lp_token", + "docs": [ + "creator lp token account" + ], + "writable": true, + "pda": { + "seeds": [ + { + "kind": "account", + "path": "creator" + }, + { + "kind": "const", + "value": [ + 6, + 221, + 246, + 225, + 215, + 101, + 161, + 147, + 217, + 203, + 225, + 70, + 206, + 235, + 121, + 172, + 28, + 180, + 133, + 237, + 95, + 91, + 55, + 145, + 58, + 140, + 245, + 133, + 126, + 255, + 0, + 169 + ] + }, + { + "kind": "account", + "path": "lp_mint" + } + ], + "program": { + "kind": "const", + "value": [ + 140, + 151, + 37, + 143, + 78, + 36, + 137, + 241, + 187, + 61, + 16, + 41, + 20, + 142, + 13, + 131, + 11, + 90, + 19, + 153, + 218, + 255, + 16, + 132, + 4, + 142, + 123, + 216, + 219, + 233, + 248, + 89 + ] + } + } + }, + { + "name": "token_0_vault", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 112, + 111, + 111, + 108, + 95, + 118, + 97, + 117, + 108, + 116 + ] + }, + { + "kind": "account", + "path": "pool_state" + }, + { + "kind": "account", + "path": "token_0_mint" + } + ] + } + }, + { + "name": "token_1_vault", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 112, + 111, + 111, + 108, + 95, + 118, + 97, + 117, + 108, + 116 + ] + }, + { + "kind": "account", + "path": "pool_state" + }, + { + "kind": "account", + "path": "token_1_mint" + } + ] + } + }, + { + "name": "create_pool_fee", + "docs": [ + "create pool fee account" + ], + "writable": true, + "address": "DNXgeM9EiiaAbaWvwjHj9fQQLAX5ZsfHyvmYUNRAdNC8" + }, + { + "name": "observation_state", + "docs": [ + "an account to store oracle observations" + ], + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 111, + 98, + 115, + 101, + 114, + 118, + 97, + 116, + 105, + 111, + 110 + ] + }, + { + "kind": "account", + "path": "pool_state" + } + ] + } + }, + { + "name": "token_program", + "docs": [ + "Program to create mint account and mint tokens" + ], + "address": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA" + }, + { + "name": "token_0_program", + "docs": [ + "Spl token program or token program 2022" + ] + }, + { + "name": "token_1_program", + "docs": [ + "Spl token program or token program 2022" + ] + }, + { + "name": "associated_token_program", + "docs": [ + "Program to create an ATA for receiving position NFT" + ], + "address": "ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL" + }, + { + "name": "system_program", + "docs": [ + "To create a new program account" + ], + "address": "11111111111111111111111111111111" + }, + { + "name": "rent", + "docs": [ + "Sysvar for program account" + ], + "address": "SysvarRent111111111111111111111111111111111" + } + ], + "args": [ + { + "name": "init_amount_0", + "type": "u64" + }, + { + "name": "init_amount_1", + "type": "u64" + }, + { + "name": "open_time", + "type": "u64" + } + ] + }, + { + "name": "swap_base_input", + "docs": [ + "Swap the tokens in the pool base input amount", + "", + "# Arguments", + "", + "* `ctx`- The context of accounts", + "* `amount_in` - input amount to transfer, output to DESTINATION is based on the exchange rate", + "* `minimum_amount_out` - Minimum amount of output token, prevents excessive slippage", + "" + ], + "discriminator": [ + 143, + 190, + 90, + 218, + 196, + 30, + 51, + 222 + ], + "accounts": [ + { + "name": "payer", + "docs": [ + "The user performing the swap" + ], + "signer": true + }, + { + "name": "authority", + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 118, + 97, + 117, + 108, + 116, + 95, + 97, + 110, + 100, + 95, + 108, + 112, + 95, + 109, + 105, + 110, + 116, + 95, + 97, + 117, + 116, + 104, + 95, + 115, + 101, + 101, + 100 + ] + } + ] + } + }, + { + "name": "amm_config", + "docs": [ + "The factory state to read protocol fees" + ] + }, + { + "name": "pool_state", + "docs": [ + "The program account of the pool in which the swap will be performed" + ], + "writable": true + }, + { + "name": "input_token_account", + "docs": [ + "The user token account for input token" + ], + "writable": true + }, + { + "name": "output_token_account", + "docs": [ + "The user token account for output token" + ], + "writable": true + }, + { + "name": "input_vault", + "docs": [ + "The vault token account for input token" + ], + "writable": true + }, + { + "name": "output_vault", + "docs": [ + "The vault token account for output token" + ], + "writable": true + }, + { + "name": "input_token_program", + "docs": [ + "SPL program for input token transfers" + ] + }, + { + "name": "output_token_program", + "docs": [ + "SPL program for output token transfers" + ] + }, + { + "name": "input_token_mint", + "docs": [ + "The mint of input token" + ] + }, + { + "name": "output_token_mint", + "docs": [ + "The mint of output token" + ] + }, + { + "name": "observation_state", + "docs": [ + "The program account for the most recent oracle observation" + ], + "writable": true + } + ], + "args": [ + { + "name": "amount_in", + "type": "u64" + }, + { + "name": "minimum_amount_out", + "type": "u64" + } + ] + }, + { + "name": "swap_base_output", + "docs": [ + "Swap the tokens in the pool base output amount", + "", + "# Arguments", + "", + "* `ctx`- The context of accounts", + "* `max_amount_in` - input amount prevents excessive slippage", + "* `amount_out` - amount of output token", + "" + ], + "discriminator": [ + 55, + 217, + 98, + 86, + 163, + 74, + 180, + 173 + ], + "accounts": [ + { + "name": "payer", + "docs": [ + "The user performing the swap" + ], + "signer": true + }, + { + "name": "authority", + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 118, + 97, + 117, + 108, + 116, + 95, + 97, + 110, + 100, + 95, + 108, + 112, + 95, + 109, + 105, + 110, + 116, + 95, + 97, + 117, + 116, + 104, + 95, + 115, + 101, + 101, + 100 + ] + } + ] + } + }, + { + "name": "amm_config", + "docs": [ + "The factory state to read protocol fees" + ] + }, + { + "name": "pool_state", + "docs": [ + "The program account of the pool in which the swap will be performed" + ], + "writable": true + }, + { + "name": "input_token_account", + "docs": [ + "The user token account for input token" + ], + "writable": true + }, + { + "name": "output_token_account", + "docs": [ + "The user token account for output token" + ], + "writable": true + }, + { + "name": "input_vault", + "docs": [ + "The vault token account for input token" + ], + "writable": true + }, + { + "name": "output_vault", + "docs": [ + "The vault token account for output token" + ], + "writable": true + }, + { + "name": "input_token_program", + "docs": [ + "SPL program for input token transfers" + ] + }, + { + "name": "output_token_program", + "docs": [ + "SPL program for output token transfers" + ] + }, + { + "name": "input_token_mint", + "docs": [ + "The mint of input token" + ] + }, + { + "name": "output_token_mint", + "docs": [ + "The mint of output token" + ] + }, + { + "name": "observation_state", + "docs": [ + "The program account for the most recent oracle observation" + ], + "writable": true + } + ], + "args": [ + { + "name": "max_amount_in", + "type": "u64" + }, + { + "name": "amount_out", + "type": "u64" + } + ] + }, + { + "name": "update_amm_config", + "docs": [ + "Updates the owner of the amm config", + "Must be called by the current owner or admin", + "", + "# Arguments", + "", + "* `ctx`- The context of accounts", + "* `trade_fee_rate`- The new trade fee rate of amm config, be set when `param` is 0", + "* `protocol_fee_rate`- The new protocol fee rate of amm config, be set when `param` is 1", + "* `fund_fee_rate`- The new fund fee rate of amm config, be set when `param` is 2", + "* `new_owner`- The config's new owner, be set when `param` is 3", + "* `new_fund_owner`- The config's new fund owner, be set when `param` is 4", + "* `param`- The value can be 0 | 1 | 2 | 3 | 4, otherwise will report a error", + "" + ], + "discriminator": [ + 49, + 60, + 174, + 136, + 154, + 28, + 116, + 200 + ], + "accounts": [ + { + "name": "owner", + "docs": [ + "The amm config owner or admin" + ], + "signer": true, + "address": "GThUX1Atko4tqhN2NaiTazWSeFWMuiUvfFnyJyUghFMJ" + }, + { + "name": "amm_config", + "docs": [ + "Amm config account to be changed" + ], + "writable": true + } + ], + "args": [ + { + "name": "param", + "type": "u8" + }, + { + "name": "value", + "type": "u64" + } + ] + }, + { + "name": "update_pool_status", + "docs": [ + "Update pool status for given value", + "", + "# Arguments", + "", + "* `ctx`- The context of accounts", + "* `status` - The value of status", + "" + ], + "discriminator": [ + 130, + 87, + 108, + 6, + 46, + 224, + 117, + 123 + ], + "accounts": [ + { + "name": "authority", + "signer": true, + "address": "GThUX1Atko4tqhN2NaiTazWSeFWMuiUvfFnyJyUghFMJ" + }, + { + "name": "pool_state", + "writable": true + } + ], + "args": [ + { + "name": "status", + "type": "u8" + } + ] + }, + { + "name": "withdraw", + "docs": [ + "Withdraw lp for token0 and token1", + "", + "# Arguments", + "", + "* `ctx`- The context of accounts", + "* `lp_token_amount` - Amount of pool tokens to burn. User receives an output of token a and b based on the percentage of the pool tokens that are returned.", + "* `minimum_token_0_amount` - Minimum amount of token 0 to receive, prevents excessive slippage", + "* `minimum_token_1_amount` - Minimum amount of token 1 to receive, prevents excessive slippage", + "" + ], + "discriminator": [ + 183, + 18, + 70, + 156, + 148, + 109, + 161, + 34 + ], + "accounts": [ + { + "name": "owner", + "docs": [ + "Pays to mint the position" + ], + "signer": true + }, + { + "name": "authority", + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 118, + 97, + 117, + 108, + 116, + 95, + 97, + 110, + 100, + 95, + 108, + 112, + 95, + 109, + 105, + 110, + 116, + 95, + 97, + 117, + 116, + 104, + 95, + 115, + 101, + 101, + 100 + ] + } + ] + } + }, + { + "name": "pool_state", + "docs": [ + "Pool state account" + ], + "writable": true + }, + { + "name": "owner_lp_token", + "docs": [ + "Owner lp token account" + ], + "writable": true + }, + { + "name": "token_0_account", + "docs": [ + "The token account for receive token_0," + ], + "writable": true + }, + { + "name": "token_1_account", + "docs": [ + "The token account for receive token_1" + ], + "writable": true + }, + { + "name": "token_0_vault", + "docs": [ + "The address that holds pool tokens for token_0" + ], + "writable": true + }, + { + "name": "token_1_vault", + "docs": [ + "The address that holds pool tokens for token_1" + ], + "writable": true + }, + { + "name": "token_program", + "docs": [ + "token Program" + ], + "address": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA" + }, + { + "name": "token_program_2022", + "docs": [ + "Token program 2022" + ], + "address": "TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb" + }, + { + "name": "vault_0_mint", + "docs": [ + "The mint of token_0 vault" + ] + }, + { + "name": "vault_1_mint", + "docs": [ + "The mint of token_1 vault" + ] + }, + { + "name": "lp_mint", + "docs": [ + "Pool lp token mint" + ], + "writable": true + }, + { + "name": "memo_program", + "docs": [ + "memo program" + ], + "address": "MemoSq4gqABAXKb96qnH8TysNcWxMyWCqXgDLGmfcHr" + } + ], + "args": [ + { + "name": "lp_token_amount", + "type": "u64" + }, + { + "name": "minimum_token_0_amount", + "type": "u64" + }, + { + "name": "minimum_token_1_amount", + "type": "u64" + } + ] + } + ], + "accounts": [ + { + "name": "AmmConfig", + "discriminator": [ + 218, + 244, + 33, + 104, + 203, + 203, + 43, + 111 + ] + }, + { + "name": "ObservationState", + "discriminator": [ + 122, + 174, + 197, + 53, + 129, + 9, + 165, + 132 + ] + }, + { + "name": "PoolState", + "discriminator": [ + 247, + 237, + 227, + 245, + 215, + 195, + 222, + 70 + ] + } + ], + "events": [ + { + "name": "LpChangeEvent", + "discriminator": [ + 121, + 163, + 205, + 201, + 57, + 218, + 117, + 60 + ] + }, + { + "name": "SwapEvent", + "discriminator": [ + 64, + 198, + 205, + 232, + 38, + 8, + 113, + 226 + ] + } + ], + "errors": [ + { + "code": 6000, + "name": "NotApproved", + "msg": "Not approved" + }, + { + "code": 6001, + "name": "InvalidOwner", + "msg": "Input account owner is not the program address" + }, + { + "code": 6002, + "name": "EmptySupply", + "msg": "Input token account empty" + }, + { + "code": 6003, + "name": "InvalidInput", + "msg": "InvalidInput" + }, + { + "code": 6004, + "name": "IncorrectLpMint", + "msg": "Address of the provided lp token mint is incorrect" + }, + { + "code": 6005, + "name": "ExceededSlippage", + "msg": "Exceeds desired slippage limit" + }, + { + "code": 6006, + "name": "ZeroTradingTokens", + "msg": "Given pool token amount results in zero trading tokens" + }, + { + "code": 6007, + "name": "NotSupportMint", + "msg": "Not support token_2022 mint extension" + }, + { + "code": 6008, + "name": "InvalidVault", + "msg": "invaild vault" + }, + { + "code": 6009, + "name": "InitLpAmountTooLess", + "msg": "Init lp amount is too less(Because 100 amount lp will be locked)" + }, + { + "code": 6010, + "name": "TransferFeeCalculateNotMatch", + "msg": "TransferFee calculate not match" + } + ], + "types": [ + { + "name": "AmmConfig", + "docs": [ + "Holds the current owner of the factory" + ], + "type": { + "kind": "struct", + "fields": [ + { + "name": "bump", + "docs": [ + "Bump to identify PDA" + ], + "type": "u8" + }, + { + "name": "disable_create_pool", + "docs": [ + "Status to control if new pool can be create" + ], + "type": "bool" + }, + { + "name": "index", + "docs": [ + "Config index" + ], + "type": "u16" + }, + { + "name": "trade_fee_rate", + "docs": [ + "The trade fee, denominated in hundredths of a bip (10^-6)" + ], + "type": "u64" + }, + { + "name": "protocol_fee_rate", + "docs": [ + "The protocol fee" + ], + "type": "u64" + }, + { + "name": "fund_fee_rate", + "docs": [ + "The fund fee, denominated in hundredths of a bip (10^-6)" + ], + "type": "u64" + }, + { + "name": "create_pool_fee", + "docs": [ + "Fee for create a new pool" + ], + "type": "u64" + }, + { + "name": "protocol_owner", + "docs": [ + "Address of the protocol fee owner" + ], + "type": "pubkey" + }, + { + "name": "fund_owner", + "docs": [ + "Address of the fund fee owner" + ], + "type": "pubkey" + }, + { + "name": "padding", + "docs": [ + "padding" + ], + "type": { + "array": [ + "u64", + 16 + ] + } + } + ] + } + }, + { + "name": "LpChangeEvent", + "docs": [ + "Emitted when deposit and withdraw" + ], + "type": { + "kind": "struct", + "fields": [ + { + "name": "pool_id", + "type": "pubkey" + }, + { + "name": "lp_amount_before", + "type": "u64" + }, + { + "name": "token_0_vault_before", + "docs": [ + "pool vault sub trade fees" + ], + "type": "u64" + }, + { + "name": "token_1_vault_before", + "docs": [ + "pool vault sub trade fees" + ], + "type": "u64" + }, + { + "name": "token_0_amount", + "docs": [ + "calculate result without transfer fee" + ], + "type": "u64" + }, + { + "name": "token_1_amount", + "docs": [ + "calculate result without transfer fee" + ], + "type": "u64" + }, + { + "name": "token_0_transfer_fee", + "type": "u64" + }, + { + "name": "token_1_transfer_fee", + "type": "u64" + }, + { + "name": "change_type", + "type": "u8" + } + ] + } + }, + { + "name": "Observation", + "docs": [ + "The element of observations in ObservationState" + ], + "serialization": "bytemuckunsafe", + "repr": { + "kind": "c", + "packed": true + }, + "type": { + "kind": "struct", + "fields": [ + { + "name": "block_timestamp", + "docs": [ + "The block timestamp of the observation" + ], + "type": "u64" + }, + { + "name": "cumulative_token_0_price_x32", + "docs": [ + "the cumulative of token0 price during the duration time, Q32.32, the remaining 64 bit for overflow" + ], + "type": "u128" + }, + { + "name": "cumulative_token_1_price_x32", + "docs": [ + "the cumulative of token1 price during the duration time, Q32.32, the remaining 64 bit for overflow" + ], + "type": "u128" + } + ] + } + }, + { + "name": "ObservationState", + "serialization": "bytemuckunsafe", + "repr": { + "kind": "c", + "packed": true + }, + "type": { + "kind": "struct", + "fields": [ + { + "name": "initialized", + "docs": [ + "Whether the ObservationState is initialized" + ], + "type": "bool" + }, + { + "name": "observation_index", + "docs": [ + "the most-recently updated index of the observations array" + ], + "type": "u16" + }, + { + "name": "pool_id", + "type": "pubkey" + }, + { + "name": "observations", + "docs": [ + "observation array" + ], + "type": { + "array": [ + { + "defined": { + "name": "Observation" + } + }, + 100 + ] + } + }, + { + "name": "padding", + "docs": [ + "padding for feature update" + ], + "type": { + "array": [ + "u64", + 4 + ] + } + } + ] + } + }, + { + "name": "PoolState", + "serialization": "bytemuckunsafe", + "repr": { + "kind": "c", + "packed": true + }, + "type": { + "kind": "struct", + "fields": [ + { + "name": "amm_config", + "docs": [ + "Which config the pool belongs" + ], + "type": "pubkey" + }, + { + "name": "pool_creator", + "docs": [ + "pool creator" + ], + "type": "pubkey" + }, + { + "name": "token_0_vault", + "docs": [ + "Token A" + ], + "type": "pubkey" + }, + { + "name": "token_1_vault", + "docs": [ + "Token B" + ], + "type": "pubkey" + }, + { + "name": "lp_mint", + "docs": [ + "Pool tokens are issued when A or B tokens are deposited.", + "Pool tokens can be withdrawn back to the original A or B token." + ], + "type": "pubkey" + }, + { + "name": "token_0_mint", + "docs": [ + "Mint information for token A" + ], + "type": "pubkey" + }, + { + "name": "token_1_mint", + "docs": [ + "Mint information for token B" + ], + "type": "pubkey" + }, + { + "name": "token_0_program", + "docs": [ + "token_0 program" + ], + "type": "pubkey" + }, + { + "name": "token_1_program", + "docs": [ + "token_1 program" + ], + "type": "pubkey" + }, + { + "name": "observation_key", + "docs": [ + "observation account to store oracle data" + ], + "type": "pubkey" + }, + { + "name": "auth_bump", + "type": "u8" + }, + { + "name": "status", + "docs": [ + "Bitwise representation of the state of the pool", + "bit0, 1: disable deposit(value is 1), 0: normal", + "bit1, 1: disable withdraw(value is 2), 0: normal", + "bit2, 1: disable swap(value is 4), 0: normal" + ], + "type": "u8" + }, + { + "name": "lp_mint_decimals", + "type": "u8" + }, + { + "name": "mint_0_decimals", + "docs": [ + "mint0 and mint1 decimals" + ], + "type": "u8" + }, + { + "name": "mint_1_decimals", + "type": "u8" + }, + { + "name": "lp_supply", + "docs": [ + "True circulating supply without burns and lock ups" + ], + "type": "u64" + }, + { + "name": "protocol_fees_token_0", + "docs": [ + "The amounts of token_0 and token_1 that are owed to the liquidity provider." + ], + "type": "u64" + }, + { + "name": "protocol_fees_token_1", + "type": "u64" + }, + { + "name": "fund_fees_token_0", + "type": "u64" + }, + { + "name": "fund_fees_token_1", + "type": "u64" + }, + { + "name": "open_time", + "docs": [ + "The timestamp allowed for swap in the pool." + ], + "type": "u64" + }, + { + "name": "recent_epoch", + "docs": [ + "recent epoch" + ], + "type": "u64" + }, + { + "name": "padding", + "docs": [ + "padding for future updates" + ], + "type": { + "array": [ + "u64", + 31 + ] + } + } + ] + } + }, + { + "name": "SwapEvent", + "docs": [ + "Emitted when swap" + ], + "type": { + "kind": "struct", + "fields": [ + { + "name": "pool_id", + "type": "pubkey" + }, + { + "name": "input_vault_before", + "docs": [ + "pool vault sub trade fees" + ], + "type": "u64" + }, + { + "name": "output_vault_before", + "docs": [ + "pool vault sub trade fees" + ], + "type": "u64" + }, + { + "name": "input_amount", + "docs": [ + "calculate result without transfer fee" + ], + "type": "u64" + }, + { + "name": "output_amount", + "docs": [ + "calculate result without transfer fee" + ], + "type": "u64" + }, + { + "name": "input_transfer_fee", + "type": "u64" + }, + { + "name": "output_transfer_fee", + "type": "u64" + }, + { + "name": "base_input", + "type": "bool" + } + ] + } + } + ] +} \ No newline at end of file diff --git a/e2e/raydium-cpmm/src/generated/accounts/amm_config.rs b/e2e/raydium-cpmm/src/generated/accounts/amm_config.rs new file mode 100644 index 0000000..20d58d4 --- /dev/null +++ b/e2e/raydium-cpmm/src/generated/accounts/amm_config.rs @@ -0,0 +1,150 @@ +//! This code was AUTOGENERATED using the codama library. +//! Please DO NOT EDIT THIS FILE, instead use visitors +//! to add features, then rerun codama to update it. +//! +//! +//! + +use borsh::BorshDeserialize; +use borsh::BorshSerialize; +use solana_address::Address; + +#[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] +pub struct AmmConfig { + pub discriminator: [u8; 8], + /// Bump to identify PDA + pub bump: u8, + /// Status to control if new pool can be create + pub disable_create_pool: bool, + /// Config index + pub index: u16, + /// The trade fee, denominated in hundredths of a bip (10^-6) + pub trade_fee_rate: u64, + /// The protocol fee + pub protocol_fee_rate: u64, + /// The fund fee, denominated in hundredths of a bip (10^-6) + pub fund_fee_rate: u64, + /// Fee for create a new pool + pub create_pool_fee: u64, + /// Address of the protocol fee owner + pub protocol_owner: Address, + /// Address of the fund fee owner + pub fund_owner: Address, + /// padding + pub padding: [u64; 16], +} + +pub const AMM_CONFIG_DISCRIMINATOR: [u8; 8] = [218, 244, 33, 104, 203, 203, 43, 111]; + +impl AmmConfig { + pub const LEN: usize = 236; + + #[inline(always)] + pub fn from_bytes(data: &[u8]) -> Result { + let mut data = data; + Self::deserialize(&mut data) + } +} + +impl<'a> TryFrom<&solana_account_info::AccountInfo<'a>> for AmmConfig { + type Error = std::io::Error; + + fn try_from(account_info: &solana_account_info::AccountInfo<'a>) -> Result { + let mut data: &[u8] = &(*account_info.data).borrow(); + Self::deserialize(&mut data) + } +} + +#[cfg(feature = "fetch")] +pub fn fetch_amm_config( + rpc: &solana_client::rpc_client::RpcClient, + address: &solana_address::Address, +) -> Result, std::io::Error> { + let accounts = fetch_all_amm_config(rpc, &[*address])?; + Ok(accounts[0].clone()) +} + +#[cfg(feature = "fetch")] +pub fn fetch_all_amm_config( + rpc: &solana_client::rpc_client::RpcClient, + addresses: &[solana_address::Address], +) -> Result>, std::io::Error> { + let accounts = rpc + .get_multiple_accounts(addresses) + .map_err(|e| std::io::Error::other(e.to_string()))?; + let mut decoded_accounts: Vec> = Vec::new(); + for i in 0..addresses.len() { + let address = addresses[i]; + let account = accounts[i].as_ref().ok_or(std::io::Error::other(format!( + "Account not found: {address}" + )))?; + let data = AmmConfig::from_bytes(&account.data)?; + decoded_accounts.push(crate::shared::DecodedAccount { + address, + account: account.clone(), + data, + }); + } + Ok(decoded_accounts) +} + +#[cfg(feature = "fetch")] +pub fn fetch_maybe_amm_config( + rpc: &solana_client::rpc_client::RpcClient, + address: &solana_address::Address, +) -> Result, std::io::Error> { + let accounts = fetch_all_maybe_amm_config(rpc, &[*address])?; + Ok(accounts[0].clone()) +} + +#[cfg(feature = "fetch")] +pub fn fetch_all_maybe_amm_config( + rpc: &solana_client::rpc_client::RpcClient, + addresses: &[solana_address::Address], +) -> Result>, std::io::Error> { + let accounts = rpc + .get_multiple_accounts(addresses) + .map_err(|e| std::io::Error::other(e.to_string()))?; + let mut decoded_accounts: Vec> = Vec::new(); + for i in 0..addresses.len() { + let address = addresses[i]; + if let Some(account) = accounts[i].as_ref() { + let data = AmmConfig::from_bytes(&account.data)?; + decoded_accounts.push(crate::shared::MaybeAccount::Exists( + crate::shared::DecodedAccount { + address, + account: account.clone(), + data, + }, + )); + } else { + decoded_accounts.push(crate::shared::MaybeAccount::NotFound(address)); + } + } + Ok(decoded_accounts) +} + +#[cfg(feature = "anchor")] +impl anchor_lang::AccountDeserialize for AmmConfig { + fn try_deserialize_unchecked(buf: &mut &[u8]) -> anchor_lang::Result { + Ok(Self::deserialize(buf)?) + } +} + +#[cfg(feature = "anchor")] +impl anchor_lang::AccountSerialize for AmmConfig {} + +#[cfg(feature = "anchor")] +impl anchor_lang::Owner for AmmConfig { + fn owner() -> anchor_lang::solana_program::pubkey::Pubkey { + anchor_lang::solana_program::pubkey::Pubkey::from(crate::RAYDIUM_CP_SWAP_ID.to_bytes()) + } +} + +#[cfg(feature = "anchor-idl-build")] +impl anchor_lang::IdlBuild for AmmConfig {} + +#[cfg(feature = "anchor-idl-build")] +impl anchor_lang::Discriminator for AmmConfig { + const DISCRIMINATOR: &[u8] = &[0; 8]; +} diff --git a/e2e/raydium-cpmm/src/generated/accounts/mod.rs b/e2e/raydium-cpmm/src/generated/accounts/mod.rs new file mode 100644 index 0000000..8018f52 --- /dev/null +++ b/e2e/raydium-cpmm/src/generated/accounts/mod.rs @@ -0,0 +1,14 @@ +//! This code was AUTOGENERATED using the codama library. +//! Please DO NOT EDIT THIS FILE, instead use visitors +//! to add features, then rerun codama to update it. +//! +//! +//! + +pub(crate) mod r#amm_config; +pub(crate) mod r#observation_state; +pub(crate) mod r#pool_state; + +pub use self::r#amm_config::*; +pub use self::r#observation_state::*; +pub use self::r#pool_state::*; diff --git a/e2e/raydium-cpmm/src/generated/accounts/observation_state.rs b/e2e/raydium-cpmm/src/generated/accounts/observation_state.rs new file mode 100644 index 0000000..40742e8 --- /dev/null +++ b/e2e/raydium-cpmm/src/generated/accounts/observation_state.rs @@ -0,0 +1,140 @@ +//! This code was AUTOGENERATED using the codama library. +//! Please DO NOT EDIT THIS FILE, instead use visitors +//! to add features, then rerun codama to update it. +//! +//! +//! + +use crate::generated::types::Observation; +use borsh::BorshDeserialize; +use borsh::BorshSerialize; +use solana_address::Address; + +#[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] +pub struct ObservationState { + pub discriminator: [u8; 8], + /// Whether the ObservationState is initialized + pub initialized: bool, + /// the most-recently updated index of the observations array + pub observation_index: u16, + pub pool_id: Address, + /// observation array + pub observations: [Observation; 100], + /// padding for feature update + pub padding: [u64; 4], +} + +pub const OBSERVATION_STATE_DISCRIMINATOR: [u8; 8] = [122, 174, 197, 53, 129, 9, 165, 132]; + +impl ObservationState { + pub const LEN: usize = 4075; + + #[inline(always)] + pub fn from_bytes(data: &[u8]) -> Result { + let mut data = data; + Self::deserialize(&mut data) + } +} + +impl<'a> TryFrom<&solana_account_info::AccountInfo<'a>> for ObservationState { + type Error = std::io::Error; + + fn try_from(account_info: &solana_account_info::AccountInfo<'a>) -> Result { + let mut data: &[u8] = &(*account_info.data).borrow(); + Self::deserialize(&mut data) + } +} + +#[cfg(feature = "fetch")] +pub fn fetch_observation_state( + rpc: &solana_client::rpc_client::RpcClient, + address: &solana_address::Address, +) -> Result, std::io::Error> { + let accounts = fetch_all_observation_state(rpc, &[*address])?; + Ok(accounts[0].clone()) +} + +#[cfg(feature = "fetch")] +pub fn fetch_all_observation_state( + rpc: &solana_client::rpc_client::RpcClient, + addresses: &[solana_address::Address], +) -> Result>, std::io::Error> { + let accounts = rpc + .get_multiple_accounts(addresses) + .map_err(|e| std::io::Error::other(e.to_string()))?; + let mut decoded_accounts: Vec> = Vec::new(); + for i in 0..addresses.len() { + let address = addresses[i]; + let account = accounts[i].as_ref().ok_or(std::io::Error::other(format!( + "Account not found: {address}" + )))?; + let data = ObservationState::from_bytes(&account.data)?; + decoded_accounts.push(crate::shared::DecodedAccount { + address, + account: account.clone(), + data, + }); + } + Ok(decoded_accounts) +} + +#[cfg(feature = "fetch")] +pub fn fetch_maybe_observation_state( + rpc: &solana_client::rpc_client::RpcClient, + address: &solana_address::Address, +) -> Result, std::io::Error> { + let accounts = fetch_all_maybe_observation_state(rpc, &[*address])?; + Ok(accounts[0].clone()) +} + +#[cfg(feature = "fetch")] +pub fn fetch_all_maybe_observation_state( + rpc: &solana_client::rpc_client::RpcClient, + addresses: &[solana_address::Address], +) -> Result>, std::io::Error> { + let accounts = rpc + .get_multiple_accounts(addresses) + .map_err(|e| std::io::Error::other(e.to_string()))?; + let mut decoded_accounts: Vec> = Vec::new(); + for i in 0..addresses.len() { + let address = addresses[i]; + if let Some(account) = accounts[i].as_ref() { + let data = ObservationState::from_bytes(&account.data)?; + decoded_accounts.push(crate::shared::MaybeAccount::Exists( + crate::shared::DecodedAccount { + address, + account: account.clone(), + data, + }, + )); + } else { + decoded_accounts.push(crate::shared::MaybeAccount::NotFound(address)); + } + } + Ok(decoded_accounts) +} + +#[cfg(feature = "anchor")] +impl anchor_lang::AccountDeserialize for ObservationState { + fn try_deserialize_unchecked(buf: &mut &[u8]) -> anchor_lang::Result { + Ok(Self::deserialize(buf)?) + } +} + +#[cfg(feature = "anchor")] +impl anchor_lang::AccountSerialize for ObservationState {} + +#[cfg(feature = "anchor")] +impl anchor_lang::Owner for ObservationState { + fn owner() -> anchor_lang::solana_program::pubkey::Pubkey { + anchor_lang::solana_program::pubkey::Pubkey::from(crate::RAYDIUM_CP_SWAP_ID.to_bytes()) + } +} + +#[cfg(feature = "anchor-idl-build")] +impl anchor_lang::IdlBuild for ObservationState {} + +#[cfg(feature = "anchor-idl-build")] +impl anchor_lang::Discriminator for ObservationState { + const DISCRIMINATOR: &[u8] = &[0; 8]; +} diff --git a/e2e/raydium-cpmm/src/generated/accounts/pool_state.rs b/e2e/raydium-cpmm/src/generated/accounts/pool_state.rs new file mode 100644 index 0000000..f603489 --- /dev/null +++ b/e2e/raydium-cpmm/src/generated/accounts/pool_state.rs @@ -0,0 +1,174 @@ +//! This code was AUTOGENERATED using the codama library. +//! Please DO NOT EDIT THIS FILE, instead use visitors +//! to add features, then rerun codama to update it. +//! +//! +//! + +use borsh::BorshDeserialize; +use borsh::BorshSerialize; +use solana_address::Address; + +#[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] +pub struct PoolState { + pub discriminator: [u8; 8], + /// Which config the pool belongs + pub amm_config: Address, + /// pool creator + pub pool_creator: Address, + /// Token A + pub token0_vault: Address, + /// Token B + pub token1_vault: Address, + /// Pool tokens are issued when A or B tokens are deposited. + /// Pool tokens can be withdrawn back to the original A or B token. + pub lp_mint: Address, + /// Mint information for token A + pub token0_mint: Address, + /// Mint information for token B + pub token1_mint: Address, + /// token_0 program + pub token0_program: Address, + /// token_1 program + pub token1_program: Address, + /// observation account to store oracle data + pub observation_key: Address, + pub auth_bump: u8, + /// Bitwise representation of the state of the pool + /// bit0, 1: disable deposit(value is 1), 0: normal + /// bit1, 1: disable withdraw(value is 2), 0: normal + /// bit2, 1: disable swap(value is 4), 0: normal + pub status: u8, + pub lp_mint_decimals: u8, + /// mint0 and mint1 decimals + pub mint0_decimals: u8, + pub mint1_decimals: u8, + /// True circulating supply without burns and lock ups + pub lp_supply: u64, + /// The amounts of token_0 and token_1 that are owed to the liquidity provider. + pub protocol_fees_token0: u64, + pub protocol_fees_token1: u64, + pub fund_fees_token0: u64, + pub fund_fees_token1: u64, + /// The timestamp allowed for swap in the pool. + pub open_time: u64, + /// recent epoch + pub recent_epoch: u64, + /// padding for future updates + pub padding: [u64; 31], +} + +pub const POOL_STATE_DISCRIMINATOR: [u8; 8] = [247, 237, 227, 245, 215, 195, 222, 70]; + +impl PoolState { + pub const LEN: usize = 637; + + #[inline(always)] + pub fn from_bytes(data: &[u8]) -> Result { + let mut data = data; + Self::deserialize(&mut data) + } +} + +impl<'a> TryFrom<&solana_account_info::AccountInfo<'a>> for PoolState { + type Error = std::io::Error; + + fn try_from(account_info: &solana_account_info::AccountInfo<'a>) -> Result { + let mut data: &[u8] = &(*account_info.data).borrow(); + Self::deserialize(&mut data) + } +} + +#[cfg(feature = "fetch")] +pub fn fetch_pool_state( + rpc: &solana_client::rpc_client::RpcClient, + address: &solana_address::Address, +) -> Result, std::io::Error> { + let accounts = fetch_all_pool_state(rpc, &[*address])?; + Ok(accounts[0].clone()) +} + +#[cfg(feature = "fetch")] +pub fn fetch_all_pool_state( + rpc: &solana_client::rpc_client::RpcClient, + addresses: &[solana_address::Address], +) -> Result>, std::io::Error> { + let accounts = rpc + .get_multiple_accounts(addresses) + .map_err(|e| std::io::Error::other(e.to_string()))?; + let mut decoded_accounts: Vec> = Vec::new(); + for i in 0..addresses.len() { + let address = addresses[i]; + let account = accounts[i].as_ref().ok_or(std::io::Error::other(format!( + "Account not found: {address}" + )))?; + let data = PoolState::from_bytes(&account.data)?; + decoded_accounts.push(crate::shared::DecodedAccount { + address, + account: account.clone(), + data, + }); + } + Ok(decoded_accounts) +} + +#[cfg(feature = "fetch")] +pub fn fetch_maybe_pool_state( + rpc: &solana_client::rpc_client::RpcClient, + address: &solana_address::Address, +) -> Result, std::io::Error> { + let accounts = fetch_all_maybe_pool_state(rpc, &[*address])?; + Ok(accounts[0].clone()) +} + +#[cfg(feature = "fetch")] +pub fn fetch_all_maybe_pool_state( + rpc: &solana_client::rpc_client::RpcClient, + addresses: &[solana_address::Address], +) -> Result>, std::io::Error> { + let accounts = rpc + .get_multiple_accounts(addresses) + .map_err(|e| std::io::Error::other(e.to_string()))?; + let mut decoded_accounts: Vec> = Vec::new(); + for i in 0..addresses.len() { + let address = addresses[i]; + if let Some(account) = accounts[i].as_ref() { + let data = PoolState::from_bytes(&account.data)?; + decoded_accounts.push(crate::shared::MaybeAccount::Exists( + crate::shared::DecodedAccount { + address, + account: account.clone(), + data, + }, + )); + } else { + decoded_accounts.push(crate::shared::MaybeAccount::NotFound(address)); + } + } + Ok(decoded_accounts) +} + +#[cfg(feature = "anchor")] +impl anchor_lang::AccountDeserialize for PoolState { + fn try_deserialize_unchecked(buf: &mut &[u8]) -> anchor_lang::Result { + Ok(Self::deserialize(buf)?) + } +} + +#[cfg(feature = "anchor")] +impl anchor_lang::AccountSerialize for PoolState {} + +#[cfg(feature = "anchor")] +impl anchor_lang::Owner for PoolState { + fn owner() -> anchor_lang::solana_program::pubkey::Pubkey { + anchor_lang::solana_program::pubkey::Pubkey::from(crate::RAYDIUM_CP_SWAP_ID.to_bytes()) + } +} + +#[cfg(feature = "anchor-idl-build")] +impl anchor_lang::IdlBuild for PoolState {} + +#[cfg(feature = "anchor-idl-build")] +impl anchor_lang::Discriminator for PoolState { + const DISCRIMINATOR: &[u8] = &[0; 8]; +} diff --git a/e2e/raydium-cpmm/src/generated/errors/mod.rs b/e2e/raydium-cpmm/src/generated/errors/mod.rs new file mode 100644 index 0000000..164fee8 --- /dev/null +++ b/e2e/raydium-cpmm/src/generated/errors/mod.rs @@ -0,0 +1,10 @@ +//! This code was AUTOGENERATED using the codama library. +//! Please DO NOT EDIT THIS FILE, instead use visitors +//! to add features, then rerun codama to update it. +//! +//! +//! + +pub(crate) mod raydium_cp_swap; + +pub use self::raydium_cp_swap::RaydiumCpSwapError; diff --git a/e2e/raydium-cpmm/src/generated/errors/raydium_cp_swap.rs b/e2e/raydium-cpmm/src/generated/errors/raydium_cp_swap.rs new file mode 100644 index 0000000..33f3db2 --- /dev/null +++ b/e2e/raydium-cpmm/src/generated/errors/raydium_cp_swap.rs @@ -0,0 +1,52 @@ +//! This code was AUTOGENERATED using the codama library. +//! Please DO NOT EDIT THIS FILE, instead use visitors +//! to add features, then rerun codama to update it. +//! +//! +//! + +use num_derive::FromPrimitive; +use thiserror::Error; + +#[derive(Clone, Debug, Eq, Error, FromPrimitive, PartialEq)] +pub enum RaydiumCpSwapError { + /// 6000 - Not approved + #[error("Not approved")] + NotApproved = 0x1770, + /// 6001 - Input account owner is not the program address + #[error("Input account owner is not the program address")] + InvalidOwner = 0x1771, + /// 6002 - Input token account empty + #[error("Input token account empty")] + EmptySupply = 0x1772, + /// 6003 - InvalidInput + #[error("InvalidInput")] + InvalidInput = 0x1773, + /// 6004 - Address of the provided lp token mint is incorrect + #[error("Address of the provided lp token mint is incorrect")] + IncorrectLpMint = 0x1774, + /// 6005 - Exceeds desired slippage limit + #[error("Exceeds desired slippage limit")] + ExceededSlippage = 0x1775, + /// 6006 - Given pool token amount results in zero trading tokens + #[error("Given pool token amount results in zero trading tokens")] + ZeroTradingTokens = 0x1776, + /// 6007 - Not support token_2022 mint extension + #[error("Not support token_2022 mint extension")] + NotSupportMint = 0x1777, + /// 6008 - invaild vault + #[error("invaild vault")] + InvalidVault = 0x1778, + /// 6009 - Init lp amount is too less(Because 100 amount lp will be locked) + #[error("Init lp amount is too less(Because 100 amount lp will be locked)")] + InitLpAmountTooLess = 0x1779, + /// 6010 - TransferFee calculate not match + #[error("TransferFee calculate not match")] + TransferFeeCalculateNotMatch = 0x177A, +} + +impl From for solana_program_error::ProgramError { + fn from(e: RaydiumCpSwapError) -> Self { + solana_program_error::ProgramError::Custom(e as u32) + } +} diff --git a/e2e/raydium-cpmm/src/generated/instructions/collect_fund_fee.rs b/e2e/raydium-cpmm/src/generated/instructions/collect_fund_fee.rs new file mode 100644 index 0000000..a4c246a --- /dev/null +++ b/e2e/raydium-cpmm/src/generated/instructions/collect_fund_fee.rs @@ -0,0 +1,806 @@ +//! This code was AUTOGENERATED using the codama library. +//! Please DO NOT EDIT THIS FILE, instead use visitors +//! to add features, then rerun codama to update it. +//! +//! +//! + +use borsh::BorshDeserialize; +use borsh::BorshSerialize; + +pub const COLLECT_FUND_FEE_DISCRIMINATOR: [u8; 8] = [167, 138, 78, 149, 223, 194, 6, 126]; + +/// Accounts. +#[derive(Debug)] +pub struct CollectFundFee { + /// Only admin or fund_owner can collect fee now + pub owner: solana_address::Address, + + pub authority: solana_address::Address, + /// Pool state stores accumulated protocol fee amount + pub pool_state: solana_address::Address, + /// Amm config account stores fund_owner + pub amm_config: solana_address::Address, + /// The address that holds pool tokens for token_0 + pub token0_vault: solana_address::Address, + /// The address that holds pool tokens for token_1 + pub token1_vault: solana_address::Address, + /// The mint of token_0 vault + pub vault0_mint: solana_address::Address, + /// The mint of token_1 vault + pub vault1_mint: solana_address::Address, + /// The address that receives the collected token_0 fund fees + pub recipient_token0_account: solana_address::Address, + /// The address that receives the collected token_1 fund fees + pub recipient_token1_account: solana_address::Address, + /// The SPL program to perform token transfers + pub token_program: solana_address::Address, + /// The SPL program 2022 to perform token transfers + pub token_program2022: solana_address::Address, +} + +impl CollectFundFee { + pub fn instruction( + &self, + args: CollectFundFeeInstructionArgs, + ) -> solana_instruction::Instruction { + self.instruction_with_remaining_accounts(args, &[]) + } + #[allow(clippy::arithmetic_side_effects)] + #[allow(clippy::vec_init_then_push)] + pub fn instruction_with_remaining_accounts( + &self, + args: CollectFundFeeInstructionArgs, + remaining_accounts: &[solana_instruction::AccountMeta], + ) -> solana_instruction::Instruction { + let mut accounts = Vec::with_capacity(12 + remaining_accounts.len()); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.owner, true, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.authority, + false, + )); + accounts.push(solana_instruction::AccountMeta::new(self.pool_state, false)); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.amm_config, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + self.token0_vault, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + self.token1_vault, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.vault0_mint, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.vault1_mint, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + self.recipient_token0_account, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + self.recipient_token1_account, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.token_program, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.token_program2022, + false, + )); + accounts.extend_from_slice(remaining_accounts); + let mut data = CollectFundFeeInstructionData::new().try_to_vec().unwrap(); + let mut args = args.try_to_vec().unwrap(); + data.append(&mut args); + + solana_instruction::Instruction { + program_id: crate::RAYDIUM_CP_SWAP_ID, + accounts, + data, + } + } +} + +#[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] +pub struct CollectFundFeeInstructionData { + discriminator: [u8; 8], +} + +impl CollectFundFeeInstructionData { + pub fn new() -> Self { + Self { + discriminator: [167, 138, 78, 149, 223, 194, 6, 126], + } + } + + pub(crate) fn try_to_vec(&self) -> Result, std::io::Error> { + borsh::to_vec(self) + } +} + +impl Default for CollectFundFeeInstructionData { + fn default() -> Self { + Self::new() + } +} + +#[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] +pub struct CollectFundFeeInstructionArgs { + pub amount0_requested: u64, + pub amount1_requested: u64, +} + +impl CollectFundFeeInstructionArgs { + pub(crate) fn try_to_vec(&self) -> Result, std::io::Error> { + borsh::to_vec(self) + } +} + +/// Instruction builder for `CollectFundFee`. +/// +/// ### Accounts: +/// +/// 0. `[signer]` owner +/// 1. `[]` authority +/// 2. `[writable]` pool_state +/// 3. `[]` amm_config +/// 4. `[writable]` token0_vault +/// 5. `[writable]` token1_vault +/// 6. `[]` vault0_mint +/// 7. `[]` vault1_mint +/// 8. `[writable]` recipient_token0_account +/// 9. `[writable]` recipient_token1_account +/// 10. `[optional]` token_program (default to `TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA`) +/// 11. `[optional]` token_program2022 (default to `TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb`) +#[derive(Clone, Debug, Default)] +pub struct CollectFundFeeBuilder { + owner: Option, + authority: Option, + pool_state: Option, + amm_config: Option, + token0_vault: Option, + token1_vault: Option, + vault0_mint: Option, + vault1_mint: Option, + recipient_token0_account: Option, + recipient_token1_account: Option, + token_program: Option, + token_program2022: Option, + amount0_requested: Option, + amount1_requested: Option, + __remaining_accounts: Vec, +} + +impl CollectFundFeeBuilder { + pub fn new() -> Self { + Self::default() + } + /// Only admin or fund_owner can collect fee now + #[inline(always)] + pub fn owner(&mut self, owner: solana_address::Address) -> &mut Self { + self.owner = Some(owner); + self + } + #[inline(always)] + pub fn authority(&mut self, authority: solana_address::Address) -> &mut Self { + self.authority = Some(authority); + self + } + /// Pool state stores accumulated protocol fee amount + #[inline(always)] + pub fn pool_state(&mut self, pool_state: solana_address::Address) -> &mut Self { + self.pool_state = Some(pool_state); + self + } + /// Amm config account stores fund_owner + #[inline(always)] + pub fn amm_config(&mut self, amm_config: solana_address::Address) -> &mut Self { + self.amm_config = Some(amm_config); + self + } + /// The address that holds pool tokens for token_0 + #[inline(always)] + pub fn token0_vault(&mut self, token0_vault: solana_address::Address) -> &mut Self { + self.token0_vault = Some(token0_vault); + self + } + /// The address that holds pool tokens for token_1 + #[inline(always)] + pub fn token1_vault(&mut self, token1_vault: solana_address::Address) -> &mut Self { + self.token1_vault = Some(token1_vault); + self + } + /// The mint of token_0 vault + #[inline(always)] + pub fn vault0_mint(&mut self, vault0_mint: solana_address::Address) -> &mut Self { + self.vault0_mint = Some(vault0_mint); + self + } + /// The mint of token_1 vault + #[inline(always)] + pub fn vault1_mint(&mut self, vault1_mint: solana_address::Address) -> &mut Self { + self.vault1_mint = Some(vault1_mint); + self + } + /// The address that receives the collected token_0 fund fees + #[inline(always)] + pub fn recipient_token0_account( + &mut self, + recipient_token0_account: solana_address::Address, + ) -> &mut Self { + self.recipient_token0_account = Some(recipient_token0_account); + self + } + /// The address that receives the collected token_1 fund fees + #[inline(always)] + pub fn recipient_token1_account( + &mut self, + recipient_token1_account: solana_address::Address, + ) -> &mut Self { + self.recipient_token1_account = Some(recipient_token1_account); + self + } + /// `[optional account, default to 'TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA']` + /// The SPL program to perform token transfers + #[inline(always)] + pub fn token_program(&mut self, token_program: solana_address::Address) -> &mut Self { + self.token_program = Some(token_program); + self + } + /// `[optional account, default to 'TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb']` + /// The SPL program 2022 to perform token transfers + #[inline(always)] + pub fn token_program2022(&mut self, token_program2022: solana_address::Address) -> &mut Self { + self.token_program2022 = Some(token_program2022); + self + } + #[inline(always)] + pub fn amount0_requested(&mut self, amount0_requested: u64) -> &mut Self { + self.amount0_requested = Some(amount0_requested); + self + } + #[inline(always)] + pub fn amount1_requested(&mut self, amount1_requested: u64) -> &mut Self { + self.amount1_requested = Some(amount1_requested); + self + } + /// Add an additional account to the instruction. + #[inline(always)] + pub fn add_remaining_account(&mut self, account: solana_instruction::AccountMeta) -> &mut Self { + self.__remaining_accounts.push(account); + self + } + /// Add additional accounts to the instruction. + #[inline(always)] + pub fn add_remaining_accounts( + &mut self, + accounts: &[solana_instruction::AccountMeta], + ) -> &mut Self { + self.__remaining_accounts.extend_from_slice(accounts); + self + } + #[allow(clippy::clone_on_copy)] + pub fn instruction(&self) -> solana_instruction::Instruction { + let accounts = CollectFundFee { + owner: self.owner.expect("owner is not set"), + authority: self.authority.expect("authority is not set"), + pool_state: self.pool_state.expect("pool_state is not set"), + amm_config: self.amm_config.expect("amm_config is not set"), + token0_vault: self.token0_vault.expect("token0_vault is not set"), + token1_vault: self.token1_vault.expect("token1_vault is not set"), + vault0_mint: self.vault0_mint.expect("vault0_mint is not set"), + vault1_mint: self.vault1_mint.expect("vault1_mint is not set"), + recipient_token0_account: self + .recipient_token0_account + .expect("recipient_token0_account is not set"), + recipient_token1_account: self + .recipient_token1_account + .expect("recipient_token1_account is not set"), + token_program: self.token_program.unwrap_or(solana_address::address!( + "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA" + )), + token_program2022: self.token_program2022.unwrap_or(solana_address::address!( + "TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb" + )), + }; + let args = CollectFundFeeInstructionArgs { + amount0_requested: self + .amount0_requested + .clone() + .expect("amount0_requested is not set"), + amount1_requested: self + .amount1_requested + .clone() + .expect("amount1_requested is not set"), + }; + + accounts.instruction_with_remaining_accounts(args, &self.__remaining_accounts) + } +} + +/// `collect_fund_fee` CPI accounts. +pub struct CollectFundFeeCpiAccounts<'a, 'b> { + /// Only admin or fund_owner can collect fee now + pub owner: &'b solana_account_info::AccountInfo<'a>, + + pub authority: &'b solana_account_info::AccountInfo<'a>, + /// Pool state stores accumulated protocol fee amount + pub pool_state: &'b solana_account_info::AccountInfo<'a>, + /// Amm config account stores fund_owner + pub amm_config: &'b solana_account_info::AccountInfo<'a>, + /// The address that holds pool tokens for token_0 + pub token0_vault: &'b solana_account_info::AccountInfo<'a>, + /// The address that holds pool tokens for token_1 + pub token1_vault: &'b solana_account_info::AccountInfo<'a>, + /// The mint of token_0 vault + pub vault0_mint: &'b solana_account_info::AccountInfo<'a>, + /// The mint of token_1 vault + pub vault1_mint: &'b solana_account_info::AccountInfo<'a>, + /// The address that receives the collected token_0 fund fees + pub recipient_token0_account: &'b solana_account_info::AccountInfo<'a>, + /// The address that receives the collected token_1 fund fees + pub recipient_token1_account: &'b solana_account_info::AccountInfo<'a>, + /// The SPL program to perform token transfers + pub token_program: &'b solana_account_info::AccountInfo<'a>, + /// The SPL program 2022 to perform token transfers + pub token_program2022: &'b solana_account_info::AccountInfo<'a>, +} + +/// `collect_fund_fee` CPI instruction. +pub struct CollectFundFeeCpi<'a, 'b> { + /// The program to invoke. + pub __program: &'b solana_account_info::AccountInfo<'a>, + /// Only admin or fund_owner can collect fee now + pub owner: &'b solana_account_info::AccountInfo<'a>, + + pub authority: &'b solana_account_info::AccountInfo<'a>, + /// Pool state stores accumulated protocol fee amount + pub pool_state: &'b solana_account_info::AccountInfo<'a>, + /// Amm config account stores fund_owner + pub amm_config: &'b solana_account_info::AccountInfo<'a>, + /// The address that holds pool tokens for token_0 + pub token0_vault: &'b solana_account_info::AccountInfo<'a>, + /// The address that holds pool tokens for token_1 + pub token1_vault: &'b solana_account_info::AccountInfo<'a>, + /// The mint of token_0 vault + pub vault0_mint: &'b solana_account_info::AccountInfo<'a>, + /// The mint of token_1 vault + pub vault1_mint: &'b solana_account_info::AccountInfo<'a>, + /// The address that receives the collected token_0 fund fees + pub recipient_token0_account: &'b solana_account_info::AccountInfo<'a>, + /// The address that receives the collected token_1 fund fees + pub recipient_token1_account: &'b solana_account_info::AccountInfo<'a>, + /// The SPL program to perform token transfers + pub token_program: &'b solana_account_info::AccountInfo<'a>, + /// The SPL program 2022 to perform token transfers + pub token_program2022: &'b solana_account_info::AccountInfo<'a>, + /// The arguments for the instruction. + pub __args: CollectFundFeeInstructionArgs, +} + +impl<'a, 'b> CollectFundFeeCpi<'a, 'b> { + pub fn new( + program: &'b solana_account_info::AccountInfo<'a>, + accounts: CollectFundFeeCpiAccounts<'a, 'b>, + args: CollectFundFeeInstructionArgs, + ) -> Self { + Self { + __program: program, + owner: accounts.owner, + authority: accounts.authority, + pool_state: accounts.pool_state, + amm_config: accounts.amm_config, + token0_vault: accounts.token0_vault, + token1_vault: accounts.token1_vault, + vault0_mint: accounts.vault0_mint, + vault1_mint: accounts.vault1_mint, + recipient_token0_account: accounts.recipient_token0_account, + recipient_token1_account: accounts.recipient_token1_account, + token_program: accounts.token_program, + token_program2022: accounts.token_program2022, + __args: args, + } + } + #[inline(always)] + pub fn invoke(&self) -> solana_program_error::ProgramResult { + self.invoke_signed_with_remaining_accounts(&[], &[]) + } + #[inline(always)] + pub fn invoke_with_remaining_accounts( + &self, + remaining_accounts: &[(&'b solana_account_info::AccountInfo<'a>, bool, bool)], + ) -> solana_program_error::ProgramResult { + self.invoke_signed_with_remaining_accounts(&[], remaining_accounts) + } + #[inline(always)] + pub fn invoke_signed(&self, signers_seeds: &[&[&[u8]]]) -> solana_program_error::ProgramResult { + self.invoke_signed_with_remaining_accounts(signers_seeds, &[]) + } + #[allow(clippy::arithmetic_side_effects)] + #[allow(clippy::clone_on_copy)] + #[allow(clippy::vec_init_then_push)] + pub fn invoke_signed_with_remaining_accounts( + &self, + signers_seeds: &[&[&[u8]]], + remaining_accounts: &[(&'b solana_account_info::AccountInfo<'a>, bool, bool)], + ) -> solana_program_error::ProgramResult { + let mut accounts = Vec::with_capacity(12 + remaining_accounts.len()); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.owner.key, + true, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.authority.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + *self.pool_state.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.amm_config.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + *self.token0_vault.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + *self.token1_vault.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.vault0_mint.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.vault1_mint.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + *self.recipient_token0_account.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + *self.recipient_token1_account.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.token_program.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.token_program2022.key, + false, + )); + remaining_accounts.iter().for_each(|remaining_account| { + accounts.push(solana_instruction::AccountMeta { + pubkey: *remaining_account.0.key, + is_signer: remaining_account.1, + is_writable: remaining_account.2, + }) + }); + let mut data = CollectFundFeeInstructionData::new().try_to_vec().unwrap(); + let mut args = self.__args.try_to_vec().unwrap(); + data.append(&mut args); + + let instruction = solana_instruction::Instruction { + program_id: crate::RAYDIUM_CP_SWAP_ID, + accounts, + data, + }; + let mut account_infos = Vec::with_capacity(13 + remaining_accounts.len()); + account_infos.push(self.__program.clone()); + account_infos.push(self.owner.clone()); + account_infos.push(self.authority.clone()); + account_infos.push(self.pool_state.clone()); + account_infos.push(self.amm_config.clone()); + account_infos.push(self.token0_vault.clone()); + account_infos.push(self.token1_vault.clone()); + account_infos.push(self.vault0_mint.clone()); + account_infos.push(self.vault1_mint.clone()); + account_infos.push(self.recipient_token0_account.clone()); + account_infos.push(self.recipient_token1_account.clone()); + account_infos.push(self.token_program.clone()); + account_infos.push(self.token_program2022.clone()); + remaining_accounts + .iter() + .for_each(|remaining_account| account_infos.push(remaining_account.0.clone())); + + if signers_seeds.is_empty() { + solana_cpi::invoke(&instruction, &account_infos) + } else { + solana_cpi::invoke_signed(&instruction, &account_infos, signers_seeds) + } + } +} + +/// Instruction builder for `CollectFundFee` via CPI. +/// +/// ### Accounts: +/// +/// 0. `[signer]` owner +/// 1. `[]` authority +/// 2. `[writable]` pool_state +/// 3. `[]` amm_config +/// 4. `[writable]` token0_vault +/// 5. `[writable]` token1_vault +/// 6. `[]` vault0_mint +/// 7. `[]` vault1_mint +/// 8. `[writable]` recipient_token0_account +/// 9. `[writable]` recipient_token1_account +/// 10. `[]` token_program +/// 11. `[]` token_program2022 +#[derive(Clone, Debug)] +pub struct CollectFundFeeCpiBuilder<'a, 'b> { + instruction: Box>, +} + +impl<'a, 'b> CollectFundFeeCpiBuilder<'a, 'b> { + pub fn new(program: &'b solana_account_info::AccountInfo<'a>) -> Self { + let instruction = Box::new(CollectFundFeeCpiBuilderInstruction { + __program: program, + owner: None, + authority: None, + pool_state: None, + amm_config: None, + token0_vault: None, + token1_vault: None, + vault0_mint: None, + vault1_mint: None, + recipient_token0_account: None, + recipient_token1_account: None, + token_program: None, + token_program2022: None, + amount0_requested: None, + amount1_requested: None, + __remaining_accounts: Vec::new(), + }); + Self { instruction } + } + /// Only admin or fund_owner can collect fee now + #[inline(always)] + pub fn owner(&mut self, owner: &'b solana_account_info::AccountInfo<'a>) -> &mut Self { + self.instruction.owner = Some(owner); + self + } + #[inline(always)] + pub fn authority(&mut self, authority: &'b solana_account_info::AccountInfo<'a>) -> &mut Self { + self.instruction.authority = Some(authority); + self + } + /// Pool state stores accumulated protocol fee amount + #[inline(always)] + pub fn pool_state( + &mut self, + pool_state: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.pool_state = Some(pool_state); + self + } + /// Amm config account stores fund_owner + #[inline(always)] + pub fn amm_config( + &mut self, + amm_config: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.amm_config = Some(amm_config); + self + } + /// The address that holds pool tokens for token_0 + #[inline(always)] + pub fn token0_vault( + &mut self, + token0_vault: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.token0_vault = Some(token0_vault); + self + } + /// The address that holds pool tokens for token_1 + #[inline(always)] + pub fn token1_vault( + &mut self, + token1_vault: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.token1_vault = Some(token1_vault); + self + } + /// The mint of token_0 vault + #[inline(always)] + pub fn vault0_mint( + &mut self, + vault0_mint: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.vault0_mint = Some(vault0_mint); + self + } + /// The mint of token_1 vault + #[inline(always)] + pub fn vault1_mint( + &mut self, + vault1_mint: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.vault1_mint = Some(vault1_mint); + self + } + /// The address that receives the collected token_0 fund fees + #[inline(always)] + pub fn recipient_token0_account( + &mut self, + recipient_token0_account: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.recipient_token0_account = Some(recipient_token0_account); + self + } + /// The address that receives the collected token_1 fund fees + #[inline(always)] + pub fn recipient_token1_account( + &mut self, + recipient_token1_account: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.recipient_token1_account = Some(recipient_token1_account); + self + } + /// The SPL program to perform token transfers + #[inline(always)] + pub fn token_program( + &mut self, + token_program: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.token_program = Some(token_program); + self + } + /// The SPL program 2022 to perform token transfers + #[inline(always)] + pub fn token_program2022( + &mut self, + token_program2022: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.token_program2022 = Some(token_program2022); + self + } + #[inline(always)] + pub fn amount0_requested(&mut self, amount0_requested: u64) -> &mut Self { + self.instruction.amount0_requested = Some(amount0_requested); + self + } + #[inline(always)] + pub fn amount1_requested(&mut self, amount1_requested: u64) -> &mut Self { + self.instruction.amount1_requested = Some(amount1_requested); + self + } + /// Add an additional account to the instruction. + #[inline(always)] + pub fn add_remaining_account( + &mut self, + account: &'b solana_account_info::AccountInfo<'a>, + is_writable: bool, + is_signer: bool, + ) -> &mut Self { + self.instruction + .__remaining_accounts + .push((account, is_writable, is_signer)); + self + } + /// Add additional accounts to the instruction. + /// + /// Each account is represented by a tuple of the `AccountInfo`, a `bool` indicating whether the account is writable or not, + /// and a `bool` indicating whether the account is a signer or not. + #[inline(always)] + pub fn add_remaining_accounts( + &mut self, + accounts: &[(&'b solana_account_info::AccountInfo<'a>, bool, bool)], + ) -> &mut Self { + self.instruction + .__remaining_accounts + .extend_from_slice(accounts); + self + } + #[inline(always)] + pub fn invoke(&self) -> solana_program_error::ProgramResult { + self.invoke_signed(&[]) + } + #[allow(clippy::clone_on_copy)] + #[allow(clippy::vec_init_then_push)] + pub fn invoke_signed(&self, signers_seeds: &[&[&[u8]]]) -> solana_program_error::ProgramResult { + let args = CollectFundFeeInstructionArgs { + amount0_requested: self + .instruction + .amount0_requested + .clone() + .expect("amount0_requested is not set"), + amount1_requested: self + .instruction + .amount1_requested + .clone() + .expect("amount1_requested is not set"), + }; + let instruction = CollectFundFeeCpi { + __program: self.instruction.__program, + + owner: self.instruction.owner.expect("owner is not set"), + + authority: self.instruction.authority.expect("authority is not set"), + + pool_state: self.instruction.pool_state.expect("pool_state is not set"), + + amm_config: self.instruction.amm_config.expect("amm_config is not set"), + + token0_vault: self + .instruction + .token0_vault + .expect("token0_vault is not set"), + + token1_vault: self + .instruction + .token1_vault + .expect("token1_vault is not set"), + + vault0_mint: self + .instruction + .vault0_mint + .expect("vault0_mint is not set"), + + vault1_mint: self + .instruction + .vault1_mint + .expect("vault1_mint is not set"), + + recipient_token0_account: self + .instruction + .recipient_token0_account + .expect("recipient_token0_account is not set"), + + recipient_token1_account: self + .instruction + .recipient_token1_account + .expect("recipient_token1_account is not set"), + + token_program: self + .instruction + .token_program + .expect("token_program is not set"), + + token_program2022: self + .instruction + .token_program2022 + .expect("token_program2022 is not set"), + __args: args, + }; + instruction.invoke_signed_with_remaining_accounts( + signers_seeds, + &self.instruction.__remaining_accounts, + ) + } +} + +#[derive(Clone, Debug)] +struct CollectFundFeeCpiBuilderInstruction<'a, 'b> { + __program: &'b solana_account_info::AccountInfo<'a>, + owner: Option<&'b solana_account_info::AccountInfo<'a>>, + authority: Option<&'b solana_account_info::AccountInfo<'a>>, + pool_state: Option<&'b solana_account_info::AccountInfo<'a>>, + amm_config: Option<&'b solana_account_info::AccountInfo<'a>>, + token0_vault: Option<&'b solana_account_info::AccountInfo<'a>>, + token1_vault: Option<&'b solana_account_info::AccountInfo<'a>>, + vault0_mint: Option<&'b solana_account_info::AccountInfo<'a>>, + vault1_mint: Option<&'b solana_account_info::AccountInfo<'a>>, + recipient_token0_account: Option<&'b solana_account_info::AccountInfo<'a>>, + recipient_token1_account: Option<&'b solana_account_info::AccountInfo<'a>>, + token_program: Option<&'b solana_account_info::AccountInfo<'a>>, + token_program2022: Option<&'b solana_account_info::AccountInfo<'a>>, + amount0_requested: Option, + amount1_requested: Option, + /// Additional instruction accounts `(AccountInfo, is_writable, is_signer)`. + __remaining_accounts: Vec<(&'b solana_account_info::AccountInfo<'a>, bool, bool)>, +} diff --git a/e2e/raydium-cpmm/src/generated/instructions/collect_protocol_fee.rs b/e2e/raydium-cpmm/src/generated/instructions/collect_protocol_fee.rs new file mode 100644 index 0000000..7b4e5f1 --- /dev/null +++ b/e2e/raydium-cpmm/src/generated/instructions/collect_protocol_fee.rs @@ -0,0 +1,810 @@ +//! This code was AUTOGENERATED using the codama library. +//! Please DO NOT EDIT THIS FILE, instead use visitors +//! to add features, then rerun codama to update it. +//! +//! +//! + +use borsh::BorshDeserialize; +use borsh::BorshSerialize; + +pub const COLLECT_PROTOCOL_FEE_DISCRIMINATOR: [u8; 8] = [136, 136, 252, 221, 194, 66, 126, 89]; + +/// Accounts. +#[derive(Debug)] +pub struct CollectProtocolFee { + /// Only admin or owner can collect fee now + pub owner: solana_address::Address, + + pub authority: solana_address::Address, + /// Pool state stores accumulated protocol fee amount + pub pool_state: solana_address::Address, + /// Amm config account stores owner + pub amm_config: solana_address::Address, + /// The address that holds pool tokens for token_0 + pub token0_vault: solana_address::Address, + /// The address that holds pool tokens for token_1 + pub token1_vault: solana_address::Address, + /// The mint of token_0 vault + pub vault0_mint: solana_address::Address, + /// The mint of token_1 vault + pub vault1_mint: solana_address::Address, + /// The address that receives the collected token_0 protocol fees + pub recipient_token0_account: solana_address::Address, + /// The address that receives the collected token_1 protocol fees + pub recipient_token1_account: solana_address::Address, + /// The SPL program to perform token transfers + pub token_program: solana_address::Address, + /// The SPL program 2022 to perform token transfers + pub token_program2022: solana_address::Address, +} + +impl CollectProtocolFee { + pub fn instruction( + &self, + args: CollectProtocolFeeInstructionArgs, + ) -> solana_instruction::Instruction { + self.instruction_with_remaining_accounts(args, &[]) + } + #[allow(clippy::arithmetic_side_effects)] + #[allow(clippy::vec_init_then_push)] + pub fn instruction_with_remaining_accounts( + &self, + args: CollectProtocolFeeInstructionArgs, + remaining_accounts: &[solana_instruction::AccountMeta], + ) -> solana_instruction::Instruction { + let mut accounts = Vec::with_capacity(12 + remaining_accounts.len()); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.owner, true, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.authority, + false, + )); + accounts.push(solana_instruction::AccountMeta::new(self.pool_state, false)); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.amm_config, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + self.token0_vault, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + self.token1_vault, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.vault0_mint, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.vault1_mint, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + self.recipient_token0_account, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + self.recipient_token1_account, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.token_program, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.token_program2022, + false, + )); + accounts.extend_from_slice(remaining_accounts); + let mut data = CollectProtocolFeeInstructionData::new() + .try_to_vec() + .unwrap(); + let mut args = args.try_to_vec().unwrap(); + data.append(&mut args); + + solana_instruction::Instruction { + program_id: crate::RAYDIUM_CP_SWAP_ID, + accounts, + data, + } + } +} + +#[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] +pub struct CollectProtocolFeeInstructionData { + discriminator: [u8; 8], +} + +impl CollectProtocolFeeInstructionData { + pub fn new() -> Self { + Self { + discriminator: [136, 136, 252, 221, 194, 66, 126, 89], + } + } + + pub(crate) fn try_to_vec(&self) -> Result, std::io::Error> { + borsh::to_vec(self) + } +} + +impl Default for CollectProtocolFeeInstructionData { + fn default() -> Self { + Self::new() + } +} + +#[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] +pub struct CollectProtocolFeeInstructionArgs { + pub amount0_requested: u64, + pub amount1_requested: u64, +} + +impl CollectProtocolFeeInstructionArgs { + pub(crate) fn try_to_vec(&self) -> Result, std::io::Error> { + borsh::to_vec(self) + } +} + +/// Instruction builder for `CollectProtocolFee`. +/// +/// ### Accounts: +/// +/// 0. `[signer]` owner +/// 1. `[]` authority +/// 2. `[writable]` pool_state +/// 3. `[]` amm_config +/// 4. `[writable]` token0_vault +/// 5. `[writable]` token1_vault +/// 6. `[]` vault0_mint +/// 7. `[]` vault1_mint +/// 8. `[writable]` recipient_token0_account +/// 9. `[writable]` recipient_token1_account +/// 10. `[optional]` token_program (default to `TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA`) +/// 11. `[optional]` token_program2022 (default to `TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb`) +#[derive(Clone, Debug, Default)] +pub struct CollectProtocolFeeBuilder { + owner: Option, + authority: Option, + pool_state: Option, + amm_config: Option, + token0_vault: Option, + token1_vault: Option, + vault0_mint: Option, + vault1_mint: Option, + recipient_token0_account: Option, + recipient_token1_account: Option, + token_program: Option, + token_program2022: Option, + amount0_requested: Option, + amount1_requested: Option, + __remaining_accounts: Vec, +} + +impl CollectProtocolFeeBuilder { + pub fn new() -> Self { + Self::default() + } + /// Only admin or owner can collect fee now + #[inline(always)] + pub fn owner(&mut self, owner: solana_address::Address) -> &mut Self { + self.owner = Some(owner); + self + } + #[inline(always)] + pub fn authority(&mut self, authority: solana_address::Address) -> &mut Self { + self.authority = Some(authority); + self + } + /// Pool state stores accumulated protocol fee amount + #[inline(always)] + pub fn pool_state(&mut self, pool_state: solana_address::Address) -> &mut Self { + self.pool_state = Some(pool_state); + self + } + /// Amm config account stores owner + #[inline(always)] + pub fn amm_config(&mut self, amm_config: solana_address::Address) -> &mut Self { + self.amm_config = Some(amm_config); + self + } + /// The address that holds pool tokens for token_0 + #[inline(always)] + pub fn token0_vault(&mut self, token0_vault: solana_address::Address) -> &mut Self { + self.token0_vault = Some(token0_vault); + self + } + /// The address that holds pool tokens for token_1 + #[inline(always)] + pub fn token1_vault(&mut self, token1_vault: solana_address::Address) -> &mut Self { + self.token1_vault = Some(token1_vault); + self + } + /// The mint of token_0 vault + #[inline(always)] + pub fn vault0_mint(&mut self, vault0_mint: solana_address::Address) -> &mut Self { + self.vault0_mint = Some(vault0_mint); + self + } + /// The mint of token_1 vault + #[inline(always)] + pub fn vault1_mint(&mut self, vault1_mint: solana_address::Address) -> &mut Self { + self.vault1_mint = Some(vault1_mint); + self + } + /// The address that receives the collected token_0 protocol fees + #[inline(always)] + pub fn recipient_token0_account( + &mut self, + recipient_token0_account: solana_address::Address, + ) -> &mut Self { + self.recipient_token0_account = Some(recipient_token0_account); + self + } + /// The address that receives the collected token_1 protocol fees + #[inline(always)] + pub fn recipient_token1_account( + &mut self, + recipient_token1_account: solana_address::Address, + ) -> &mut Self { + self.recipient_token1_account = Some(recipient_token1_account); + self + } + /// `[optional account, default to 'TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA']` + /// The SPL program to perform token transfers + #[inline(always)] + pub fn token_program(&mut self, token_program: solana_address::Address) -> &mut Self { + self.token_program = Some(token_program); + self + } + /// `[optional account, default to 'TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb']` + /// The SPL program 2022 to perform token transfers + #[inline(always)] + pub fn token_program2022(&mut self, token_program2022: solana_address::Address) -> &mut Self { + self.token_program2022 = Some(token_program2022); + self + } + #[inline(always)] + pub fn amount0_requested(&mut self, amount0_requested: u64) -> &mut Self { + self.amount0_requested = Some(amount0_requested); + self + } + #[inline(always)] + pub fn amount1_requested(&mut self, amount1_requested: u64) -> &mut Self { + self.amount1_requested = Some(amount1_requested); + self + } + /// Add an additional account to the instruction. + #[inline(always)] + pub fn add_remaining_account(&mut self, account: solana_instruction::AccountMeta) -> &mut Self { + self.__remaining_accounts.push(account); + self + } + /// Add additional accounts to the instruction. + #[inline(always)] + pub fn add_remaining_accounts( + &mut self, + accounts: &[solana_instruction::AccountMeta], + ) -> &mut Self { + self.__remaining_accounts.extend_from_slice(accounts); + self + } + #[allow(clippy::clone_on_copy)] + pub fn instruction(&self) -> solana_instruction::Instruction { + let accounts = CollectProtocolFee { + owner: self.owner.expect("owner is not set"), + authority: self.authority.expect("authority is not set"), + pool_state: self.pool_state.expect("pool_state is not set"), + amm_config: self.amm_config.expect("amm_config is not set"), + token0_vault: self.token0_vault.expect("token0_vault is not set"), + token1_vault: self.token1_vault.expect("token1_vault is not set"), + vault0_mint: self.vault0_mint.expect("vault0_mint is not set"), + vault1_mint: self.vault1_mint.expect("vault1_mint is not set"), + recipient_token0_account: self + .recipient_token0_account + .expect("recipient_token0_account is not set"), + recipient_token1_account: self + .recipient_token1_account + .expect("recipient_token1_account is not set"), + token_program: self.token_program.unwrap_or(solana_address::address!( + "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA" + )), + token_program2022: self.token_program2022.unwrap_or(solana_address::address!( + "TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb" + )), + }; + let args = CollectProtocolFeeInstructionArgs { + amount0_requested: self + .amount0_requested + .clone() + .expect("amount0_requested is not set"), + amount1_requested: self + .amount1_requested + .clone() + .expect("amount1_requested is not set"), + }; + + accounts.instruction_with_remaining_accounts(args, &self.__remaining_accounts) + } +} + +/// `collect_protocol_fee` CPI accounts. +pub struct CollectProtocolFeeCpiAccounts<'a, 'b> { + /// Only admin or owner can collect fee now + pub owner: &'b solana_account_info::AccountInfo<'a>, + + pub authority: &'b solana_account_info::AccountInfo<'a>, + /// Pool state stores accumulated protocol fee amount + pub pool_state: &'b solana_account_info::AccountInfo<'a>, + /// Amm config account stores owner + pub amm_config: &'b solana_account_info::AccountInfo<'a>, + /// The address that holds pool tokens for token_0 + pub token0_vault: &'b solana_account_info::AccountInfo<'a>, + /// The address that holds pool tokens for token_1 + pub token1_vault: &'b solana_account_info::AccountInfo<'a>, + /// The mint of token_0 vault + pub vault0_mint: &'b solana_account_info::AccountInfo<'a>, + /// The mint of token_1 vault + pub vault1_mint: &'b solana_account_info::AccountInfo<'a>, + /// The address that receives the collected token_0 protocol fees + pub recipient_token0_account: &'b solana_account_info::AccountInfo<'a>, + /// The address that receives the collected token_1 protocol fees + pub recipient_token1_account: &'b solana_account_info::AccountInfo<'a>, + /// The SPL program to perform token transfers + pub token_program: &'b solana_account_info::AccountInfo<'a>, + /// The SPL program 2022 to perform token transfers + pub token_program2022: &'b solana_account_info::AccountInfo<'a>, +} + +/// `collect_protocol_fee` CPI instruction. +pub struct CollectProtocolFeeCpi<'a, 'b> { + /// The program to invoke. + pub __program: &'b solana_account_info::AccountInfo<'a>, + /// Only admin or owner can collect fee now + pub owner: &'b solana_account_info::AccountInfo<'a>, + + pub authority: &'b solana_account_info::AccountInfo<'a>, + /// Pool state stores accumulated protocol fee amount + pub pool_state: &'b solana_account_info::AccountInfo<'a>, + /// Amm config account stores owner + pub amm_config: &'b solana_account_info::AccountInfo<'a>, + /// The address that holds pool tokens for token_0 + pub token0_vault: &'b solana_account_info::AccountInfo<'a>, + /// The address that holds pool tokens for token_1 + pub token1_vault: &'b solana_account_info::AccountInfo<'a>, + /// The mint of token_0 vault + pub vault0_mint: &'b solana_account_info::AccountInfo<'a>, + /// The mint of token_1 vault + pub vault1_mint: &'b solana_account_info::AccountInfo<'a>, + /// The address that receives the collected token_0 protocol fees + pub recipient_token0_account: &'b solana_account_info::AccountInfo<'a>, + /// The address that receives the collected token_1 protocol fees + pub recipient_token1_account: &'b solana_account_info::AccountInfo<'a>, + /// The SPL program to perform token transfers + pub token_program: &'b solana_account_info::AccountInfo<'a>, + /// The SPL program 2022 to perform token transfers + pub token_program2022: &'b solana_account_info::AccountInfo<'a>, + /// The arguments for the instruction. + pub __args: CollectProtocolFeeInstructionArgs, +} + +impl<'a, 'b> CollectProtocolFeeCpi<'a, 'b> { + pub fn new( + program: &'b solana_account_info::AccountInfo<'a>, + accounts: CollectProtocolFeeCpiAccounts<'a, 'b>, + args: CollectProtocolFeeInstructionArgs, + ) -> Self { + Self { + __program: program, + owner: accounts.owner, + authority: accounts.authority, + pool_state: accounts.pool_state, + amm_config: accounts.amm_config, + token0_vault: accounts.token0_vault, + token1_vault: accounts.token1_vault, + vault0_mint: accounts.vault0_mint, + vault1_mint: accounts.vault1_mint, + recipient_token0_account: accounts.recipient_token0_account, + recipient_token1_account: accounts.recipient_token1_account, + token_program: accounts.token_program, + token_program2022: accounts.token_program2022, + __args: args, + } + } + #[inline(always)] + pub fn invoke(&self) -> solana_program_error::ProgramResult { + self.invoke_signed_with_remaining_accounts(&[], &[]) + } + #[inline(always)] + pub fn invoke_with_remaining_accounts( + &self, + remaining_accounts: &[(&'b solana_account_info::AccountInfo<'a>, bool, bool)], + ) -> solana_program_error::ProgramResult { + self.invoke_signed_with_remaining_accounts(&[], remaining_accounts) + } + #[inline(always)] + pub fn invoke_signed(&self, signers_seeds: &[&[&[u8]]]) -> solana_program_error::ProgramResult { + self.invoke_signed_with_remaining_accounts(signers_seeds, &[]) + } + #[allow(clippy::arithmetic_side_effects)] + #[allow(clippy::clone_on_copy)] + #[allow(clippy::vec_init_then_push)] + pub fn invoke_signed_with_remaining_accounts( + &self, + signers_seeds: &[&[&[u8]]], + remaining_accounts: &[(&'b solana_account_info::AccountInfo<'a>, bool, bool)], + ) -> solana_program_error::ProgramResult { + let mut accounts = Vec::with_capacity(12 + remaining_accounts.len()); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.owner.key, + true, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.authority.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + *self.pool_state.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.amm_config.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + *self.token0_vault.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + *self.token1_vault.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.vault0_mint.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.vault1_mint.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + *self.recipient_token0_account.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + *self.recipient_token1_account.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.token_program.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.token_program2022.key, + false, + )); + remaining_accounts.iter().for_each(|remaining_account| { + accounts.push(solana_instruction::AccountMeta { + pubkey: *remaining_account.0.key, + is_signer: remaining_account.1, + is_writable: remaining_account.2, + }) + }); + let mut data = CollectProtocolFeeInstructionData::new() + .try_to_vec() + .unwrap(); + let mut args = self.__args.try_to_vec().unwrap(); + data.append(&mut args); + + let instruction = solana_instruction::Instruction { + program_id: crate::RAYDIUM_CP_SWAP_ID, + accounts, + data, + }; + let mut account_infos = Vec::with_capacity(13 + remaining_accounts.len()); + account_infos.push(self.__program.clone()); + account_infos.push(self.owner.clone()); + account_infos.push(self.authority.clone()); + account_infos.push(self.pool_state.clone()); + account_infos.push(self.amm_config.clone()); + account_infos.push(self.token0_vault.clone()); + account_infos.push(self.token1_vault.clone()); + account_infos.push(self.vault0_mint.clone()); + account_infos.push(self.vault1_mint.clone()); + account_infos.push(self.recipient_token0_account.clone()); + account_infos.push(self.recipient_token1_account.clone()); + account_infos.push(self.token_program.clone()); + account_infos.push(self.token_program2022.clone()); + remaining_accounts + .iter() + .for_each(|remaining_account| account_infos.push(remaining_account.0.clone())); + + if signers_seeds.is_empty() { + solana_cpi::invoke(&instruction, &account_infos) + } else { + solana_cpi::invoke_signed(&instruction, &account_infos, signers_seeds) + } + } +} + +/// Instruction builder for `CollectProtocolFee` via CPI. +/// +/// ### Accounts: +/// +/// 0. `[signer]` owner +/// 1. `[]` authority +/// 2. `[writable]` pool_state +/// 3. `[]` amm_config +/// 4. `[writable]` token0_vault +/// 5. `[writable]` token1_vault +/// 6. `[]` vault0_mint +/// 7. `[]` vault1_mint +/// 8. `[writable]` recipient_token0_account +/// 9. `[writable]` recipient_token1_account +/// 10. `[]` token_program +/// 11. `[]` token_program2022 +#[derive(Clone, Debug)] +pub struct CollectProtocolFeeCpiBuilder<'a, 'b> { + instruction: Box>, +} + +impl<'a, 'b> CollectProtocolFeeCpiBuilder<'a, 'b> { + pub fn new(program: &'b solana_account_info::AccountInfo<'a>) -> Self { + let instruction = Box::new(CollectProtocolFeeCpiBuilderInstruction { + __program: program, + owner: None, + authority: None, + pool_state: None, + amm_config: None, + token0_vault: None, + token1_vault: None, + vault0_mint: None, + vault1_mint: None, + recipient_token0_account: None, + recipient_token1_account: None, + token_program: None, + token_program2022: None, + amount0_requested: None, + amount1_requested: None, + __remaining_accounts: Vec::new(), + }); + Self { instruction } + } + /// Only admin or owner can collect fee now + #[inline(always)] + pub fn owner(&mut self, owner: &'b solana_account_info::AccountInfo<'a>) -> &mut Self { + self.instruction.owner = Some(owner); + self + } + #[inline(always)] + pub fn authority(&mut self, authority: &'b solana_account_info::AccountInfo<'a>) -> &mut Self { + self.instruction.authority = Some(authority); + self + } + /// Pool state stores accumulated protocol fee amount + #[inline(always)] + pub fn pool_state( + &mut self, + pool_state: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.pool_state = Some(pool_state); + self + } + /// Amm config account stores owner + #[inline(always)] + pub fn amm_config( + &mut self, + amm_config: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.amm_config = Some(amm_config); + self + } + /// The address that holds pool tokens for token_0 + #[inline(always)] + pub fn token0_vault( + &mut self, + token0_vault: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.token0_vault = Some(token0_vault); + self + } + /// The address that holds pool tokens for token_1 + #[inline(always)] + pub fn token1_vault( + &mut self, + token1_vault: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.token1_vault = Some(token1_vault); + self + } + /// The mint of token_0 vault + #[inline(always)] + pub fn vault0_mint( + &mut self, + vault0_mint: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.vault0_mint = Some(vault0_mint); + self + } + /// The mint of token_1 vault + #[inline(always)] + pub fn vault1_mint( + &mut self, + vault1_mint: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.vault1_mint = Some(vault1_mint); + self + } + /// The address that receives the collected token_0 protocol fees + #[inline(always)] + pub fn recipient_token0_account( + &mut self, + recipient_token0_account: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.recipient_token0_account = Some(recipient_token0_account); + self + } + /// The address that receives the collected token_1 protocol fees + #[inline(always)] + pub fn recipient_token1_account( + &mut self, + recipient_token1_account: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.recipient_token1_account = Some(recipient_token1_account); + self + } + /// The SPL program to perform token transfers + #[inline(always)] + pub fn token_program( + &mut self, + token_program: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.token_program = Some(token_program); + self + } + /// The SPL program 2022 to perform token transfers + #[inline(always)] + pub fn token_program2022( + &mut self, + token_program2022: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.token_program2022 = Some(token_program2022); + self + } + #[inline(always)] + pub fn amount0_requested(&mut self, amount0_requested: u64) -> &mut Self { + self.instruction.amount0_requested = Some(amount0_requested); + self + } + #[inline(always)] + pub fn amount1_requested(&mut self, amount1_requested: u64) -> &mut Self { + self.instruction.amount1_requested = Some(amount1_requested); + self + } + /// Add an additional account to the instruction. + #[inline(always)] + pub fn add_remaining_account( + &mut self, + account: &'b solana_account_info::AccountInfo<'a>, + is_writable: bool, + is_signer: bool, + ) -> &mut Self { + self.instruction + .__remaining_accounts + .push((account, is_writable, is_signer)); + self + } + /// Add additional accounts to the instruction. + /// + /// Each account is represented by a tuple of the `AccountInfo`, a `bool` indicating whether the account is writable or not, + /// and a `bool` indicating whether the account is a signer or not. + #[inline(always)] + pub fn add_remaining_accounts( + &mut self, + accounts: &[(&'b solana_account_info::AccountInfo<'a>, bool, bool)], + ) -> &mut Self { + self.instruction + .__remaining_accounts + .extend_from_slice(accounts); + self + } + #[inline(always)] + pub fn invoke(&self) -> solana_program_error::ProgramResult { + self.invoke_signed(&[]) + } + #[allow(clippy::clone_on_copy)] + #[allow(clippy::vec_init_then_push)] + pub fn invoke_signed(&self, signers_seeds: &[&[&[u8]]]) -> solana_program_error::ProgramResult { + let args = CollectProtocolFeeInstructionArgs { + amount0_requested: self + .instruction + .amount0_requested + .clone() + .expect("amount0_requested is not set"), + amount1_requested: self + .instruction + .amount1_requested + .clone() + .expect("amount1_requested is not set"), + }; + let instruction = CollectProtocolFeeCpi { + __program: self.instruction.__program, + + owner: self.instruction.owner.expect("owner is not set"), + + authority: self.instruction.authority.expect("authority is not set"), + + pool_state: self.instruction.pool_state.expect("pool_state is not set"), + + amm_config: self.instruction.amm_config.expect("amm_config is not set"), + + token0_vault: self + .instruction + .token0_vault + .expect("token0_vault is not set"), + + token1_vault: self + .instruction + .token1_vault + .expect("token1_vault is not set"), + + vault0_mint: self + .instruction + .vault0_mint + .expect("vault0_mint is not set"), + + vault1_mint: self + .instruction + .vault1_mint + .expect("vault1_mint is not set"), + + recipient_token0_account: self + .instruction + .recipient_token0_account + .expect("recipient_token0_account is not set"), + + recipient_token1_account: self + .instruction + .recipient_token1_account + .expect("recipient_token1_account is not set"), + + token_program: self + .instruction + .token_program + .expect("token_program is not set"), + + token_program2022: self + .instruction + .token_program2022 + .expect("token_program2022 is not set"), + __args: args, + }; + instruction.invoke_signed_with_remaining_accounts( + signers_seeds, + &self.instruction.__remaining_accounts, + ) + } +} + +#[derive(Clone, Debug)] +struct CollectProtocolFeeCpiBuilderInstruction<'a, 'b> { + __program: &'b solana_account_info::AccountInfo<'a>, + owner: Option<&'b solana_account_info::AccountInfo<'a>>, + authority: Option<&'b solana_account_info::AccountInfo<'a>>, + pool_state: Option<&'b solana_account_info::AccountInfo<'a>>, + amm_config: Option<&'b solana_account_info::AccountInfo<'a>>, + token0_vault: Option<&'b solana_account_info::AccountInfo<'a>>, + token1_vault: Option<&'b solana_account_info::AccountInfo<'a>>, + vault0_mint: Option<&'b solana_account_info::AccountInfo<'a>>, + vault1_mint: Option<&'b solana_account_info::AccountInfo<'a>>, + recipient_token0_account: Option<&'b solana_account_info::AccountInfo<'a>>, + recipient_token1_account: Option<&'b solana_account_info::AccountInfo<'a>>, + token_program: Option<&'b solana_account_info::AccountInfo<'a>>, + token_program2022: Option<&'b solana_account_info::AccountInfo<'a>>, + amount0_requested: Option, + amount1_requested: Option, + /// Additional instruction accounts `(AccountInfo, is_writable, is_signer)`. + __remaining_accounts: Vec<(&'b solana_account_info::AccountInfo<'a>, bool, bool)>, +} diff --git a/e2e/raydium-cpmm/src/generated/instructions/create_amm_config.rs b/e2e/raydium-cpmm/src/generated/instructions/create_amm_config.rs new file mode 100644 index 0000000..0a7b2ce --- /dev/null +++ b/e2e/raydium-cpmm/src/generated/instructions/create_amm_config.rs @@ -0,0 +1,484 @@ +//! This code was AUTOGENERATED using the codama library. +//! Please DO NOT EDIT THIS FILE, instead use visitors +//! to add features, then rerun codama to update it. +//! +//! +//! + +use borsh::BorshDeserialize; +use borsh::BorshSerialize; + +pub const CREATE_AMM_CONFIG_DISCRIMINATOR: [u8; 8] = [137, 52, 237, 212, 215, 117, 108, 104]; + +/// Accounts. +#[derive(Debug)] +pub struct CreateAmmConfig { + /// Address to be set as protocol owner. + pub owner: solana_address::Address, + /// Initialize config state account to store protocol owner address and fee rates. + pub amm_config: solana_address::Address, + + pub system_program: solana_address::Address, +} + +impl CreateAmmConfig { + pub fn instruction( + &self, + args: CreateAmmConfigInstructionArgs, + ) -> solana_instruction::Instruction { + self.instruction_with_remaining_accounts(args, &[]) + } + #[allow(clippy::arithmetic_side_effects)] + #[allow(clippy::vec_init_then_push)] + pub fn instruction_with_remaining_accounts( + &self, + args: CreateAmmConfigInstructionArgs, + remaining_accounts: &[solana_instruction::AccountMeta], + ) -> solana_instruction::Instruction { + let mut accounts = Vec::with_capacity(3 + remaining_accounts.len()); + accounts.push(solana_instruction::AccountMeta::new(self.owner, true)); + accounts.push(solana_instruction::AccountMeta::new(self.amm_config, false)); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.system_program, + false, + )); + accounts.extend_from_slice(remaining_accounts); + let mut data = CreateAmmConfigInstructionData::new().try_to_vec().unwrap(); + let mut args = args.try_to_vec().unwrap(); + data.append(&mut args); + + solana_instruction::Instruction { + program_id: crate::RAYDIUM_CP_SWAP_ID, + accounts, + data, + } + } +} + +#[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] +pub struct CreateAmmConfigInstructionData { + discriminator: [u8; 8], +} + +impl CreateAmmConfigInstructionData { + pub fn new() -> Self { + Self { + discriminator: [137, 52, 237, 212, 215, 117, 108, 104], + } + } + + pub(crate) fn try_to_vec(&self) -> Result, std::io::Error> { + borsh::to_vec(self) + } +} + +impl Default for CreateAmmConfigInstructionData { + fn default() -> Self { + Self::new() + } +} + +#[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] +pub struct CreateAmmConfigInstructionArgs { + pub index: u16, + pub trade_fee_rate: u64, + pub protocol_fee_rate: u64, + pub fund_fee_rate: u64, + pub create_pool_fee: u64, +} + +impl CreateAmmConfigInstructionArgs { + pub(crate) fn try_to_vec(&self) -> Result, std::io::Error> { + borsh::to_vec(self) + } +} + +/// Instruction builder for `CreateAmmConfig`. +/// +/// ### Accounts: +/// +/// 0. `[writable, signer, optional]` owner (default to `GThUX1Atko4tqhN2NaiTazWSeFWMuiUvfFnyJyUghFMJ`) +/// 1. `[writable]` amm_config +/// 2. `[optional]` system_program (default to `11111111111111111111111111111111`) +#[derive(Clone, Debug, Default)] +pub struct CreateAmmConfigBuilder { + owner: Option, + amm_config: Option, + system_program: Option, + index: Option, + trade_fee_rate: Option, + protocol_fee_rate: Option, + fund_fee_rate: Option, + create_pool_fee: Option, + __remaining_accounts: Vec, +} + +impl CreateAmmConfigBuilder { + pub fn new() -> Self { + Self::default() + } + /// `[optional account, default to 'GThUX1Atko4tqhN2NaiTazWSeFWMuiUvfFnyJyUghFMJ']` + /// Address to be set as protocol owner. + #[inline(always)] + pub fn owner(&mut self, owner: solana_address::Address) -> &mut Self { + self.owner = Some(owner); + self + } + /// Initialize config state account to store protocol owner address and fee rates. + #[inline(always)] + pub fn amm_config(&mut self, amm_config: solana_address::Address) -> &mut Self { + self.amm_config = Some(amm_config); + self + } + /// `[optional account, default to '11111111111111111111111111111111']` + #[inline(always)] + pub fn system_program(&mut self, system_program: solana_address::Address) -> &mut Self { + self.system_program = Some(system_program); + self + } + #[inline(always)] + pub fn index(&mut self, index: u16) -> &mut Self { + self.index = Some(index); + self + } + #[inline(always)] + pub fn trade_fee_rate(&mut self, trade_fee_rate: u64) -> &mut Self { + self.trade_fee_rate = Some(trade_fee_rate); + self + } + #[inline(always)] + pub fn protocol_fee_rate(&mut self, protocol_fee_rate: u64) -> &mut Self { + self.protocol_fee_rate = Some(protocol_fee_rate); + self + } + #[inline(always)] + pub fn fund_fee_rate(&mut self, fund_fee_rate: u64) -> &mut Self { + self.fund_fee_rate = Some(fund_fee_rate); + self + } + #[inline(always)] + pub fn create_pool_fee(&mut self, create_pool_fee: u64) -> &mut Self { + self.create_pool_fee = Some(create_pool_fee); + self + } + /// Add an additional account to the instruction. + #[inline(always)] + pub fn add_remaining_account(&mut self, account: solana_instruction::AccountMeta) -> &mut Self { + self.__remaining_accounts.push(account); + self + } + /// Add additional accounts to the instruction. + #[inline(always)] + pub fn add_remaining_accounts( + &mut self, + accounts: &[solana_instruction::AccountMeta], + ) -> &mut Self { + self.__remaining_accounts.extend_from_slice(accounts); + self + } + #[allow(clippy::clone_on_copy)] + pub fn instruction(&self) -> solana_instruction::Instruction { + let accounts = CreateAmmConfig { + owner: self.owner.unwrap_or(solana_address::address!( + "GThUX1Atko4tqhN2NaiTazWSeFWMuiUvfFnyJyUghFMJ" + )), + amm_config: self.amm_config.expect("amm_config is not set"), + system_program: self + .system_program + .unwrap_or(solana_address::address!("11111111111111111111111111111111")), + }; + let args = CreateAmmConfigInstructionArgs { + index: self.index.clone().expect("index is not set"), + trade_fee_rate: self + .trade_fee_rate + .clone() + .expect("trade_fee_rate is not set"), + protocol_fee_rate: self + .protocol_fee_rate + .clone() + .expect("protocol_fee_rate is not set"), + fund_fee_rate: self + .fund_fee_rate + .clone() + .expect("fund_fee_rate is not set"), + create_pool_fee: self + .create_pool_fee + .clone() + .expect("create_pool_fee is not set"), + }; + + accounts.instruction_with_remaining_accounts(args, &self.__remaining_accounts) + } +} + +/// `create_amm_config` CPI accounts. +pub struct CreateAmmConfigCpiAccounts<'a, 'b> { + /// Address to be set as protocol owner. + pub owner: &'b solana_account_info::AccountInfo<'a>, + /// Initialize config state account to store protocol owner address and fee rates. + pub amm_config: &'b solana_account_info::AccountInfo<'a>, + + pub system_program: &'b solana_account_info::AccountInfo<'a>, +} + +/// `create_amm_config` CPI instruction. +pub struct CreateAmmConfigCpi<'a, 'b> { + /// The program to invoke. + pub __program: &'b solana_account_info::AccountInfo<'a>, + /// Address to be set as protocol owner. + pub owner: &'b solana_account_info::AccountInfo<'a>, + /// Initialize config state account to store protocol owner address and fee rates. + pub amm_config: &'b solana_account_info::AccountInfo<'a>, + + pub system_program: &'b solana_account_info::AccountInfo<'a>, + /// The arguments for the instruction. + pub __args: CreateAmmConfigInstructionArgs, +} + +impl<'a, 'b> CreateAmmConfigCpi<'a, 'b> { + pub fn new( + program: &'b solana_account_info::AccountInfo<'a>, + accounts: CreateAmmConfigCpiAccounts<'a, 'b>, + args: CreateAmmConfigInstructionArgs, + ) -> Self { + Self { + __program: program, + owner: accounts.owner, + amm_config: accounts.amm_config, + system_program: accounts.system_program, + __args: args, + } + } + #[inline(always)] + pub fn invoke(&self) -> solana_program_error::ProgramResult { + self.invoke_signed_with_remaining_accounts(&[], &[]) + } + #[inline(always)] + pub fn invoke_with_remaining_accounts( + &self, + remaining_accounts: &[(&'b solana_account_info::AccountInfo<'a>, bool, bool)], + ) -> solana_program_error::ProgramResult { + self.invoke_signed_with_remaining_accounts(&[], remaining_accounts) + } + #[inline(always)] + pub fn invoke_signed(&self, signers_seeds: &[&[&[u8]]]) -> solana_program_error::ProgramResult { + self.invoke_signed_with_remaining_accounts(signers_seeds, &[]) + } + #[allow(clippy::arithmetic_side_effects)] + #[allow(clippy::clone_on_copy)] + #[allow(clippy::vec_init_then_push)] + pub fn invoke_signed_with_remaining_accounts( + &self, + signers_seeds: &[&[&[u8]]], + remaining_accounts: &[(&'b solana_account_info::AccountInfo<'a>, bool, bool)], + ) -> solana_program_error::ProgramResult { + let mut accounts = Vec::with_capacity(3 + remaining_accounts.len()); + accounts.push(solana_instruction::AccountMeta::new(*self.owner.key, true)); + accounts.push(solana_instruction::AccountMeta::new( + *self.amm_config.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.system_program.key, + false, + )); + remaining_accounts.iter().for_each(|remaining_account| { + accounts.push(solana_instruction::AccountMeta { + pubkey: *remaining_account.0.key, + is_signer: remaining_account.1, + is_writable: remaining_account.2, + }) + }); + let mut data = CreateAmmConfigInstructionData::new().try_to_vec().unwrap(); + let mut args = self.__args.try_to_vec().unwrap(); + data.append(&mut args); + + let instruction = solana_instruction::Instruction { + program_id: crate::RAYDIUM_CP_SWAP_ID, + accounts, + data, + }; + let mut account_infos = Vec::with_capacity(4 + remaining_accounts.len()); + account_infos.push(self.__program.clone()); + account_infos.push(self.owner.clone()); + account_infos.push(self.amm_config.clone()); + account_infos.push(self.system_program.clone()); + remaining_accounts + .iter() + .for_each(|remaining_account| account_infos.push(remaining_account.0.clone())); + + if signers_seeds.is_empty() { + solana_cpi::invoke(&instruction, &account_infos) + } else { + solana_cpi::invoke_signed(&instruction, &account_infos, signers_seeds) + } + } +} + +/// Instruction builder for `CreateAmmConfig` via CPI. +/// +/// ### Accounts: +/// +/// 0. `[writable, signer]` owner +/// 1. `[writable]` amm_config +/// 2. `[]` system_program +#[derive(Clone, Debug)] +pub struct CreateAmmConfigCpiBuilder<'a, 'b> { + instruction: Box>, +} + +impl<'a, 'b> CreateAmmConfigCpiBuilder<'a, 'b> { + pub fn new(program: &'b solana_account_info::AccountInfo<'a>) -> Self { + let instruction = Box::new(CreateAmmConfigCpiBuilderInstruction { + __program: program, + owner: None, + amm_config: None, + system_program: None, + index: None, + trade_fee_rate: None, + protocol_fee_rate: None, + fund_fee_rate: None, + create_pool_fee: None, + __remaining_accounts: Vec::new(), + }); + Self { instruction } + } + /// Address to be set as protocol owner. + #[inline(always)] + pub fn owner(&mut self, owner: &'b solana_account_info::AccountInfo<'a>) -> &mut Self { + self.instruction.owner = Some(owner); + self + } + /// Initialize config state account to store protocol owner address and fee rates. + #[inline(always)] + pub fn amm_config( + &mut self, + amm_config: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.amm_config = Some(amm_config); + self + } + #[inline(always)] + pub fn system_program( + &mut self, + system_program: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.system_program = Some(system_program); + self + } + #[inline(always)] + pub fn index(&mut self, index: u16) -> &mut Self { + self.instruction.index = Some(index); + self + } + #[inline(always)] + pub fn trade_fee_rate(&mut self, trade_fee_rate: u64) -> &mut Self { + self.instruction.trade_fee_rate = Some(trade_fee_rate); + self + } + #[inline(always)] + pub fn protocol_fee_rate(&mut self, protocol_fee_rate: u64) -> &mut Self { + self.instruction.protocol_fee_rate = Some(protocol_fee_rate); + self + } + #[inline(always)] + pub fn fund_fee_rate(&mut self, fund_fee_rate: u64) -> &mut Self { + self.instruction.fund_fee_rate = Some(fund_fee_rate); + self + } + #[inline(always)] + pub fn create_pool_fee(&mut self, create_pool_fee: u64) -> &mut Self { + self.instruction.create_pool_fee = Some(create_pool_fee); + self + } + /// Add an additional account to the instruction. + #[inline(always)] + pub fn add_remaining_account( + &mut self, + account: &'b solana_account_info::AccountInfo<'a>, + is_writable: bool, + is_signer: bool, + ) -> &mut Self { + self.instruction + .__remaining_accounts + .push((account, is_writable, is_signer)); + self + } + /// Add additional accounts to the instruction. + /// + /// Each account is represented by a tuple of the `AccountInfo`, a `bool` indicating whether the account is writable or not, + /// and a `bool` indicating whether the account is a signer or not. + #[inline(always)] + pub fn add_remaining_accounts( + &mut self, + accounts: &[(&'b solana_account_info::AccountInfo<'a>, bool, bool)], + ) -> &mut Self { + self.instruction + .__remaining_accounts + .extend_from_slice(accounts); + self + } + #[inline(always)] + pub fn invoke(&self) -> solana_program_error::ProgramResult { + self.invoke_signed(&[]) + } + #[allow(clippy::clone_on_copy)] + #[allow(clippy::vec_init_then_push)] + pub fn invoke_signed(&self, signers_seeds: &[&[&[u8]]]) -> solana_program_error::ProgramResult { + let args = CreateAmmConfigInstructionArgs { + index: self.instruction.index.clone().expect("index is not set"), + trade_fee_rate: self + .instruction + .trade_fee_rate + .clone() + .expect("trade_fee_rate is not set"), + protocol_fee_rate: self + .instruction + .protocol_fee_rate + .clone() + .expect("protocol_fee_rate is not set"), + fund_fee_rate: self + .instruction + .fund_fee_rate + .clone() + .expect("fund_fee_rate is not set"), + create_pool_fee: self + .instruction + .create_pool_fee + .clone() + .expect("create_pool_fee is not set"), + }; + let instruction = CreateAmmConfigCpi { + __program: self.instruction.__program, + + owner: self.instruction.owner.expect("owner is not set"), + + amm_config: self.instruction.amm_config.expect("amm_config is not set"), + + system_program: self + .instruction + .system_program + .expect("system_program is not set"), + __args: args, + }; + instruction.invoke_signed_with_remaining_accounts( + signers_seeds, + &self.instruction.__remaining_accounts, + ) + } +} + +#[derive(Clone, Debug)] +struct CreateAmmConfigCpiBuilderInstruction<'a, 'b> { + __program: &'b solana_account_info::AccountInfo<'a>, + owner: Option<&'b solana_account_info::AccountInfo<'a>>, + amm_config: Option<&'b solana_account_info::AccountInfo<'a>>, + system_program: Option<&'b solana_account_info::AccountInfo<'a>>, + index: Option, + trade_fee_rate: Option, + protocol_fee_rate: Option, + fund_fee_rate: Option, + create_pool_fee: Option, + /// Additional instruction accounts `(AccountInfo, is_writable, is_signer)`. + __remaining_accounts: Vec<(&'b solana_account_info::AccountInfo<'a>, bool, bool)>, +} diff --git a/e2e/raydium-cpmm/src/generated/instructions/deposit.rs b/e2e/raydium-cpmm/src/generated/instructions/deposit.rs new file mode 100644 index 0000000..1645205 --- /dev/null +++ b/e2e/raydium-cpmm/src/generated/instructions/deposit.rs @@ -0,0 +1,850 @@ +//! This code was AUTOGENERATED using the codama library. +//! Please DO NOT EDIT THIS FILE, instead use visitors +//! to add features, then rerun codama to update it. +//! +//! +//! + +use borsh::BorshDeserialize; +use borsh::BorshSerialize; + +pub const DEPOSIT_DISCRIMINATOR: [u8; 8] = [242, 35, 198, 137, 82, 225, 242, 182]; + +/// Accounts. +#[derive(Debug)] +pub struct Deposit { + /// Pays to mint the position + pub owner: solana_address::Address, + + pub authority: solana_address::Address, + + pub pool_state: solana_address::Address, + /// Owner lp token account + pub owner_lp_token: solana_address::Address, + /// The payer's token account for token_0 + pub token0_account: solana_address::Address, + /// The payer's token account for token_1 + pub token1_account: solana_address::Address, + /// The address that holds pool tokens for token_0 + pub token0_vault: solana_address::Address, + /// The address that holds pool tokens for token_1 + pub token1_vault: solana_address::Address, + /// token Program + pub token_program: solana_address::Address, + /// Token program 2022 + pub token_program2022: solana_address::Address, + /// The mint of token_0 vault + pub vault0_mint: solana_address::Address, + /// The mint of token_1 vault + pub vault1_mint: solana_address::Address, + /// Lp token mint + pub lp_mint: solana_address::Address, +} + +impl Deposit { + pub fn instruction(&self, args: DepositInstructionArgs) -> solana_instruction::Instruction { + self.instruction_with_remaining_accounts(args, &[]) + } + #[allow(clippy::arithmetic_side_effects)] + #[allow(clippy::vec_init_then_push)] + pub fn instruction_with_remaining_accounts( + &self, + args: DepositInstructionArgs, + remaining_accounts: &[solana_instruction::AccountMeta], + ) -> solana_instruction::Instruction { + let mut accounts = Vec::with_capacity(13 + remaining_accounts.len()); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.owner, true, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.authority, + false, + )); + accounts.push(solana_instruction::AccountMeta::new(self.pool_state, false)); + accounts.push(solana_instruction::AccountMeta::new( + self.owner_lp_token, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + self.token0_account, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + self.token1_account, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + self.token0_vault, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + self.token1_vault, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.token_program, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.token_program2022, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.vault0_mint, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.vault1_mint, + false, + )); + accounts.push(solana_instruction::AccountMeta::new(self.lp_mint, false)); + accounts.extend_from_slice(remaining_accounts); + let mut data = DepositInstructionData::new().try_to_vec().unwrap(); + let mut args = args.try_to_vec().unwrap(); + data.append(&mut args); + + solana_instruction::Instruction { + program_id: crate::RAYDIUM_CP_SWAP_ID, + accounts, + data, + } + } +} + +#[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] +pub struct DepositInstructionData { + discriminator: [u8; 8], +} + +impl DepositInstructionData { + pub fn new() -> Self { + Self { + discriminator: [242, 35, 198, 137, 82, 225, 242, 182], + } + } + + pub(crate) fn try_to_vec(&self) -> Result, std::io::Error> { + borsh::to_vec(self) + } +} + +impl Default for DepositInstructionData { + fn default() -> Self { + Self::new() + } +} + +#[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] +pub struct DepositInstructionArgs { + pub lp_token_amount: u64, + pub maximum_token0_amount: u64, + pub maximum_token1_amount: u64, +} + +impl DepositInstructionArgs { + pub(crate) fn try_to_vec(&self) -> Result, std::io::Error> { + borsh::to_vec(self) + } +} + +/// Instruction builder for `Deposit`. +/// +/// ### Accounts: +/// +/// 0. `[signer]` owner +/// 1. `[]` authority +/// 2. `[writable]` pool_state +/// 3. `[writable]` owner_lp_token +/// 4. `[writable]` token0_account +/// 5. `[writable]` token1_account +/// 6. `[writable]` token0_vault +/// 7. `[writable]` token1_vault +/// 8. `[optional]` token_program (default to `TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA`) +/// 9. `[optional]` token_program2022 (default to `TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb`) +/// 10. `[]` vault0_mint +/// 11. `[]` vault1_mint +/// 12. `[writable]` lp_mint +#[derive(Clone, Debug, Default)] +pub struct DepositBuilder { + owner: Option, + authority: Option, + pool_state: Option, + owner_lp_token: Option, + token0_account: Option, + token1_account: Option, + token0_vault: Option, + token1_vault: Option, + token_program: Option, + token_program2022: Option, + vault0_mint: Option, + vault1_mint: Option, + lp_mint: Option, + lp_token_amount: Option, + maximum_token0_amount: Option, + maximum_token1_amount: Option, + __remaining_accounts: Vec, +} + +impl DepositBuilder { + pub fn new() -> Self { + Self::default() + } + /// Pays to mint the position + #[inline(always)] + pub fn owner(&mut self, owner: solana_address::Address) -> &mut Self { + self.owner = Some(owner); + self + } + #[inline(always)] + pub fn authority(&mut self, authority: solana_address::Address) -> &mut Self { + self.authority = Some(authority); + self + } + #[inline(always)] + pub fn pool_state(&mut self, pool_state: solana_address::Address) -> &mut Self { + self.pool_state = Some(pool_state); + self + } + /// Owner lp token account + #[inline(always)] + pub fn owner_lp_token(&mut self, owner_lp_token: solana_address::Address) -> &mut Self { + self.owner_lp_token = Some(owner_lp_token); + self + } + /// The payer's token account for token_0 + #[inline(always)] + pub fn token0_account(&mut self, token0_account: solana_address::Address) -> &mut Self { + self.token0_account = Some(token0_account); + self + } + /// The payer's token account for token_1 + #[inline(always)] + pub fn token1_account(&mut self, token1_account: solana_address::Address) -> &mut Self { + self.token1_account = Some(token1_account); + self + } + /// The address that holds pool tokens for token_0 + #[inline(always)] + pub fn token0_vault(&mut self, token0_vault: solana_address::Address) -> &mut Self { + self.token0_vault = Some(token0_vault); + self + } + /// The address that holds pool tokens for token_1 + #[inline(always)] + pub fn token1_vault(&mut self, token1_vault: solana_address::Address) -> &mut Self { + self.token1_vault = Some(token1_vault); + self + } + /// `[optional account, default to 'TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA']` + /// token Program + #[inline(always)] + pub fn token_program(&mut self, token_program: solana_address::Address) -> &mut Self { + self.token_program = Some(token_program); + self + } + /// `[optional account, default to 'TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb']` + /// Token program 2022 + #[inline(always)] + pub fn token_program2022(&mut self, token_program2022: solana_address::Address) -> &mut Self { + self.token_program2022 = Some(token_program2022); + self + } + /// The mint of token_0 vault + #[inline(always)] + pub fn vault0_mint(&mut self, vault0_mint: solana_address::Address) -> &mut Self { + self.vault0_mint = Some(vault0_mint); + self + } + /// The mint of token_1 vault + #[inline(always)] + pub fn vault1_mint(&mut self, vault1_mint: solana_address::Address) -> &mut Self { + self.vault1_mint = Some(vault1_mint); + self + } + /// Lp token mint + #[inline(always)] + pub fn lp_mint(&mut self, lp_mint: solana_address::Address) -> &mut Self { + self.lp_mint = Some(lp_mint); + self + } + #[inline(always)] + pub fn lp_token_amount(&mut self, lp_token_amount: u64) -> &mut Self { + self.lp_token_amount = Some(lp_token_amount); + self + } + #[inline(always)] + pub fn maximum_token0_amount(&mut self, maximum_token0_amount: u64) -> &mut Self { + self.maximum_token0_amount = Some(maximum_token0_amount); + self + } + #[inline(always)] + pub fn maximum_token1_amount(&mut self, maximum_token1_amount: u64) -> &mut Self { + self.maximum_token1_amount = Some(maximum_token1_amount); + self + } + /// Add an additional account to the instruction. + #[inline(always)] + pub fn add_remaining_account(&mut self, account: solana_instruction::AccountMeta) -> &mut Self { + self.__remaining_accounts.push(account); + self + } + /// Add additional accounts to the instruction. + #[inline(always)] + pub fn add_remaining_accounts( + &mut self, + accounts: &[solana_instruction::AccountMeta], + ) -> &mut Self { + self.__remaining_accounts.extend_from_slice(accounts); + self + } + #[allow(clippy::clone_on_copy)] + pub fn instruction(&self) -> solana_instruction::Instruction { + let accounts = Deposit { + owner: self.owner.expect("owner is not set"), + authority: self.authority.expect("authority is not set"), + pool_state: self.pool_state.expect("pool_state is not set"), + owner_lp_token: self.owner_lp_token.expect("owner_lp_token is not set"), + token0_account: self.token0_account.expect("token0_account is not set"), + token1_account: self.token1_account.expect("token1_account is not set"), + token0_vault: self.token0_vault.expect("token0_vault is not set"), + token1_vault: self.token1_vault.expect("token1_vault is not set"), + token_program: self.token_program.unwrap_or(solana_address::address!( + "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA" + )), + token_program2022: self.token_program2022.unwrap_or(solana_address::address!( + "TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb" + )), + vault0_mint: self.vault0_mint.expect("vault0_mint is not set"), + vault1_mint: self.vault1_mint.expect("vault1_mint is not set"), + lp_mint: self.lp_mint.expect("lp_mint is not set"), + }; + let args = DepositInstructionArgs { + lp_token_amount: self + .lp_token_amount + .clone() + .expect("lp_token_amount is not set"), + maximum_token0_amount: self + .maximum_token0_amount + .clone() + .expect("maximum_token0_amount is not set"), + maximum_token1_amount: self + .maximum_token1_amount + .clone() + .expect("maximum_token1_amount is not set"), + }; + + accounts.instruction_with_remaining_accounts(args, &self.__remaining_accounts) + } +} + +/// `deposit` CPI accounts. +pub struct DepositCpiAccounts<'a, 'b> { + /// Pays to mint the position + pub owner: &'b solana_account_info::AccountInfo<'a>, + + pub authority: &'b solana_account_info::AccountInfo<'a>, + + pub pool_state: &'b solana_account_info::AccountInfo<'a>, + /// Owner lp token account + pub owner_lp_token: &'b solana_account_info::AccountInfo<'a>, + /// The payer's token account for token_0 + pub token0_account: &'b solana_account_info::AccountInfo<'a>, + /// The payer's token account for token_1 + pub token1_account: &'b solana_account_info::AccountInfo<'a>, + /// The address that holds pool tokens for token_0 + pub token0_vault: &'b solana_account_info::AccountInfo<'a>, + /// The address that holds pool tokens for token_1 + pub token1_vault: &'b solana_account_info::AccountInfo<'a>, + /// token Program + pub token_program: &'b solana_account_info::AccountInfo<'a>, + /// Token program 2022 + pub token_program2022: &'b solana_account_info::AccountInfo<'a>, + /// The mint of token_0 vault + pub vault0_mint: &'b solana_account_info::AccountInfo<'a>, + /// The mint of token_1 vault + pub vault1_mint: &'b solana_account_info::AccountInfo<'a>, + /// Lp token mint + pub lp_mint: &'b solana_account_info::AccountInfo<'a>, +} + +/// `deposit` CPI instruction. +pub struct DepositCpi<'a, 'b> { + /// The program to invoke. + pub __program: &'b solana_account_info::AccountInfo<'a>, + /// Pays to mint the position + pub owner: &'b solana_account_info::AccountInfo<'a>, + + pub authority: &'b solana_account_info::AccountInfo<'a>, + + pub pool_state: &'b solana_account_info::AccountInfo<'a>, + /// Owner lp token account + pub owner_lp_token: &'b solana_account_info::AccountInfo<'a>, + /// The payer's token account for token_0 + pub token0_account: &'b solana_account_info::AccountInfo<'a>, + /// The payer's token account for token_1 + pub token1_account: &'b solana_account_info::AccountInfo<'a>, + /// The address that holds pool tokens for token_0 + pub token0_vault: &'b solana_account_info::AccountInfo<'a>, + /// The address that holds pool tokens for token_1 + pub token1_vault: &'b solana_account_info::AccountInfo<'a>, + /// token Program + pub token_program: &'b solana_account_info::AccountInfo<'a>, + /// Token program 2022 + pub token_program2022: &'b solana_account_info::AccountInfo<'a>, + /// The mint of token_0 vault + pub vault0_mint: &'b solana_account_info::AccountInfo<'a>, + /// The mint of token_1 vault + pub vault1_mint: &'b solana_account_info::AccountInfo<'a>, + /// Lp token mint + pub lp_mint: &'b solana_account_info::AccountInfo<'a>, + /// The arguments for the instruction. + pub __args: DepositInstructionArgs, +} + +impl<'a, 'b> DepositCpi<'a, 'b> { + pub fn new( + program: &'b solana_account_info::AccountInfo<'a>, + accounts: DepositCpiAccounts<'a, 'b>, + args: DepositInstructionArgs, + ) -> Self { + Self { + __program: program, + owner: accounts.owner, + authority: accounts.authority, + pool_state: accounts.pool_state, + owner_lp_token: accounts.owner_lp_token, + token0_account: accounts.token0_account, + token1_account: accounts.token1_account, + token0_vault: accounts.token0_vault, + token1_vault: accounts.token1_vault, + token_program: accounts.token_program, + token_program2022: accounts.token_program2022, + vault0_mint: accounts.vault0_mint, + vault1_mint: accounts.vault1_mint, + lp_mint: accounts.lp_mint, + __args: args, + } + } + #[inline(always)] + pub fn invoke(&self) -> solana_program_error::ProgramResult { + self.invoke_signed_with_remaining_accounts(&[], &[]) + } + #[inline(always)] + pub fn invoke_with_remaining_accounts( + &self, + remaining_accounts: &[(&'b solana_account_info::AccountInfo<'a>, bool, bool)], + ) -> solana_program_error::ProgramResult { + self.invoke_signed_with_remaining_accounts(&[], remaining_accounts) + } + #[inline(always)] + pub fn invoke_signed(&self, signers_seeds: &[&[&[u8]]]) -> solana_program_error::ProgramResult { + self.invoke_signed_with_remaining_accounts(signers_seeds, &[]) + } + #[allow(clippy::arithmetic_side_effects)] + #[allow(clippy::clone_on_copy)] + #[allow(clippy::vec_init_then_push)] + pub fn invoke_signed_with_remaining_accounts( + &self, + signers_seeds: &[&[&[u8]]], + remaining_accounts: &[(&'b solana_account_info::AccountInfo<'a>, bool, bool)], + ) -> solana_program_error::ProgramResult { + let mut accounts = Vec::with_capacity(13 + remaining_accounts.len()); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.owner.key, + true, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.authority.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + *self.pool_state.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + *self.owner_lp_token.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + *self.token0_account.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + *self.token1_account.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + *self.token0_vault.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + *self.token1_vault.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.token_program.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.token_program2022.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.vault0_mint.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.vault1_mint.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + *self.lp_mint.key, + false, + )); + remaining_accounts.iter().for_each(|remaining_account| { + accounts.push(solana_instruction::AccountMeta { + pubkey: *remaining_account.0.key, + is_signer: remaining_account.1, + is_writable: remaining_account.2, + }) + }); + let mut data = DepositInstructionData::new().try_to_vec().unwrap(); + let mut args = self.__args.try_to_vec().unwrap(); + data.append(&mut args); + + let instruction = solana_instruction::Instruction { + program_id: crate::RAYDIUM_CP_SWAP_ID, + accounts, + data, + }; + let mut account_infos = Vec::with_capacity(14 + remaining_accounts.len()); + account_infos.push(self.__program.clone()); + account_infos.push(self.owner.clone()); + account_infos.push(self.authority.clone()); + account_infos.push(self.pool_state.clone()); + account_infos.push(self.owner_lp_token.clone()); + account_infos.push(self.token0_account.clone()); + account_infos.push(self.token1_account.clone()); + account_infos.push(self.token0_vault.clone()); + account_infos.push(self.token1_vault.clone()); + account_infos.push(self.token_program.clone()); + account_infos.push(self.token_program2022.clone()); + account_infos.push(self.vault0_mint.clone()); + account_infos.push(self.vault1_mint.clone()); + account_infos.push(self.lp_mint.clone()); + remaining_accounts + .iter() + .for_each(|remaining_account| account_infos.push(remaining_account.0.clone())); + + if signers_seeds.is_empty() { + solana_cpi::invoke(&instruction, &account_infos) + } else { + solana_cpi::invoke_signed(&instruction, &account_infos, signers_seeds) + } + } +} + +/// Instruction builder for `Deposit` via CPI. +/// +/// ### Accounts: +/// +/// 0. `[signer]` owner +/// 1. `[]` authority +/// 2. `[writable]` pool_state +/// 3. `[writable]` owner_lp_token +/// 4. `[writable]` token0_account +/// 5. `[writable]` token1_account +/// 6. `[writable]` token0_vault +/// 7. `[writable]` token1_vault +/// 8. `[]` token_program +/// 9. `[]` token_program2022 +/// 10. `[]` vault0_mint +/// 11. `[]` vault1_mint +/// 12. `[writable]` lp_mint +#[derive(Clone, Debug)] +pub struct DepositCpiBuilder<'a, 'b> { + instruction: Box>, +} + +impl<'a, 'b> DepositCpiBuilder<'a, 'b> { + pub fn new(program: &'b solana_account_info::AccountInfo<'a>) -> Self { + let instruction = Box::new(DepositCpiBuilderInstruction { + __program: program, + owner: None, + authority: None, + pool_state: None, + owner_lp_token: None, + token0_account: None, + token1_account: None, + token0_vault: None, + token1_vault: None, + token_program: None, + token_program2022: None, + vault0_mint: None, + vault1_mint: None, + lp_mint: None, + lp_token_amount: None, + maximum_token0_amount: None, + maximum_token1_amount: None, + __remaining_accounts: Vec::new(), + }); + Self { instruction } + } + /// Pays to mint the position + #[inline(always)] + pub fn owner(&mut self, owner: &'b solana_account_info::AccountInfo<'a>) -> &mut Self { + self.instruction.owner = Some(owner); + self + } + #[inline(always)] + pub fn authority(&mut self, authority: &'b solana_account_info::AccountInfo<'a>) -> &mut Self { + self.instruction.authority = Some(authority); + self + } + #[inline(always)] + pub fn pool_state( + &mut self, + pool_state: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.pool_state = Some(pool_state); + self + } + /// Owner lp token account + #[inline(always)] + pub fn owner_lp_token( + &mut self, + owner_lp_token: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.owner_lp_token = Some(owner_lp_token); + self + } + /// The payer's token account for token_0 + #[inline(always)] + pub fn token0_account( + &mut self, + token0_account: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.token0_account = Some(token0_account); + self + } + /// The payer's token account for token_1 + #[inline(always)] + pub fn token1_account( + &mut self, + token1_account: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.token1_account = Some(token1_account); + self + } + /// The address that holds pool tokens for token_0 + #[inline(always)] + pub fn token0_vault( + &mut self, + token0_vault: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.token0_vault = Some(token0_vault); + self + } + /// The address that holds pool tokens for token_1 + #[inline(always)] + pub fn token1_vault( + &mut self, + token1_vault: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.token1_vault = Some(token1_vault); + self + } + /// token Program + #[inline(always)] + pub fn token_program( + &mut self, + token_program: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.token_program = Some(token_program); + self + } + /// Token program 2022 + #[inline(always)] + pub fn token_program2022( + &mut self, + token_program2022: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.token_program2022 = Some(token_program2022); + self + } + /// The mint of token_0 vault + #[inline(always)] + pub fn vault0_mint( + &mut self, + vault0_mint: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.vault0_mint = Some(vault0_mint); + self + } + /// The mint of token_1 vault + #[inline(always)] + pub fn vault1_mint( + &mut self, + vault1_mint: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.vault1_mint = Some(vault1_mint); + self + } + /// Lp token mint + #[inline(always)] + pub fn lp_mint(&mut self, lp_mint: &'b solana_account_info::AccountInfo<'a>) -> &mut Self { + self.instruction.lp_mint = Some(lp_mint); + self + } + #[inline(always)] + pub fn lp_token_amount(&mut self, lp_token_amount: u64) -> &mut Self { + self.instruction.lp_token_amount = Some(lp_token_amount); + self + } + #[inline(always)] + pub fn maximum_token0_amount(&mut self, maximum_token0_amount: u64) -> &mut Self { + self.instruction.maximum_token0_amount = Some(maximum_token0_amount); + self + } + #[inline(always)] + pub fn maximum_token1_amount(&mut self, maximum_token1_amount: u64) -> &mut Self { + self.instruction.maximum_token1_amount = Some(maximum_token1_amount); + self + } + /// Add an additional account to the instruction. + #[inline(always)] + pub fn add_remaining_account( + &mut self, + account: &'b solana_account_info::AccountInfo<'a>, + is_writable: bool, + is_signer: bool, + ) -> &mut Self { + self.instruction + .__remaining_accounts + .push((account, is_writable, is_signer)); + self + } + /// Add additional accounts to the instruction. + /// + /// Each account is represented by a tuple of the `AccountInfo`, a `bool` indicating whether the account is writable or not, + /// and a `bool` indicating whether the account is a signer or not. + #[inline(always)] + pub fn add_remaining_accounts( + &mut self, + accounts: &[(&'b solana_account_info::AccountInfo<'a>, bool, bool)], + ) -> &mut Self { + self.instruction + .__remaining_accounts + .extend_from_slice(accounts); + self + } + #[inline(always)] + pub fn invoke(&self) -> solana_program_error::ProgramResult { + self.invoke_signed(&[]) + } + #[allow(clippy::clone_on_copy)] + #[allow(clippy::vec_init_then_push)] + pub fn invoke_signed(&self, signers_seeds: &[&[&[u8]]]) -> solana_program_error::ProgramResult { + let args = DepositInstructionArgs { + lp_token_amount: self + .instruction + .lp_token_amount + .clone() + .expect("lp_token_amount is not set"), + maximum_token0_amount: self + .instruction + .maximum_token0_amount + .clone() + .expect("maximum_token0_amount is not set"), + maximum_token1_amount: self + .instruction + .maximum_token1_amount + .clone() + .expect("maximum_token1_amount is not set"), + }; + let instruction = DepositCpi { + __program: self.instruction.__program, + + owner: self.instruction.owner.expect("owner is not set"), + + authority: self.instruction.authority.expect("authority is not set"), + + pool_state: self.instruction.pool_state.expect("pool_state is not set"), + + owner_lp_token: self + .instruction + .owner_lp_token + .expect("owner_lp_token is not set"), + + token0_account: self + .instruction + .token0_account + .expect("token0_account is not set"), + + token1_account: self + .instruction + .token1_account + .expect("token1_account is not set"), + + token0_vault: self + .instruction + .token0_vault + .expect("token0_vault is not set"), + + token1_vault: self + .instruction + .token1_vault + .expect("token1_vault is not set"), + + token_program: self + .instruction + .token_program + .expect("token_program is not set"), + + token_program2022: self + .instruction + .token_program2022 + .expect("token_program2022 is not set"), + + vault0_mint: self + .instruction + .vault0_mint + .expect("vault0_mint is not set"), + + vault1_mint: self + .instruction + .vault1_mint + .expect("vault1_mint is not set"), + + lp_mint: self.instruction.lp_mint.expect("lp_mint is not set"), + __args: args, + }; + instruction.invoke_signed_with_remaining_accounts( + signers_seeds, + &self.instruction.__remaining_accounts, + ) + } +} + +#[derive(Clone, Debug)] +struct DepositCpiBuilderInstruction<'a, 'b> { + __program: &'b solana_account_info::AccountInfo<'a>, + owner: Option<&'b solana_account_info::AccountInfo<'a>>, + authority: Option<&'b solana_account_info::AccountInfo<'a>>, + pool_state: Option<&'b solana_account_info::AccountInfo<'a>>, + owner_lp_token: Option<&'b solana_account_info::AccountInfo<'a>>, + token0_account: Option<&'b solana_account_info::AccountInfo<'a>>, + token1_account: Option<&'b solana_account_info::AccountInfo<'a>>, + token0_vault: Option<&'b solana_account_info::AccountInfo<'a>>, + token1_vault: Option<&'b solana_account_info::AccountInfo<'a>>, + token_program: Option<&'b solana_account_info::AccountInfo<'a>>, + token_program2022: Option<&'b solana_account_info::AccountInfo<'a>>, + vault0_mint: Option<&'b solana_account_info::AccountInfo<'a>>, + vault1_mint: Option<&'b solana_account_info::AccountInfo<'a>>, + lp_mint: Option<&'b solana_account_info::AccountInfo<'a>>, + lp_token_amount: Option, + maximum_token0_amount: Option, + maximum_token1_amount: Option, + /// Additional instruction accounts `(AccountInfo, is_writable, is_signer)`. + __remaining_accounts: Vec<(&'b solana_account_info::AccountInfo<'a>, bool, bool)>, +} diff --git a/e2e/raydium-cpmm/src/generated/instructions/initialize.rs b/e2e/raydium-cpmm/src/generated/instructions/initialize.rs new file mode 100644 index 0000000..b7c4e2c --- /dev/null +++ b/e2e/raydium-cpmm/src/generated/instructions/initialize.rs @@ -0,0 +1,1177 @@ +//! This code was AUTOGENERATED using the codama library. +//! Please DO NOT EDIT THIS FILE, instead use visitors +//! to add features, then rerun codama to update it. +//! +//! +//! + +use borsh::BorshDeserialize; +use borsh::BorshSerialize; + +pub const INITIALIZE_DISCRIMINATOR: [u8; 8] = [175, 175, 109, 31, 13, 152, 155, 237]; + +/// Accounts. +#[derive(Debug)] +pub struct Initialize { + /// Address paying to create the pool. Can be anyone + pub creator: solana_address::Address, + /// Which config the pool belongs to. + pub amm_config: solana_address::Address, + /// pool vault and lp mint authority + pub authority: solana_address::Address, + /// PDA account: + /// seeds = [ + /// POOL_SEED.as_bytes(), + /// amm_config.key().as_ref(), + /// token_0_mint.key().as_ref(), + /// token_1_mint.key().as_ref(), + /// ], + /// + /// Or random account: must be signed by cli + pub pool_state: solana_address::Address, + /// Token_0 mint, the key must smaller than token_1 mint. + pub token0_mint: solana_address::Address, + /// Token_1 mint, the key must grater then token_0 mint. + pub token1_mint: solana_address::Address, + /// pool lp mint + pub lp_mint: solana_address::Address, + /// payer token0 account + pub creator_token0: solana_address::Address, + /// creator token1 account + pub creator_token1: solana_address::Address, + /// creator lp token account + pub creator_lp_token: solana_address::Address, + + pub token0_vault: solana_address::Address, + + pub token1_vault: solana_address::Address, + /// create pool fee account + pub create_pool_fee: solana_address::Address, + /// an account to store oracle observations + pub observation_state: solana_address::Address, + /// Program to create mint account and mint tokens + pub token_program: solana_address::Address, + /// Spl token program or token program 2022 + pub token0_program: solana_address::Address, + /// Spl token program or token program 2022 + pub token1_program: solana_address::Address, + /// Program to create an ATA for receiving position NFT + pub associated_token_program: solana_address::Address, + /// To create a new program account + pub system_program: solana_address::Address, + /// Sysvar for program account + pub rent: solana_address::Address, +} + +impl Initialize { + pub fn instruction(&self, args: InitializeInstructionArgs) -> solana_instruction::Instruction { + self.instruction_with_remaining_accounts(args, &[]) + } + #[allow(clippy::arithmetic_side_effects)] + #[allow(clippy::vec_init_then_push)] + pub fn instruction_with_remaining_accounts( + &self, + args: InitializeInstructionArgs, + remaining_accounts: &[solana_instruction::AccountMeta], + ) -> solana_instruction::Instruction { + let mut accounts = Vec::with_capacity(20 + remaining_accounts.len()); + accounts.push(solana_instruction::AccountMeta::new(self.creator, true)); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.amm_config, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.authority, + false, + )); + accounts.push(solana_instruction::AccountMeta::new(self.pool_state, false)); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.token0_mint, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.token1_mint, + false, + )); + accounts.push(solana_instruction::AccountMeta::new(self.lp_mint, false)); + accounts.push(solana_instruction::AccountMeta::new( + self.creator_token0, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + self.creator_token1, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + self.creator_lp_token, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + self.token0_vault, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + self.token1_vault, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + self.create_pool_fee, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + self.observation_state, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.token_program, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.token0_program, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.token1_program, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.associated_token_program, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.system_program, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.rent, false, + )); + accounts.extend_from_slice(remaining_accounts); + let mut data = InitializeInstructionData::new().try_to_vec().unwrap(); + let mut args = args.try_to_vec().unwrap(); + data.append(&mut args); + + solana_instruction::Instruction { + program_id: crate::RAYDIUM_CP_SWAP_ID, + accounts, + data, + } + } +} + +#[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] +pub struct InitializeInstructionData { + discriminator: [u8; 8], +} + +impl InitializeInstructionData { + pub fn new() -> Self { + Self { + discriminator: [175, 175, 109, 31, 13, 152, 155, 237], + } + } + + pub(crate) fn try_to_vec(&self) -> Result, std::io::Error> { + borsh::to_vec(self) + } +} + +impl Default for InitializeInstructionData { + fn default() -> Self { + Self::new() + } +} + +#[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] +pub struct InitializeInstructionArgs { + pub init_amount0: u64, + pub init_amount1: u64, + pub open_time: u64, +} + +impl InitializeInstructionArgs { + pub(crate) fn try_to_vec(&self) -> Result, std::io::Error> { + borsh::to_vec(self) + } +} + +/// Instruction builder for `Initialize`. +/// +/// ### Accounts: +/// +/// 0. `[writable, signer]` creator +/// 1. `[]` amm_config +/// 2. `[]` authority +/// 3. `[writable]` pool_state +/// 4. `[]` token0_mint +/// 5. `[]` token1_mint +/// 6. `[writable]` lp_mint +/// 7. `[writable]` creator_token0 +/// 8. `[writable]` creator_token1 +/// 9. `[writable]` creator_lp_token +/// 10. `[writable]` token0_vault +/// 11. `[writable]` token1_vault +/// 12. `[writable, optional]` create_pool_fee (default to `DNXgeM9EiiaAbaWvwjHj9fQQLAX5ZsfHyvmYUNRAdNC8`) +/// 13. `[writable]` observation_state +/// 14. `[optional]` token_program (default to `TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA`) +/// 15. `[]` token0_program +/// 16. `[]` token1_program +/// 17. `[optional]` associated_token_program (default to `ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL`) +/// 18. `[optional]` system_program (default to `11111111111111111111111111111111`) +/// 19. `[optional]` rent (default to `SysvarRent111111111111111111111111111111111`) +#[derive(Clone, Debug, Default)] +pub struct InitializeBuilder { + creator: Option, + amm_config: Option, + authority: Option, + pool_state: Option, + token0_mint: Option, + token1_mint: Option, + lp_mint: Option, + creator_token0: Option, + creator_token1: Option, + creator_lp_token: Option, + token0_vault: Option, + token1_vault: Option, + create_pool_fee: Option, + observation_state: Option, + token_program: Option, + token0_program: Option, + token1_program: Option, + associated_token_program: Option, + system_program: Option, + rent: Option, + init_amount0: Option, + init_amount1: Option, + open_time: Option, + __remaining_accounts: Vec, +} + +impl InitializeBuilder { + pub fn new() -> Self { + Self::default() + } + /// Address paying to create the pool. Can be anyone + #[inline(always)] + pub fn creator(&mut self, creator: solana_address::Address) -> &mut Self { + self.creator = Some(creator); + self + } + /// Which config the pool belongs to. + #[inline(always)] + pub fn amm_config(&mut self, amm_config: solana_address::Address) -> &mut Self { + self.amm_config = Some(amm_config); + self + } + /// pool vault and lp mint authority + #[inline(always)] + pub fn authority(&mut self, authority: solana_address::Address) -> &mut Self { + self.authority = Some(authority); + self + } + /// PDA account: + /// seeds = [ + /// POOL_SEED.as_bytes(), + /// amm_config.key().as_ref(), + /// token_0_mint.key().as_ref(), + /// token_1_mint.key().as_ref(), + /// ], + /// + /// Or random account: must be signed by cli + #[inline(always)] + pub fn pool_state(&mut self, pool_state: solana_address::Address) -> &mut Self { + self.pool_state = Some(pool_state); + self + } + /// Token_0 mint, the key must smaller than token_1 mint. + #[inline(always)] + pub fn token0_mint(&mut self, token0_mint: solana_address::Address) -> &mut Self { + self.token0_mint = Some(token0_mint); + self + } + /// Token_1 mint, the key must grater then token_0 mint. + #[inline(always)] + pub fn token1_mint(&mut self, token1_mint: solana_address::Address) -> &mut Self { + self.token1_mint = Some(token1_mint); + self + } + /// pool lp mint + #[inline(always)] + pub fn lp_mint(&mut self, lp_mint: solana_address::Address) -> &mut Self { + self.lp_mint = Some(lp_mint); + self + } + /// payer token0 account + #[inline(always)] + pub fn creator_token0(&mut self, creator_token0: solana_address::Address) -> &mut Self { + self.creator_token0 = Some(creator_token0); + self + } + /// creator token1 account + #[inline(always)] + pub fn creator_token1(&mut self, creator_token1: solana_address::Address) -> &mut Self { + self.creator_token1 = Some(creator_token1); + self + } + /// creator lp token account + #[inline(always)] + pub fn creator_lp_token(&mut self, creator_lp_token: solana_address::Address) -> &mut Self { + self.creator_lp_token = Some(creator_lp_token); + self + } + #[inline(always)] + pub fn token0_vault(&mut self, token0_vault: solana_address::Address) -> &mut Self { + self.token0_vault = Some(token0_vault); + self + } + #[inline(always)] + pub fn token1_vault(&mut self, token1_vault: solana_address::Address) -> &mut Self { + self.token1_vault = Some(token1_vault); + self + } + /// `[optional account, default to 'DNXgeM9EiiaAbaWvwjHj9fQQLAX5ZsfHyvmYUNRAdNC8']` + /// create pool fee account + #[inline(always)] + pub fn create_pool_fee(&mut self, create_pool_fee: solana_address::Address) -> &mut Self { + self.create_pool_fee = Some(create_pool_fee); + self + } + /// an account to store oracle observations + #[inline(always)] + pub fn observation_state(&mut self, observation_state: solana_address::Address) -> &mut Self { + self.observation_state = Some(observation_state); + self + } + /// `[optional account, default to 'TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA']` + /// Program to create mint account and mint tokens + #[inline(always)] + pub fn token_program(&mut self, token_program: solana_address::Address) -> &mut Self { + self.token_program = Some(token_program); + self + } + /// Spl token program or token program 2022 + #[inline(always)] + pub fn token0_program(&mut self, token0_program: solana_address::Address) -> &mut Self { + self.token0_program = Some(token0_program); + self + } + /// Spl token program or token program 2022 + #[inline(always)] + pub fn token1_program(&mut self, token1_program: solana_address::Address) -> &mut Self { + self.token1_program = Some(token1_program); + self + } + /// `[optional account, default to 'ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL']` + /// Program to create an ATA for receiving position NFT + #[inline(always)] + pub fn associated_token_program( + &mut self, + associated_token_program: solana_address::Address, + ) -> &mut Self { + self.associated_token_program = Some(associated_token_program); + self + } + /// `[optional account, default to '11111111111111111111111111111111']` + /// To create a new program account + #[inline(always)] + pub fn system_program(&mut self, system_program: solana_address::Address) -> &mut Self { + self.system_program = Some(system_program); + self + } + /// `[optional account, default to 'SysvarRent111111111111111111111111111111111']` + /// Sysvar for program account + #[inline(always)] + pub fn rent(&mut self, rent: solana_address::Address) -> &mut Self { + self.rent = Some(rent); + self + } + #[inline(always)] + pub fn init_amount0(&mut self, init_amount0: u64) -> &mut Self { + self.init_amount0 = Some(init_amount0); + self + } + #[inline(always)] + pub fn init_amount1(&mut self, init_amount1: u64) -> &mut Self { + self.init_amount1 = Some(init_amount1); + self + } + #[inline(always)] + pub fn open_time(&mut self, open_time: u64) -> &mut Self { + self.open_time = Some(open_time); + self + } + /// Add an additional account to the instruction. + #[inline(always)] + pub fn add_remaining_account(&mut self, account: solana_instruction::AccountMeta) -> &mut Self { + self.__remaining_accounts.push(account); + self + } + /// Add additional accounts to the instruction. + #[inline(always)] + pub fn add_remaining_accounts( + &mut self, + accounts: &[solana_instruction::AccountMeta], + ) -> &mut Self { + self.__remaining_accounts.extend_from_slice(accounts); + self + } + #[allow(clippy::clone_on_copy)] + pub fn instruction(&self) -> solana_instruction::Instruction { + let accounts = Initialize { + creator: self.creator.expect("creator is not set"), + amm_config: self.amm_config.expect("amm_config is not set"), + authority: self.authority.expect("authority is not set"), + pool_state: self.pool_state.expect("pool_state is not set"), + token0_mint: self.token0_mint.expect("token0_mint is not set"), + token1_mint: self.token1_mint.expect("token1_mint is not set"), + lp_mint: self.lp_mint.expect("lp_mint is not set"), + creator_token0: self.creator_token0.expect("creator_token0 is not set"), + creator_token1: self.creator_token1.expect("creator_token1 is not set"), + creator_lp_token: self.creator_lp_token.expect("creator_lp_token is not set"), + token0_vault: self.token0_vault.expect("token0_vault is not set"), + token1_vault: self.token1_vault.expect("token1_vault is not set"), + create_pool_fee: self.create_pool_fee.unwrap_or(solana_address::address!( + "DNXgeM9EiiaAbaWvwjHj9fQQLAX5ZsfHyvmYUNRAdNC8" + )), + observation_state: self + .observation_state + .expect("observation_state is not set"), + token_program: self.token_program.unwrap_or(solana_address::address!( + "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA" + )), + token0_program: self.token0_program.expect("token0_program is not set"), + token1_program: self.token1_program.expect("token1_program is not set"), + associated_token_program: self.associated_token_program.unwrap_or( + solana_address::address!("ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL"), + ), + system_program: self + .system_program + .unwrap_or(solana_address::address!("11111111111111111111111111111111")), + rent: self.rent.unwrap_or(solana_address::address!( + "SysvarRent111111111111111111111111111111111" + )), + }; + let args = InitializeInstructionArgs { + init_amount0: self.init_amount0.clone().expect("init_amount0 is not set"), + init_amount1: self.init_amount1.clone().expect("init_amount1 is not set"), + open_time: self.open_time.clone().expect("open_time is not set"), + }; + + accounts.instruction_with_remaining_accounts(args, &self.__remaining_accounts) + } +} + +/// `initialize` CPI accounts. +pub struct InitializeCpiAccounts<'a, 'b> { + /// Address paying to create the pool. Can be anyone + pub creator: &'b solana_account_info::AccountInfo<'a>, + /// Which config the pool belongs to. + pub amm_config: &'b solana_account_info::AccountInfo<'a>, + /// pool vault and lp mint authority + pub authority: &'b solana_account_info::AccountInfo<'a>, + /// PDA account: + /// seeds = [ + /// POOL_SEED.as_bytes(), + /// amm_config.key().as_ref(), + /// token_0_mint.key().as_ref(), + /// token_1_mint.key().as_ref(), + /// ], + /// + /// Or random account: must be signed by cli + pub pool_state: &'b solana_account_info::AccountInfo<'a>, + /// Token_0 mint, the key must smaller than token_1 mint. + pub token0_mint: &'b solana_account_info::AccountInfo<'a>, + /// Token_1 mint, the key must grater then token_0 mint. + pub token1_mint: &'b solana_account_info::AccountInfo<'a>, + /// pool lp mint + pub lp_mint: &'b solana_account_info::AccountInfo<'a>, + /// payer token0 account + pub creator_token0: &'b solana_account_info::AccountInfo<'a>, + /// creator token1 account + pub creator_token1: &'b solana_account_info::AccountInfo<'a>, + /// creator lp token account + pub creator_lp_token: &'b solana_account_info::AccountInfo<'a>, + + pub token0_vault: &'b solana_account_info::AccountInfo<'a>, + + pub token1_vault: &'b solana_account_info::AccountInfo<'a>, + /// create pool fee account + pub create_pool_fee: &'b solana_account_info::AccountInfo<'a>, + /// an account to store oracle observations + pub observation_state: &'b solana_account_info::AccountInfo<'a>, + /// Program to create mint account and mint tokens + pub token_program: &'b solana_account_info::AccountInfo<'a>, + /// Spl token program or token program 2022 + pub token0_program: &'b solana_account_info::AccountInfo<'a>, + /// Spl token program or token program 2022 + pub token1_program: &'b solana_account_info::AccountInfo<'a>, + /// Program to create an ATA for receiving position NFT + pub associated_token_program: &'b solana_account_info::AccountInfo<'a>, + /// To create a new program account + pub system_program: &'b solana_account_info::AccountInfo<'a>, + /// Sysvar for program account + pub rent: &'b solana_account_info::AccountInfo<'a>, +} + +/// `initialize` CPI instruction. +pub struct InitializeCpi<'a, 'b> { + /// The program to invoke. + pub __program: &'b solana_account_info::AccountInfo<'a>, + /// Address paying to create the pool. Can be anyone + pub creator: &'b solana_account_info::AccountInfo<'a>, + /// Which config the pool belongs to. + pub amm_config: &'b solana_account_info::AccountInfo<'a>, + /// pool vault and lp mint authority + pub authority: &'b solana_account_info::AccountInfo<'a>, + /// PDA account: + /// seeds = [ + /// POOL_SEED.as_bytes(), + /// amm_config.key().as_ref(), + /// token_0_mint.key().as_ref(), + /// token_1_mint.key().as_ref(), + /// ], + /// + /// Or random account: must be signed by cli + pub pool_state: &'b solana_account_info::AccountInfo<'a>, + /// Token_0 mint, the key must smaller than token_1 mint. + pub token0_mint: &'b solana_account_info::AccountInfo<'a>, + /// Token_1 mint, the key must grater then token_0 mint. + pub token1_mint: &'b solana_account_info::AccountInfo<'a>, + /// pool lp mint + pub lp_mint: &'b solana_account_info::AccountInfo<'a>, + /// payer token0 account + pub creator_token0: &'b solana_account_info::AccountInfo<'a>, + /// creator token1 account + pub creator_token1: &'b solana_account_info::AccountInfo<'a>, + /// creator lp token account + pub creator_lp_token: &'b solana_account_info::AccountInfo<'a>, + + pub token0_vault: &'b solana_account_info::AccountInfo<'a>, + + pub token1_vault: &'b solana_account_info::AccountInfo<'a>, + /// create pool fee account + pub create_pool_fee: &'b solana_account_info::AccountInfo<'a>, + /// an account to store oracle observations + pub observation_state: &'b solana_account_info::AccountInfo<'a>, + /// Program to create mint account and mint tokens + pub token_program: &'b solana_account_info::AccountInfo<'a>, + /// Spl token program or token program 2022 + pub token0_program: &'b solana_account_info::AccountInfo<'a>, + /// Spl token program or token program 2022 + pub token1_program: &'b solana_account_info::AccountInfo<'a>, + /// Program to create an ATA for receiving position NFT + pub associated_token_program: &'b solana_account_info::AccountInfo<'a>, + /// To create a new program account + pub system_program: &'b solana_account_info::AccountInfo<'a>, + /// Sysvar for program account + pub rent: &'b solana_account_info::AccountInfo<'a>, + /// The arguments for the instruction. + pub __args: InitializeInstructionArgs, +} + +impl<'a, 'b> InitializeCpi<'a, 'b> { + pub fn new( + program: &'b solana_account_info::AccountInfo<'a>, + accounts: InitializeCpiAccounts<'a, 'b>, + args: InitializeInstructionArgs, + ) -> Self { + Self { + __program: program, + creator: accounts.creator, + amm_config: accounts.amm_config, + authority: accounts.authority, + pool_state: accounts.pool_state, + token0_mint: accounts.token0_mint, + token1_mint: accounts.token1_mint, + lp_mint: accounts.lp_mint, + creator_token0: accounts.creator_token0, + creator_token1: accounts.creator_token1, + creator_lp_token: accounts.creator_lp_token, + token0_vault: accounts.token0_vault, + token1_vault: accounts.token1_vault, + create_pool_fee: accounts.create_pool_fee, + observation_state: accounts.observation_state, + token_program: accounts.token_program, + token0_program: accounts.token0_program, + token1_program: accounts.token1_program, + associated_token_program: accounts.associated_token_program, + system_program: accounts.system_program, + rent: accounts.rent, + __args: args, + } + } + #[inline(always)] + pub fn invoke(&self) -> solana_program_error::ProgramResult { + self.invoke_signed_with_remaining_accounts(&[], &[]) + } + #[inline(always)] + pub fn invoke_with_remaining_accounts( + &self, + remaining_accounts: &[(&'b solana_account_info::AccountInfo<'a>, bool, bool)], + ) -> solana_program_error::ProgramResult { + self.invoke_signed_with_remaining_accounts(&[], remaining_accounts) + } + #[inline(always)] + pub fn invoke_signed(&self, signers_seeds: &[&[&[u8]]]) -> solana_program_error::ProgramResult { + self.invoke_signed_with_remaining_accounts(signers_seeds, &[]) + } + #[allow(clippy::arithmetic_side_effects)] + #[allow(clippy::clone_on_copy)] + #[allow(clippy::vec_init_then_push)] + pub fn invoke_signed_with_remaining_accounts( + &self, + signers_seeds: &[&[&[u8]]], + remaining_accounts: &[(&'b solana_account_info::AccountInfo<'a>, bool, bool)], + ) -> solana_program_error::ProgramResult { + let mut accounts = Vec::with_capacity(20 + remaining_accounts.len()); + accounts.push(solana_instruction::AccountMeta::new( + *self.creator.key, + true, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.amm_config.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.authority.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + *self.pool_state.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.token0_mint.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.token1_mint.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + *self.lp_mint.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + *self.creator_token0.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + *self.creator_token1.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + *self.creator_lp_token.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + *self.token0_vault.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + *self.token1_vault.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + *self.create_pool_fee.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + *self.observation_state.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.token_program.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.token0_program.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.token1_program.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.associated_token_program.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.system_program.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.rent.key, + false, + )); + remaining_accounts.iter().for_each(|remaining_account| { + accounts.push(solana_instruction::AccountMeta { + pubkey: *remaining_account.0.key, + is_signer: remaining_account.1, + is_writable: remaining_account.2, + }) + }); + let mut data = InitializeInstructionData::new().try_to_vec().unwrap(); + let mut args = self.__args.try_to_vec().unwrap(); + data.append(&mut args); + + let instruction = solana_instruction::Instruction { + program_id: crate::RAYDIUM_CP_SWAP_ID, + accounts, + data, + }; + let mut account_infos = Vec::with_capacity(21 + remaining_accounts.len()); + account_infos.push(self.__program.clone()); + account_infos.push(self.creator.clone()); + account_infos.push(self.amm_config.clone()); + account_infos.push(self.authority.clone()); + account_infos.push(self.pool_state.clone()); + account_infos.push(self.token0_mint.clone()); + account_infos.push(self.token1_mint.clone()); + account_infos.push(self.lp_mint.clone()); + account_infos.push(self.creator_token0.clone()); + account_infos.push(self.creator_token1.clone()); + account_infos.push(self.creator_lp_token.clone()); + account_infos.push(self.token0_vault.clone()); + account_infos.push(self.token1_vault.clone()); + account_infos.push(self.create_pool_fee.clone()); + account_infos.push(self.observation_state.clone()); + account_infos.push(self.token_program.clone()); + account_infos.push(self.token0_program.clone()); + account_infos.push(self.token1_program.clone()); + account_infos.push(self.associated_token_program.clone()); + account_infos.push(self.system_program.clone()); + account_infos.push(self.rent.clone()); + remaining_accounts + .iter() + .for_each(|remaining_account| account_infos.push(remaining_account.0.clone())); + + if signers_seeds.is_empty() { + solana_cpi::invoke(&instruction, &account_infos) + } else { + solana_cpi::invoke_signed(&instruction, &account_infos, signers_seeds) + } + } +} + +/// Instruction builder for `Initialize` via CPI. +/// +/// ### Accounts: +/// +/// 0. `[writable, signer]` creator +/// 1. `[]` amm_config +/// 2. `[]` authority +/// 3. `[writable]` pool_state +/// 4. `[]` token0_mint +/// 5. `[]` token1_mint +/// 6. `[writable]` lp_mint +/// 7. `[writable]` creator_token0 +/// 8. `[writable]` creator_token1 +/// 9. `[writable]` creator_lp_token +/// 10. `[writable]` token0_vault +/// 11. `[writable]` token1_vault +/// 12. `[writable]` create_pool_fee +/// 13. `[writable]` observation_state +/// 14. `[]` token_program +/// 15. `[]` token0_program +/// 16. `[]` token1_program +/// 17. `[]` associated_token_program +/// 18. `[]` system_program +/// 19. `[]` rent +#[derive(Clone, Debug)] +pub struct InitializeCpiBuilder<'a, 'b> { + instruction: Box>, +} + +impl<'a, 'b> InitializeCpiBuilder<'a, 'b> { + pub fn new(program: &'b solana_account_info::AccountInfo<'a>) -> Self { + let instruction = Box::new(InitializeCpiBuilderInstruction { + __program: program, + creator: None, + amm_config: None, + authority: None, + pool_state: None, + token0_mint: None, + token1_mint: None, + lp_mint: None, + creator_token0: None, + creator_token1: None, + creator_lp_token: None, + token0_vault: None, + token1_vault: None, + create_pool_fee: None, + observation_state: None, + token_program: None, + token0_program: None, + token1_program: None, + associated_token_program: None, + system_program: None, + rent: None, + init_amount0: None, + init_amount1: None, + open_time: None, + __remaining_accounts: Vec::new(), + }); + Self { instruction } + } + /// Address paying to create the pool. Can be anyone + #[inline(always)] + pub fn creator(&mut self, creator: &'b solana_account_info::AccountInfo<'a>) -> &mut Self { + self.instruction.creator = Some(creator); + self + } + /// Which config the pool belongs to. + #[inline(always)] + pub fn amm_config( + &mut self, + amm_config: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.amm_config = Some(amm_config); + self + } + /// pool vault and lp mint authority + #[inline(always)] + pub fn authority(&mut self, authority: &'b solana_account_info::AccountInfo<'a>) -> &mut Self { + self.instruction.authority = Some(authority); + self + } + /// PDA account: + /// seeds = [ + /// POOL_SEED.as_bytes(), + /// amm_config.key().as_ref(), + /// token_0_mint.key().as_ref(), + /// token_1_mint.key().as_ref(), + /// ], + /// + /// Or random account: must be signed by cli + #[inline(always)] + pub fn pool_state( + &mut self, + pool_state: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.pool_state = Some(pool_state); + self + } + /// Token_0 mint, the key must smaller than token_1 mint. + #[inline(always)] + pub fn token0_mint( + &mut self, + token0_mint: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.token0_mint = Some(token0_mint); + self + } + /// Token_1 mint, the key must grater then token_0 mint. + #[inline(always)] + pub fn token1_mint( + &mut self, + token1_mint: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.token1_mint = Some(token1_mint); + self + } + /// pool lp mint + #[inline(always)] + pub fn lp_mint(&mut self, lp_mint: &'b solana_account_info::AccountInfo<'a>) -> &mut Self { + self.instruction.lp_mint = Some(lp_mint); + self + } + /// payer token0 account + #[inline(always)] + pub fn creator_token0( + &mut self, + creator_token0: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.creator_token0 = Some(creator_token0); + self + } + /// creator token1 account + #[inline(always)] + pub fn creator_token1( + &mut self, + creator_token1: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.creator_token1 = Some(creator_token1); + self + } + /// creator lp token account + #[inline(always)] + pub fn creator_lp_token( + &mut self, + creator_lp_token: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.creator_lp_token = Some(creator_lp_token); + self + } + #[inline(always)] + pub fn token0_vault( + &mut self, + token0_vault: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.token0_vault = Some(token0_vault); + self + } + #[inline(always)] + pub fn token1_vault( + &mut self, + token1_vault: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.token1_vault = Some(token1_vault); + self + } + /// create pool fee account + #[inline(always)] + pub fn create_pool_fee( + &mut self, + create_pool_fee: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.create_pool_fee = Some(create_pool_fee); + self + } + /// an account to store oracle observations + #[inline(always)] + pub fn observation_state( + &mut self, + observation_state: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.observation_state = Some(observation_state); + self + } + /// Program to create mint account and mint tokens + #[inline(always)] + pub fn token_program( + &mut self, + token_program: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.token_program = Some(token_program); + self + } + /// Spl token program or token program 2022 + #[inline(always)] + pub fn token0_program( + &mut self, + token0_program: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.token0_program = Some(token0_program); + self + } + /// Spl token program or token program 2022 + #[inline(always)] + pub fn token1_program( + &mut self, + token1_program: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.token1_program = Some(token1_program); + self + } + /// Program to create an ATA for receiving position NFT + #[inline(always)] + pub fn associated_token_program( + &mut self, + associated_token_program: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.associated_token_program = Some(associated_token_program); + self + } + /// To create a new program account + #[inline(always)] + pub fn system_program( + &mut self, + system_program: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.system_program = Some(system_program); + self + } + /// Sysvar for program account + #[inline(always)] + pub fn rent(&mut self, rent: &'b solana_account_info::AccountInfo<'a>) -> &mut Self { + self.instruction.rent = Some(rent); + self + } + #[inline(always)] + pub fn init_amount0(&mut self, init_amount0: u64) -> &mut Self { + self.instruction.init_amount0 = Some(init_amount0); + self + } + #[inline(always)] + pub fn init_amount1(&mut self, init_amount1: u64) -> &mut Self { + self.instruction.init_amount1 = Some(init_amount1); + self + } + #[inline(always)] + pub fn open_time(&mut self, open_time: u64) -> &mut Self { + self.instruction.open_time = Some(open_time); + self + } + /// Add an additional account to the instruction. + #[inline(always)] + pub fn add_remaining_account( + &mut self, + account: &'b solana_account_info::AccountInfo<'a>, + is_writable: bool, + is_signer: bool, + ) -> &mut Self { + self.instruction + .__remaining_accounts + .push((account, is_writable, is_signer)); + self + } + /// Add additional accounts to the instruction. + /// + /// Each account is represented by a tuple of the `AccountInfo`, a `bool` indicating whether the account is writable or not, + /// and a `bool` indicating whether the account is a signer or not. + #[inline(always)] + pub fn add_remaining_accounts( + &mut self, + accounts: &[(&'b solana_account_info::AccountInfo<'a>, bool, bool)], + ) -> &mut Self { + self.instruction + .__remaining_accounts + .extend_from_slice(accounts); + self + } + #[inline(always)] + pub fn invoke(&self) -> solana_program_error::ProgramResult { + self.invoke_signed(&[]) + } + #[allow(clippy::clone_on_copy)] + #[allow(clippy::vec_init_then_push)] + pub fn invoke_signed(&self, signers_seeds: &[&[&[u8]]]) -> solana_program_error::ProgramResult { + let args = InitializeInstructionArgs { + init_amount0: self + .instruction + .init_amount0 + .clone() + .expect("init_amount0 is not set"), + init_amount1: self + .instruction + .init_amount1 + .clone() + .expect("init_amount1 is not set"), + open_time: self + .instruction + .open_time + .clone() + .expect("open_time is not set"), + }; + let instruction = InitializeCpi { + __program: self.instruction.__program, + + creator: self.instruction.creator.expect("creator is not set"), + + amm_config: self.instruction.amm_config.expect("amm_config is not set"), + + authority: self.instruction.authority.expect("authority is not set"), + + pool_state: self.instruction.pool_state.expect("pool_state is not set"), + + token0_mint: self + .instruction + .token0_mint + .expect("token0_mint is not set"), + + token1_mint: self + .instruction + .token1_mint + .expect("token1_mint is not set"), + + lp_mint: self.instruction.lp_mint.expect("lp_mint is not set"), + + creator_token0: self + .instruction + .creator_token0 + .expect("creator_token0 is not set"), + + creator_token1: self + .instruction + .creator_token1 + .expect("creator_token1 is not set"), + + creator_lp_token: self + .instruction + .creator_lp_token + .expect("creator_lp_token is not set"), + + token0_vault: self + .instruction + .token0_vault + .expect("token0_vault is not set"), + + token1_vault: self + .instruction + .token1_vault + .expect("token1_vault is not set"), + + create_pool_fee: self + .instruction + .create_pool_fee + .expect("create_pool_fee is not set"), + + observation_state: self + .instruction + .observation_state + .expect("observation_state is not set"), + + token_program: self + .instruction + .token_program + .expect("token_program is not set"), + + token0_program: self + .instruction + .token0_program + .expect("token0_program is not set"), + + token1_program: self + .instruction + .token1_program + .expect("token1_program is not set"), + + associated_token_program: self + .instruction + .associated_token_program + .expect("associated_token_program is not set"), + + system_program: self + .instruction + .system_program + .expect("system_program is not set"), + + rent: self.instruction.rent.expect("rent is not set"), + __args: args, + }; + instruction.invoke_signed_with_remaining_accounts( + signers_seeds, + &self.instruction.__remaining_accounts, + ) + } +} + +#[derive(Clone, Debug)] +struct InitializeCpiBuilderInstruction<'a, 'b> { + __program: &'b solana_account_info::AccountInfo<'a>, + creator: Option<&'b solana_account_info::AccountInfo<'a>>, + amm_config: Option<&'b solana_account_info::AccountInfo<'a>>, + authority: Option<&'b solana_account_info::AccountInfo<'a>>, + pool_state: Option<&'b solana_account_info::AccountInfo<'a>>, + token0_mint: Option<&'b solana_account_info::AccountInfo<'a>>, + token1_mint: Option<&'b solana_account_info::AccountInfo<'a>>, + lp_mint: Option<&'b solana_account_info::AccountInfo<'a>>, + creator_token0: Option<&'b solana_account_info::AccountInfo<'a>>, + creator_token1: Option<&'b solana_account_info::AccountInfo<'a>>, + creator_lp_token: Option<&'b solana_account_info::AccountInfo<'a>>, + token0_vault: Option<&'b solana_account_info::AccountInfo<'a>>, + token1_vault: Option<&'b solana_account_info::AccountInfo<'a>>, + create_pool_fee: Option<&'b solana_account_info::AccountInfo<'a>>, + observation_state: Option<&'b solana_account_info::AccountInfo<'a>>, + token_program: Option<&'b solana_account_info::AccountInfo<'a>>, + token0_program: Option<&'b solana_account_info::AccountInfo<'a>>, + token1_program: Option<&'b solana_account_info::AccountInfo<'a>>, + associated_token_program: Option<&'b solana_account_info::AccountInfo<'a>>, + system_program: Option<&'b solana_account_info::AccountInfo<'a>>, + rent: Option<&'b solana_account_info::AccountInfo<'a>>, + init_amount0: Option, + init_amount1: Option, + open_time: Option, + /// Additional instruction accounts `(AccountInfo, is_writable, is_signer)`. + __remaining_accounts: Vec<(&'b solana_account_info::AccountInfo<'a>, bool, bool)>, +} diff --git a/e2e/raydium-cpmm/src/generated/instructions/mod.rs b/e2e/raydium-cpmm/src/generated/instructions/mod.rs new file mode 100644 index 0000000..3520d1a --- /dev/null +++ b/e2e/raydium-cpmm/src/generated/instructions/mod.rs @@ -0,0 +1,28 @@ +//! This code was AUTOGENERATED using the codama library. +//! Please DO NOT EDIT THIS FILE, instead use visitors +//! to add features, then rerun codama to update it. +//! +//! +//! + +pub(crate) mod r#collect_fund_fee; +pub(crate) mod r#collect_protocol_fee; +pub(crate) mod r#create_amm_config; +pub(crate) mod r#deposit; +pub(crate) mod r#initialize; +pub(crate) mod r#swap_base_input; +pub(crate) mod r#swap_base_output; +pub(crate) mod r#update_amm_config; +pub(crate) mod r#update_pool_status; +pub(crate) mod r#withdraw; + +pub use self::r#collect_fund_fee::*; +pub use self::r#collect_protocol_fee::*; +pub use self::r#create_amm_config::*; +pub use self::r#deposit::*; +pub use self::r#initialize::*; +pub use self::r#swap_base_input::*; +pub use self::r#swap_base_output::*; +pub use self::r#update_amm_config::*; +pub use self::r#update_pool_status::*; +pub use self::r#withdraw::*; diff --git a/e2e/raydium-cpmm/src/generated/instructions/swap_base_input.rs b/e2e/raydium-cpmm/src/generated/instructions/swap_base_input.rs new file mode 100644 index 0000000..910a24c --- /dev/null +++ b/e2e/raydium-cpmm/src/generated/instructions/swap_base_input.rs @@ -0,0 +1,853 @@ +//! This code was AUTOGENERATED using the codama library. +//! Please DO NOT EDIT THIS FILE, instead use visitors +//! to add features, then rerun codama to update it. +//! +//! +//! + +use borsh::BorshDeserialize; +use borsh::BorshSerialize; + +pub const SWAP_BASE_INPUT_DISCRIMINATOR: [u8; 8] = [143, 190, 90, 218, 196, 30, 51, 222]; + +/// Accounts. +#[derive(Debug)] +pub struct SwapBaseInput { + /// The user performing the swap + pub payer: solana_address::Address, + + pub authority: solana_address::Address, + /// The factory state to read protocol fees + pub amm_config: solana_address::Address, + /// The program account of the pool in which the swap will be performed + pub pool_state: solana_address::Address, + /// The user token account for input token + pub input_token_account: solana_address::Address, + /// The user token account for output token + pub output_token_account: solana_address::Address, + /// The vault token account for input token + pub input_vault: solana_address::Address, + /// The vault token account for output token + pub output_vault: solana_address::Address, + /// SPL program for input token transfers + pub input_token_program: solana_address::Address, + /// SPL program for output token transfers + pub output_token_program: solana_address::Address, + /// The mint of input token + pub input_token_mint: solana_address::Address, + /// The mint of output token + pub output_token_mint: solana_address::Address, + /// The program account for the most recent oracle observation + pub observation_state: solana_address::Address, +} + +impl SwapBaseInput { + pub fn instruction( + &self, + args: SwapBaseInputInstructionArgs, + ) -> solana_instruction::Instruction { + self.instruction_with_remaining_accounts(args, &[]) + } + #[allow(clippy::arithmetic_side_effects)] + #[allow(clippy::vec_init_then_push)] + pub fn instruction_with_remaining_accounts( + &self, + args: SwapBaseInputInstructionArgs, + remaining_accounts: &[solana_instruction::AccountMeta], + ) -> solana_instruction::Instruction { + let mut accounts = Vec::with_capacity(13 + remaining_accounts.len()); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.payer, true, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.authority, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.amm_config, + false, + )); + accounts.push(solana_instruction::AccountMeta::new(self.pool_state, false)); + accounts.push(solana_instruction::AccountMeta::new( + self.input_token_account, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + self.output_token_account, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + self.input_vault, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + self.output_vault, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.input_token_program, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.output_token_program, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.input_token_mint, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.output_token_mint, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + self.observation_state, + false, + )); + accounts.extend_from_slice(remaining_accounts); + let mut data = SwapBaseInputInstructionData::new().try_to_vec().unwrap(); + let mut args = args.try_to_vec().unwrap(); + data.append(&mut args); + + solana_instruction::Instruction { + program_id: crate::RAYDIUM_CP_SWAP_ID, + accounts, + data, + } + } +} + +#[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] +pub struct SwapBaseInputInstructionData { + discriminator: [u8; 8], +} + +impl SwapBaseInputInstructionData { + pub fn new() -> Self { + Self { + discriminator: [143, 190, 90, 218, 196, 30, 51, 222], + } + } + + pub(crate) fn try_to_vec(&self) -> Result, std::io::Error> { + borsh::to_vec(self) + } +} + +impl Default for SwapBaseInputInstructionData { + fn default() -> Self { + Self::new() + } +} + +#[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] +pub struct SwapBaseInputInstructionArgs { + pub amount_in: u64, + pub minimum_amount_out: u64, +} + +impl SwapBaseInputInstructionArgs { + pub(crate) fn try_to_vec(&self) -> Result, std::io::Error> { + borsh::to_vec(self) + } +} + +/// Instruction builder for `SwapBaseInput`. +/// +/// ### Accounts: +/// +/// 0. `[signer]` payer +/// 1. `[]` authority +/// 2. `[]` amm_config +/// 3. `[writable]` pool_state +/// 4. `[writable]` input_token_account +/// 5. `[writable]` output_token_account +/// 6. `[writable]` input_vault +/// 7. `[writable]` output_vault +/// 8. `[]` input_token_program +/// 9. `[]` output_token_program +/// 10. `[]` input_token_mint +/// 11. `[]` output_token_mint +/// 12. `[writable]` observation_state +#[derive(Clone, Debug, Default)] +pub struct SwapBaseInputBuilder { + payer: Option, + authority: Option, + amm_config: Option, + pool_state: Option, + input_token_account: Option, + output_token_account: Option, + input_vault: Option, + output_vault: Option, + input_token_program: Option, + output_token_program: Option, + input_token_mint: Option, + output_token_mint: Option, + observation_state: Option, + amount_in: Option, + minimum_amount_out: Option, + __remaining_accounts: Vec, +} + +impl SwapBaseInputBuilder { + pub fn new() -> Self { + Self::default() + } + /// The user performing the swap + #[inline(always)] + pub fn payer(&mut self, payer: solana_address::Address) -> &mut Self { + self.payer = Some(payer); + self + } + #[inline(always)] + pub fn authority(&mut self, authority: solana_address::Address) -> &mut Self { + self.authority = Some(authority); + self + } + /// The factory state to read protocol fees + #[inline(always)] + pub fn amm_config(&mut self, amm_config: solana_address::Address) -> &mut Self { + self.amm_config = Some(amm_config); + self + } + /// The program account of the pool in which the swap will be performed + #[inline(always)] + pub fn pool_state(&mut self, pool_state: solana_address::Address) -> &mut Self { + self.pool_state = Some(pool_state); + self + } + /// The user token account for input token + #[inline(always)] + pub fn input_token_account( + &mut self, + input_token_account: solana_address::Address, + ) -> &mut Self { + self.input_token_account = Some(input_token_account); + self + } + /// The user token account for output token + #[inline(always)] + pub fn output_token_account( + &mut self, + output_token_account: solana_address::Address, + ) -> &mut Self { + self.output_token_account = Some(output_token_account); + self + } + /// The vault token account for input token + #[inline(always)] + pub fn input_vault(&mut self, input_vault: solana_address::Address) -> &mut Self { + self.input_vault = Some(input_vault); + self + } + /// The vault token account for output token + #[inline(always)] + pub fn output_vault(&mut self, output_vault: solana_address::Address) -> &mut Self { + self.output_vault = Some(output_vault); + self + } + /// SPL program for input token transfers + #[inline(always)] + pub fn input_token_program( + &mut self, + input_token_program: solana_address::Address, + ) -> &mut Self { + self.input_token_program = Some(input_token_program); + self + } + /// SPL program for output token transfers + #[inline(always)] + pub fn output_token_program( + &mut self, + output_token_program: solana_address::Address, + ) -> &mut Self { + self.output_token_program = Some(output_token_program); + self + } + /// The mint of input token + #[inline(always)] + pub fn input_token_mint(&mut self, input_token_mint: solana_address::Address) -> &mut Self { + self.input_token_mint = Some(input_token_mint); + self + } + /// The mint of output token + #[inline(always)] + pub fn output_token_mint(&mut self, output_token_mint: solana_address::Address) -> &mut Self { + self.output_token_mint = Some(output_token_mint); + self + } + /// The program account for the most recent oracle observation + #[inline(always)] + pub fn observation_state(&mut self, observation_state: solana_address::Address) -> &mut Self { + self.observation_state = Some(observation_state); + self + } + #[inline(always)] + pub fn amount_in(&mut self, amount_in: u64) -> &mut Self { + self.amount_in = Some(amount_in); + self + } + #[inline(always)] + pub fn minimum_amount_out(&mut self, minimum_amount_out: u64) -> &mut Self { + self.minimum_amount_out = Some(minimum_amount_out); + self + } + /// Add an additional account to the instruction. + #[inline(always)] + pub fn add_remaining_account(&mut self, account: solana_instruction::AccountMeta) -> &mut Self { + self.__remaining_accounts.push(account); + self + } + /// Add additional accounts to the instruction. + #[inline(always)] + pub fn add_remaining_accounts( + &mut self, + accounts: &[solana_instruction::AccountMeta], + ) -> &mut Self { + self.__remaining_accounts.extend_from_slice(accounts); + self + } + #[allow(clippy::clone_on_copy)] + pub fn instruction(&self) -> solana_instruction::Instruction { + let accounts = SwapBaseInput { + payer: self.payer.expect("payer is not set"), + authority: self.authority.expect("authority is not set"), + amm_config: self.amm_config.expect("amm_config is not set"), + pool_state: self.pool_state.expect("pool_state is not set"), + input_token_account: self + .input_token_account + .expect("input_token_account is not set"), + output_token_account: self + .output_token_account + .expect("output_token_account is not set"), + input_vault: self.input_vault.expect("input_vault is not set"), + output_vault: self.output_vault.expect("output_vault is not set"), + input_token_program: self + .input_token_program + .expect("input_token_program is not set"), + output_token_program: self + .output_token_program + .expect("output_token_program is not set"), + input_token_mint: self.input_token_mint.expect("input_token_mint is not set"), + output_token_mint: self + .output_token_mint + .expect("output_token_mint is not set"), + observation_state: self + .observation_state + .expect("observation_state is not set"), + }; + let args = SwapBaseInputInstructionArgs { + amount_in: self.amount_in.clone().expect("amount_in is not set"), + minimum_amount_out: self + .minimum_amount_out + .clone() + .expect("minimum_amount_out is not set"), + }; + + accounts.instruction_with_remaining_accounts(args, &self.__remaining_accounts) + } +} + +/// `swap_base_input` CPI accounts. +pub struct SwapBaseInputCpiAccounts<'a, 'b> { + /// The user performing the swap + pub payer: &'b solana_account_info::AccountInfo<'a>, + + pub authority: &'b solana_account_info::AccountInfo<'a>, + /// The factory state to read protocol fees + pub amm_config: &'b solana_account_info::AccountInfo<'a>, + /// The program account of the pool in which the swap will be performed + pub pool_state: &'b solana_account_info::AccountInfo<'a>, + /// The user token account for input token + pub input_token_account: &'b solana_account_info::AccountInfo<'a>, + /// The user token account for output token + pub output_token_account: &'b solana_account_info::AccountInfo<'a>, + /// The vault token account for input token + pub input_vault: &'b solana_account_info::AccountInfo<'a>, + /// The vault token account for output token + pub output_vault: &'b solana_account_info::AccountInfo<'a>, + /// SPL program for input token transfers + pub input_token_program: &'b solana_account_info::AccountInfo<'a>, + /// SPL program for output token transfers + pub output_token_program: &'b solana_account_info::AccountInfo<'a>, + /// The mint of input token + pub input_token_mint: &'b solana_account_info::AccountInfo<'a>, + /// The mint of output token + pub output_token_mint: &'b solana_account_info::AccountInfo<'a>, + /// The program account for the most recent oracle observation + pub observation_state: &'b solana_account_info::AccountInfo<'a>, +} + +/// `swap_base_input` CPI instruction. +pub struct SwapBaseInputCpi<'a, 'b> { + /// The program to invoke. + pub __program: &'b solana_account_info::AccountInfo<'a>, + /// The user performing the swap + pub payer: &'b solana_account_info::AccountInfo<'a>, + + pub authority: &'b solana_account_info::AccountInfo<'a>, + /// The factory state to read protocol fees + pub amm_config: &'b solana_account_info::AccountInfo<'a>, + /// The program account of the pool in which the swap will be performed + pub pool_state: &'b solana_account_info::AccountInfo<'a>, + /// The user token account for input token + pub input_token_account: &'b solana_account_info::AccountInfo<'a>, + /// The user token account for output token + pub output_token_account: &'b solana_account_info::AccountInfo<'a>, + /// The vault token account for input token + pub input_vault: &'b solana_account_info::AccountInfo<'a>, + /// The vault token account for output token + pub output_vault: &'b solana_account_info::AccountInfo<'a>, + /// SPL program for input token transfers + pub input_token_program: &'b solana_account_info::AccountInfo<'a>, + /// SPL program for output token transfers + pub output_token_program: &'b solana_account_info::AccountInfo<'a>, + /// The mint of input token + pub input_token_mint: &'b solana_account_info::AccountInfo<'a>, + /// The mint of output token + pub output_token_mint: &'b solana_account_info::AccountInfo<'a>, + /// The program account for the most recent oracle observation + pub observation_state: &'b solana_account_info::AccountInfo<'a>, + /// The arguments for the instruction. + pub __args: SwapBaseInputInstructionArgs, +} + +impl<'a, 'b> SwapBaseInputCpi<'a, 'b> { + pub fn new( + program: &'b solana_account_info::AccountInfo<'a>, + accounts: SwapBaseInputCpiAccounts<'a, 'b>, + args: SwapBaseInputInstructionArgs, + ) -> Self { + Self { + __program: program, + payer: accounts.payer, + authority: accounts.authority, + amm_config: accounts.amm_config, + pool_state: accounts.pool_state, + input_token_account: accounts.input_token_account, + output_token_account: accounts.output_token_account, + input_vault: accounts.input_vault, + output_vault: accounts.output_vault, + input_token_program: accounts.input_token_program, + output_token_program: accounts.output_token_program, + input_token_mint: accounts.input_token_mint, + output_token_mint: accounts.output_token_mint, + observation_state: accounts.observation_state, + __args: args, + } + } + #[inline(always)] + pub fn invoke(&self) -> solana_program_error::ProgramResult { + self.invoke_signed_with_remaining_accounts(&[], &[]) + } + #[inline(always)] + pub fn invoke_with_remaining_accounts( + &self, + remaining_accounts: &[(&'b solana_account_info::AccountInfo<'a>, bool, bool)], + ) -> solana_program_error::ProgramResult { + self.invoke_signed_with_remaining_accounts(&[], remaining_accounts) + } + #[inline(always)] + pub fn invoke_signed(&self, signers_seeds: &[&[&[u8]]]) -> solana_program_error::ProgramResult { + self.invoke_signed_with_remaining_accounts(signers_seeds, &[]) + } + #[allow(clippy::arithmetic_side_effects)] + #[allow(clippy::clone_on_copy)] + #[allow(clippy::vec_init_then_push)] + pub fn invoke_signed_with_remaining_accounts( + &self, + signers_seeds: &[&[&[u8]]], + remaining_accounts: &[(&'b solana_account_info::AccountInfo<'a>, bool, bool)], + ) -> solana_program_error::ProgramResult { + let mut accounts = Vec::with_capacity(13 + remaining_accounts.len()); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.payer.key, + true, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.authority.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.amm_config.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + *self.pool_state.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + *self.input_token_account.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + *self.output_token_account.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + *self.input_vault.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + *self.output_vault.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.input_token_program.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.output_token_program.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.input_token_mint.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.output_token_mint.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + *self.observation_state.key, + false, + )); + remaining_accounts.iter().for_each(|remaining_account| { + accounts.push(solana_instruction::AccountMeta { + pubkey: *remaining_account.0.key, + is_signer: remaining_account.1, + is_writable: remaining_account.2, + }) + }); + let mut data = SwapBaseInputInstructionData::new().try_to_vec().unwrap(); + let mut args = self.__args.try_to_vec().unwrap(); + data.append(&mut args); + + let instruction = solana_instruction::Instruction { + program_id: crate::RAYDIUM_CP_SWAP_ID, + accounts, + data, + }; + let mut account_infos = Vec::with_capacity(14 + remaining_accounts.len()); + account_infos.push(self.__program.clone()); + account_infos.push(self.payer.clone()); + account_infos.push(self.authority.clone()); + account_infos.push(self.amm_config.clone()); + account_infos.push(self.pool_state.clone()); + account_infos.push(self.input_token_account.clone()); + account_infos.push(self.output_token_account.clone()); + account_infos.push(self.input_vault.clone()); + account_infos.push(self.output_vault.clone()); + account_infos.push(self.input_token_program.clone()); + account_infos.push(self.output_token_program.clone()); + account_infos.push(self.input_token_mint.clone()); + account_infos.push(self.output_token_mint.clone()); + account_infos.push(self.observation_state.clone()); + remaining_accounts + .iter() + .for_each(|remaining_account| account_infos.push(remaining_account.0.clone())); + + if signers_seeds.is_empty() { + solana_cpi::invoke(&instruction, &account_infos) + } else { + solana_cpi::invoke_signed(&instruction, &account_infos, signers_seeds) + } + } +} + +/// Instruction builder for `SwapBaseInput` via CPI. +/// +/// ### Accounts: +/// +/// 0. `[signer]` payer +/// 1. `[]` authority +/// 2. `[]` amm_config +/// 3. `[writable]` pool_state +/// 4. `[writable]` input_token_account +/// 5. `[writable]` output_token_account +/// 6. `[writable]` input_vault +/// 7. `[writable]` output_vault +/// 8. `[]` input_token_program +/// 9. `[]` output_token_program +/// 10. `[]` input_token_mint +/// 11. `[]` output_token_mint +/// 12. `[writable]` observation_state +#[derive(Clone, Debug)] +pub struct SwapBaseInputCpiBuilder<'a, 'b> { + instruction: Box>, +} + +impl<'a, 'b> SwapBaseInputCpiBuilder<'a, 'b> { + pub fn new(program: &'b solana_account_info::AccountInfo<'a>) -> Self { + let instruction = Box::new(SwapBaseInputCpiBuilderInstruction { + __program: program, + payer: None, + authority: None, + amm_config: None, + pool_state: None, + input_token_account: None, + output_token_account: None, + input_vault: None, + output_vault: None, + input_token_program: None, + output_token_program: None, + input_token_mint: None, + output_token_mint: None, + observation_state: None, + amount_in: None, + minimum_amount_out: None, + __remaining_accounts: Vec::new(), + }); + Self { instruction } + } + /// The user performing the swap + #[inline(always)] + pub fn payer(&mut self, payer: &'b solana_account_info::AccountInfo<'a>) -> &mut Self { + self.instruction.payer = Some(payer); + self + } + #[inline(always)] + pub fn authority(&mut self, authority: &'b solana_account_info::AccountInfo<'a>) -> &mut Self { + self.instruction.authority = Some(authority); + self + } + /// The factory state to read protocol fees + #[inline(always)] + pub fn amm_config( + &mut self, + amm_config: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.amm_config = Some(amm_config); + self + } + /// The program account of the pool in which the swap will be performed + #[inline(always)] + pub fn pool_state( + &mut self, + pool_state: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.pool_state = Some(pool_state); + self + } + /// The user token account for input token + #[inline(always)] + pub fn input_token_account( + &mut self, + input_token_account: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.input_token_account = Some(input_token_account); + self + } + /// The user token account for output token + #[inline(always)] + pub fn output_token_account( + &mut self, + output_token_account: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.output_token_account = Some(output_token_account); + self + } + /// The vault token account for input token + #[inline(always)] + pub fn input_vault( + &mut self, + input_vault: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.input_vault = Some(input_vault); + self + } + /// The vault token account for output token + #[inline(always)] + pub fn output_vault( + &mut self, + output_vault: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.output_vault = Some(output_vault); + self + } + /// SPL program for input token transfers + #[inline(always)] + pub fn input_token_program( + &mut self, + input_token_program: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.input_token_program = Some(input_token_program); + self + } + /// SPL program for output token transfers + #[inline(always)] + pub fn output_token_program( + &mut self, + output_token_program: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.output_token_program = Some(output_token_program); + self + } + /// The mint of input token + #[inline(always)] + pub fn input_token_mint( + &mut self, + input_token_mint: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.input_token_mint = Some(input_token_mint); + self + } + /// The mint of output token + #[inline(always)] + pub fn output_token_mint( + &mut self, + output_token_mint: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.output_token_mint = Some(output_token_mint); + self + } + /// The program account for the most recent oracle observation + #[inline(always)] + pub fn observation_state( + &mut self, + observation_state: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.observation_state = Some(observation_state); + self + } + #[inline(always)] + pub fn amount_in(&mut self, amount_in: u64) -> &mut Self { + self.instruction.amount_in = Some(amount_in); + self + } + #[inline(always)] + pub fn minimum_amount_out(&mut self, minimum_amount_out: u64) -> &mut Self { + self.instruction.minimum_amount_out = Some(minimum_amount_out); + self + } + /// Add an additional account to the instruction. + #[inline(always)] + pub fn add_remaining_account( + &mut self, + account: &'b solana_account_info::AccountInfo<'a>, + is_writable: bool, + is_signer: bool, + ) -> &mut Self { + self.instruction + .__remaining_accounts + .push((account, is_writable, is_signer)); + self + } + /// Add additional accounts to the instruction. + /// + /// Each account is represented by a tuple of the `AccountInfo`, a `bool` indicating whether the account is writable or not, + /// and a `bool` indicating whether the account is a signer or not. + #[inline(always)] + pub fn add_remaining_accounts( + &mut self, + accounts: &[(&'b solana_account_info::AccountInfo<'a>, bool, bool)], + ) -> &mut Self { + self.instruction + .__remaining_accounts + .extend_from_slice(accounts); + self + } + #[inline(always)] + pub fn invoke(&self) -> solana_program_error::ProgramResult { + self.invoke_signed(&[]) + } + #[allow(clippy::clone_on_copy)] + #[allow(clippy::vec_init_then_push)] + pub fn invoke_signed(&self, signers_seeds: &[&[&[u8]]]) -> solana_program_error::ProgramResult { + let args = SwapBaseInputInstructionArgs { + amount_in: self + .instruction + .amount_in + .clone() + .expect("amount_in is not set"), + minimum_amount_out: self + .instruction + .minimum_amount_out + .clone() + .expect("minimum_amount_out is not set"), + }; + let instruction = SwapBaseInputCpi { + __program: self.instruction.__program, + + payer: self.instruction.payer.expect("payer is not set"), + + authority: self.instruction.authority.expect("authority is not set"), + + amm_config: self.instruction.amm_config.expect("amm_config is not set"), + + pool_state: self.instruction.pool_state.expect("pool_state is not set"), + + input_token_account: self + .instruction + .input_token_account + .expect("input_token_account is not set"), + + output_token_account: self + .instruction + .output_token_account + .expect("output_token_account is not set"), + + input_vault: self + .instruction + .input_vault + .expect("input_vault is not set"), + + output_vault: self + .instruction + .output_vault + .expect("output_vault is not set"), + + input_token_program: self + .instruction + .input_token_program + .expect("input_token_program is not set"), + + output_token_program: self + .instruction + .output_token_program + .expect("output_token_program is not set"), + + input_token_mint: self + .instruction + .input_token_mint + .expect("input_token_mint is not set"), + + output_token_mint: self + .instruction + .output_token_mint + .expect("output_token_mint is not set"), + + observation_state: self + .instruction + .observation_state + .expect("observation_state is not set"), + __args: args, + }; + instruction.invoke_signed_with_remaining_accounts( + signers_seeds, + &self.instruction.__remaining_accounts, + ) + } +} + +#[derive(Clone, Debug)] +struct SwapBaseInputCpiBuilderInstruction<'a, 'b> { + __program: &'b solana_account_info::AccountInfo<'a>, + payer: Option<&'b solana_account_info::AccountInfo<'a>>, + authority: Option<&'b solana_account_info::AccountInfo<'a>>, + amm_config: Option<&'b solana_account_info::AccountInfo<'a>>, + pool_state: Option<&'b solana_account_info::AccountInfo<'a>>, + input_token_account: Option<&'b solana_account_info::AccountInfo<'a>>, + output_token_account: Option<&'b solana_account_info::AccountInfo<'a>>, + input_vault: Option<&'b solana_account_info::AccountInfo<'a>>, + output_vault: Option<&'b solana_account_info::AccountInfo<'a>>, + input_token_program: Option<&'b solana_account_info::AccountInfo<'a>>, + output_token_program: Option<&'b solana_account_info::AccountInfo<'a>>, + input_token_mint: Option<&'b solana_account_info::AccountInfo<'a>>, + output_token_mint: Option<&'b solana_account_info::AccountInfo<'a>>, + observation_state: Option<&'b solana_account_info::AccountInfo<'a>>, + amount_in: Option, + minimum_amount_out: Option, + /// Additional instruction accounts `(AccountInfo, is_writable, is_signer)`. + __remaining_accounts: Vec<(&'b solana_account_info::AccountInfo<'a>, bool, bool)>, +} diff --git a/e2e/raydium-cpmm/src/generated/instructions/swap_base_output.rs b/e2e/raydium-cpmm/src/generated/instructions/swap_base_output.rs new file mode 100644 index 0000000..a0a8dd0 --- /dev/null +++ b/e2e/raydium-cpmm/src/generated/instructions/swap_base_output.rs @@ -0,0 +1,853 @@ +//! This code was AUTOGENERATED using the codama library. +//! Please DO NOT EDIT THIS FILE, instead use visitors +//! to add features, then rerun codama to update it. +//! +//! +//! + +use borsh::BorshDeserialize; +use borsh::BorshSerialize; + +pub const SWAP_BASE_OUTPUT_DISCRIMINATOR: [u8; 8] = [55, 217, 98, 86, 163, 74, 180, 173]; + +/// Accounts. +#[derive(Debug)] +pub struct SwapBaseOutput { + /// The user performing the swap + pub payer: solana_address::Address, + + pub authority: solana_address::Address, + /// The factory state to read protocol fees + pub amm_config: solana_address::Address, + /// The program account of the pool in which the swap will be performed + pub pool_state: solana_address::Address, + /// The user token account for input token + pub input_token_account: solana_address::Address, + /// The user token account for output token + pub output_token_account: solana_address::Address, + /// The vault token account for input token + pub input_vault: solana_address::Address, + /// The vault token account for output token + pub output_vault: solana_address::Address, + /// SPL program for input token transfers + pub input_token_program: solana_address::Address, + /// SPL program for output token transfers + pub output_token_program: solana_address::Address, + /// The mint of input token + pub input_token_mint: solana_address::Address, + /// The mint of output token + pub output_token_mint: solana_address::Address, + /// The program account for the most recent oracle observation + pub observation_state: solana_address::Address, +} + +impl SwapBaseOutput { + pub fn instruction( + &self, + args: SwapBaseOutputInstructionArgs, + ) -> solana_instruction::Instruction { + self.instruction_with_remaining_accounts(args, &[]) + } + #[allow(clippy::arithmetic_side_effects)] + #[allow(clippy::vec_init_then_push)] + pub fn instruction_with_remaining_accounts( + &self, + args: SwapBaseOutputInstructionArgs, + remaining_accounts: &[solana_instruction::AccountMeta], + ) -> solana_instruction::Instruction { + let mut accounts = Vec::with_capacity(13 + remaining_accounts.len()); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.payer, true, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.authority, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.amm_config, + false, + )); + accounts.push(solana_instruction::AccountMeta::new(self.pool_state, false)); + accounts.push(solana_instruction::AccountMeta::new( + self.input_token_account, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + self.output_token_account, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + self.input_vault, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + self.output_vault, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.input_token_program, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.output_token_program, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.input_token_mint, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.output_token_mint, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + self.observation_state, + false, + )); + accounts.extend_from_slice(remaining_accounts); + let mut data = SwapBaseOutputInstructionData::new().try_to_vec().unwrap(); + let mut args = args.try_to_vec().unwrap(); + data.append(&mut args); + + solana_instruction::Instruction { + program_id: crate::RAYDIUM_CP_SWAP_ID, + accounts, + data, + } + } +} + +#[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] +pub struct SwapBaseOutputInstructionData { + discriminator: [u8; 8], +} + +impl SwapBaseOutputInstructionData { + pub fn new() -> Self { + Self { + discriminator: [55, 217, 98, 86, 163, 74, 180, 173], + } + } + + pub(crate) fn try_to_vec(&self) -> Result, std::io::Error> { + borsh::to_vec(self) + } +} + +impl Default for SwapBaseOutputInstructionData { + fn default() -> Self { + Self::new() + } +} + +#[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] +pub struct SwapBaseOutputInstructionArgs { + pub max_amount_in: u64, + pub amount_out: u64, +} + +impl SwapBaseOutputInstructionArgs { + pub(crate) fn try_to_vec(&self) -> Result, std::io::Error> { + borsh::to_vec(self) + } +} + +/// Instruction builder for `SwapBaseOutput`. +/// +/// ### Accounts: +/// +/// 0. `[signer]` payer +/// 1. `[]` authority +/// 2. `[]` amm_config +/// 3. `[writable]` pool_state +/// 4. `[writable]` input_token_account +/// 5. `[writable]` output_token_account +/// 6. `[writable]` input_vault +/// 7. `[writable]` output_vault +/// 8. `[]` input_token_program +/// 9. `[]` output_token_program +/// 10. `[]` input_token_mint +/// 11. `[]` output_token_mint +/// 12. `[writable]` observation_state +#[derive(Clone, Debug, Default)] +pub struct SwapBaseOutputBuilder { + payer: Option, + authority: Option, + amm_config: Option, + pool_state: Option, + input_token_account: Option, + output_token_account: Option, + input_vault: Option, + output_vault: Option, + input_token_program: Option, + output_token_program: Option, + input_token_mint: Option, + output_token_mint: Option, + observation_state: Option, + max_amount_in: Option, + amount_out: Option, + __remaining_accounts: Vec, +} + +impl SwapBaseOutputBuilder { + pub fn new() -> Self { + Self::default() + } + /// The user performing the swap + #[inline(always)] + pub fn payer(&mut self, payer: solana_address::Address) -> &mut Self { + self.payer = Some(payer); + self + } + #[inline(always)] + pub fn authority(&mut self, authority: solana_address::Address) -> &mut Self { + self.authority = Some(authority); + self + } + /// The factory state to read protocol fees + #[inline(always)] + pub fn amm_config(&mut self, amm_config: solana_address::Address) -> &mut Self { + self.amm_config = Some(amm_config); + self + } + /// The program account of the pool in which the swap will be performed + #[inline(always)] + pub fn pool_state(&mut self, pool_state: solana_address::Address) -> &mut Self { + self.pool_state = Some(pool_state); + self + } + /// The user token account for input token + #[inline(always)] + pub fn input_token_account( + &mut self, + input_token_account: solana_address::Address, + ) -> &mut Self { + self.input_token_account = Some(input_token_account); + self + } + /// The user token account for output token + #[inline(always)] + pub fn output_token_account( + &mut self, + output_token_account: solana_address::Address, + ) -> &mut Self { + self.output_token_account = Some(output_token_account); + self + } + /// The vault token account for input token + #[inline(always)] + pub fn input_vault(&mut self, input_vault: solana_address::Address) -> &mut Self { + self.input_vault = Some(input_vault); + self + } + /// The vault token account for output token + #[inline(always)] + pub fn output_vault(&mut self, output_vault: solana_address::Address) -> &mut Self { + self.output_vault = Some(output_vault); + self + } + /// SPL program for input token transfers + #[inline(always)] + pub fn input_token_program( + &mut self, + input_token_program: solana_address::Address, + ) -> &mut Self { + self.input_token_program = Some(input_token_program); + self + } + /// SPL program for output token transfers + #[inline(always)] + pub fn output_token_program( + &mut self, + output_token_program: solana_address::Address, + ) -> &mut Self { + self.output_token_program = Some(output_token_program); + self + } + /// The mint of input token + #[inline(always)] + pub fn input_token_mint(&mut self, input_token_mint: solana_address::Address) -> &mut Self { + self.input_token_mint = Some(input_token_mint); + self + } + /// The mint of output token + #[inline(always)] + pub fn output_token_mint(&mut self, output_token_mint: solana_address::Address) -> &mut Self { + self.output_token_mint = Some(output_token_mint); + self + } + /// The program account for the most recent oracle observation + #[inline(always)] + pub fn observation_state(&mut self, observation_state: solana_address::Address) -> &mut Self { + self.observation_state = Some(observation_state); + self + } + #[inline(always)] + pub fn max_amount_in(&mut self, max_amount_in: u64) -> &mut Self { + self.max_amount_in = Some(max_amount_in); + self + } + #[inline(always)] + pub fn amount_out(&mut self, amount_out: u64) -> &mut Self { + self.amount_out = Some(amount_out); + self + } + /// Add an additional account to the instruction. + #[inline(always)] + pub fn add_remaining_account(&mut self, account: solana_instruction::AccountMeta) -> &mut Self { + self.__remaining_accounts.push(account); + self + } + /// Add additional accounts to the instruction. + #[inline(always)] + pub fn add_remaining_accounts( + &mut self, + accounts: &[solana_instruction::AccountMeta], + ) -> &mut Self { + self.__remaining_accounts.extend_from_slice(accounts); + self + } + #[allow(clippy::clone_on_copy)] + pub fn instruction(&self) -> solana_instruction::Instruction { + let accounts = SwapBaseOutput { + payer: self.payer.expect("payer is not set"), + authority: self.authority.expect("authority is not set"), + amm_config: self.amm_config.expect("amm_config is not set"), + pool_state: self.pool_state.expect("pool_state is not set"), + input_token_account: self + .input_token_account + .expect("input_token_account is not set"), + output_token_account: self + .output_token_account + .expect("output_token_account is not set"), + input_vault: self.input_vault.expect("input_vault is not set"), + output_vault: self.output_vault.expect("output_vault is not set"), + input_token_program: self + .input_token_program + .expect("input_token_program is not set"), + output_token_program: self + .output_token_program + .expect("output_token_program is not set"), + input_token_mint: self.input_token_mint.expect("input_token_mint is not set"), + output_token_mint: self + .output_token_mint + .expect("output_token_mint is not set"), + observation_state: self + .observation_state + .expect("observation_state is not set"), + }; + let args = SwapBaseOutputInstructionArgs { + max_amount_in: self + .max_amount_in + .clone() + .expect("max_amount_in is not set"), + amount_out: self.amount_out.clone().expect("amount_out is not set"), + }; + + accounts.instruction_with_remaining_accounts(args, &self.__remaining_accounts) + } +} + +/// `swap_base_output` CPI accounts. +pub struct SwapBaseOutputCpiAccounts<'a, 'b> { + /// The user performing the swap + pub payer: &'b solana_account_info::AccountInfo<'a>, + + pub authority: &'b solana_account_info::AccountInfo<'a>, + /// The factory state to read protocol fees + pub amm_config: &'b solana_account_info::AccountInfo<'a>, + /// The program account of the pool in which the swap will be performed + pub pool_state: &'b solana_account_info::AccountInfo<'a>, + /// The user token account for input token + pub input_token_account: &'b solana_account_info::AccountInfo<'a>, + /// The user token account for output token + pub output_token_account: &'b solana_account_info::AccountInfo<'a>, + /// The vault token account for input token + pub input_vault: &'b solana_account_info::AccountInfo<'a>, + /// The vault token account for output token + pub output_vault: &'b solana_account_info::AccountInfo<'a>, + /// SPL program for input token transfers + pub input_token_program: &'b solana_account_info::AccountInfo<'a>, + /// SPL program for output token transfers + pub output_token_program: &'b solana_account_info::AccountInfo<'a>, + /// The mint of input token + pub input_token_mint: &'b solana_account_info::AccountInfo<'a>, + /// The mint of output token + pub output_token_mint: &'b solana_account_info::AccountInfo<'a>, + /// The program account for the most recent oracle observation + pub observation_state: &'b solana_account_info::AccountInfo<'a>, +} + +/// `swap_base_output` CPI instruction. +pub struct SwapBaseOutputCpi<'a, 'b> { + /// The program to invoke. + pub __program: &'b solana_account_info::AccountInfo<'a>, + /// The user performing the swap + pub payer: &'b solana_account_info::AccountInfo<'a>, + + pub authority: &'b solana_account_info::AccountInfo<'a>, + /// The factory state to read protocol fees + pub amm_config: &'b solana_account_info::AccountInfo<'a>, + /// The program account of the pool in which the swap will be performed + pub pool_state: &'b solana_account_info::AccountInfo<'a>, + /// The user token account for input token + pub input_token_account: &'b solana_account_info::AccountInfo<'a>, + /// The user token account for output token + pub output_token_account: &'b solana_account_info::AccountInfo<'a>, + /// The vault token account for input token + pub input_vault: &'b solana_account_info::AccountInfo<'a>, + /// The vault token account for output token + pub output_vault: &'b solana_account_info::AccountInfo<'a>, + /// SPL program for input token transfers + pub input_token_program: &'b solana_account_info::AccountInfo<'a>, + /// SPL program for output token transfers + pub output_token_program: &'b solana_account_info::AccountInfo<'a>, + /// The mint of input token + pub input_token_mint: &'b solana_account_info::AccountInfo<'a>, + /// The mint of output token + pub output_token_mint: &'b solana_account_info::AccountInfo<'a>, + /// The program account for the most recent oracle observation + pub observation_state: &'b solana_account_info::AccountInfo<'a>, + /// The arguments for the instruction. + pub __args: SwapBaseOutputInstructionArgs, +} + +impl<'a, 'b> SwapBaseOutputCpi<'a, 'b> { + pub fn new( + program: &'b solana_account_info::AccountInfo<'a>, + accounts: SwapBaseOutputCpiAccounts<'a, 'b>, + args: SwapBaseOutputInstructionArgs, + ) -> Self { + Self { + __program: program, + payer: accounts.payer, + authority: accounts.authority, + amm_config: accounts.amm_config, + pool_state: accounts.pool_state, + input_token_account: accounts.input_token_account, + output_token_account: accounts.output_token_account, + input_vault: accounts.input_vault, + output_vault: accounts.output_vault, + input_token_program: accounts.input_token_program, + output_token_program: accounts.output_token_program, + input_token_mint: accounts.input_token_mint, + output_token_mint: accounts.output_token_mint, + observation_state: accounts.observation_state, + __args: args, + } + } + #[inline(always)] + pub fn invoke(&self) -> solana_program_error::ProgramResult { + self.invoke_signed_with_remaining_accounts(&[], &[]) + } + #[inline(always)] + pub fn invoke_with_remaining_accounts( + &self, + remaining_accounts: &[(&'b solana_account_info::AccountInfo<'a>, bool, bool)], + ) -> solana_program_error::ProgramResult { + self.invoke_signed_with_remaining_accounts(&[], remaining_accounts) + } + #[inline(always)] + pub fn invoke_signed(&self, signers_seeds: &[&[&[u8]]]) -> solana_program_error::ProgramResult { + self.invoke_signed_with_remaining_accounts(signers_seeds, &[]) + } + #[allow(clippy::arithmetic_side_effects)] + #[allow(clippy::clone_on_copy)] + #[allow(clippy::vec_init_then_push)] + pub fn invoke_signed_with_remaining_accounts( + &self, + signers_seeds: &[&[&[u8]]], + remaining_accounts: &[(&'b solana_account_info::AccountInfo<'a>, bool, bool)], + ) -> solana_program_error::ProgramResult { + let mut accounts = Vec::with_capacity(13 + remaining_accounts.len()); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.payer.key, + true, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.authority.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.amm_config.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + *self.pool_state.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + *self.input_token_account.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + *self.output_token_account.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + *self.input_vault.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + *self.output_vault.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.input_token_program.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.output_token_program.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.input_token_mint.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.output_token_mint.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + *self.observation_state.key, + false, + )); + remaining_accounts.iter().for_each(|remaining_account| { + accounts.push(solana_instruction::AccountMeta { + pubkey: *remaining_account.0.key, + is_signer: remaining_account.1, + is_writable: remaining_account.2, + }) + }); + let mut data = SwapBaseOutputInstructionData::new().try_to_vec().unwrap(); + let mut args = self.__args.try_to_vec().unwrap(); + data.append(&mut args); + + let instruction = solana_instruction::Instruction { + program_id: crate::RAYDIUM_CP_SWAP_ID, + accounts, + data, + }; + let mut account_infos = Vec::with_capacity(14 + remaining_accounts.len()); + account_infos.push(self.__program.clone()); + account_infos.push(self.payer.clone()); + account_infos.push(self.authority.clone()); + account_infos.push(self.amm_config.clone()); + account_infos.push(self.pool_state.clone()); + account_infos.push(self.input_token_account.clone()); + account_infos.push(self.output_token_account.clone()); + account_infos.push(self.input_vault.clone()); + account_infos.push(self.output_vault.clone()); + account_infos.push(self.input_token_program.clone()); + account_infos.push(self.output_token_program.clone()); + account_infos.push(self.input_token_mint.clone()); + account_infos.push(self.output_token_mint.clone()); + account_infos.push(self.observation_state.clone()); + remaining_accounts + .iter() + .for_each(|remaining_account| account_infos.push(remaining_account.0.clone())); + + if signers_seeds.is_empty() { + solana_cpi::invoke(&instruction, &account_infos) + } else { + solana_cpi::invoke_signed(&instruction, &account_infos, signers_seeds) + } + } +} + +/// Instruction builder for `SwapBaseOutput` via CPI. +/// +/// ### Accounts: +/// +/// 0. `[signer]` payer +/// 1. `[]` authority +/// 2. `[]` amm_config +/// 3. `[writable]` pool_state +/// 4. `[writable]` input_token_account +/// 5. `[writable]` output_token_account +/// 6. `[writable]` input_vault +/// 7. `[writable]` output_vault +/// 8. `[]` input_token_program +/// 9. `[]` output_token_program +/// 10. `[]` input_token_mint +/// 11. `[]` output_token_mint +/// 12. `[writable]` observation_state +#[derive(Clone, Debug)] +pub struct SwapBaseOutputCpiBuilder<'a, 'b> { + instruction: Box>, +} + +impl<'a, 'b> SwapBaseOutputCpiBuilder<'a, 'b> { + pub fn new(program: &'b solana_account_info::AccountInfo<'a>) -> Self { + let instruction = Box::new(SwapBaseOutputCpiBuilderInstruction { + __program: program, + payer: None, + authority: None, + amm_config: None, + pool_state: None, + input_token_account: None, + output_token_account: None, + input_vault: None, + output_vault: None, + input_token_program: None, + output_token_program: None, + input_token_mint: None, + output_token_mint: None, + observation_state: None, + max_amount_in: None, + amount_out: None, + __remaining_accounts: Vec::new(), + }); + Self { instruction } + } + /// The user performing the swap + #[inline(always)] + pub fn payer(&mut self, payer: &'b solana_account_info::AccountInfo<'a>) -> &mut Self { + self.instruction.payer = Some(payer); + self + } + #[inline(always)] + pub fn authority(&mut self, authority: &'b solana_account_info::AccountInfo<'a>) -> &mut Self { + self.instruction.authority = Some(authority); + self + } + /// The factory state to read protocol fees + #[inline(always)] + pub fn amm_config( + &mut self, + amm_config: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.amm_config = Some(amm_config); + self + } + /// The program account of the pool in which the swap will be performed + #[inline(always)] + pub fn pool_state( + &mut self, + pool_state: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.pool_state = Some(pool_state); + self + } + /// The user token account for input token + #[inline(always)] + pub fn input_token_account( + &mut self, + input_token_account: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.input_token_account = Some(input_token_account); + self + } + /// The user token account for output token + #[inline(always)] + pub fn output_token_account( + &mut self, + output_token_account: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.output_token_account = Some(output_token_account); + self + } + /// The vault token account for input token + #[inline(always)] + pub fn input_vault( + &mut self, + input_vault: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.input_vault = Some(input_vault); + self + } + /// The vault token account for output token + #[inline(always)] + pub fn output_vault( + &mut self, + output_vault: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.output_vault = Some(output_vault); + self + } + /// SPL program for input token transfers + #[inline(always)] + pub fn input_token_program( + &mut self, + input_token_program: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.input_token_program = Some(input_token_program); + self + } + /// SPL program for output token transfers + #[inline(always)] + pub fn output_token_program( + &mut self, + output_token_program: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.output_token_program = Some(output_token_program); + self + } + /// The mint of input token + #[inline(always)] + pub fn input_token_mint( + &mut self, + input_token_mint: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.input_token_mint = Some(input_token_mint); + self + } + /// The mint of output token + #[inline(always)] + pub fn output_token_mint( + &mut self, + output_token_mint: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.output_token_mint = Some(output_token_mint); + self + } + /// The program account for the most recent oracle observation + #[inline(always)] + pub fn observation_state( + &mut self, + observation_state: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.observation_state = Some(observation_state); + self + } + #[inline(always)] + pub fn max_amount_in(&mut self, max_amount_in: u64) -> &mut Self { + self.instruction.max_amount_in = Some(max_amount_in); + self + } + #[inline(always)] + pub fn amount_out(&mut self, amount_out: u64) -> &mut Self { + self.instruction.amount_out = Some(amount_out); + self + } + /// Add an additional account to the instruction. + #[inline(always)] + pub fn add_remaining_account( + &mut self, + account: &'b solana_account_info::AccountInfo<'a>, + is_writable: bool, + is_signer: bool, + ) -> &mut Self { + self.instruction + .__remaining_accounts + .push((account, is_writable, is_signer)); + self + } + /// Add additional accounts to the instruction. + /// + /// Each account is represented by a tuple of the `AccountInfo`, a `bool` indicating whether the account is writable or not, + /// and a `bool` indicating whether the account is a signer or not. + #[inline(always)] + pub fn add_remaining_accounts( + &mut self, + accounts: &[(&'b solana_account_info::AccountInfo<'a>, bool, bool)], + ) -> &mut Self { + self.instruction + .__remaining_accounts + .extend_from_slice(accounts); + self + } + #[inline(always)] + pub fn invoke(&self) -> solana_program_error::ProgramResult { + self.invoke_signed(&[]) + } + #[allow(clippy::clone_on_copy)] + #[allow(clippy::vec_init_then_push)] + pub fn invoke_signed(&self, signers_seeds: &[&[&[u8]]]) -> solana_program_error::ProgramResult { + let args = SwapBaseOutputInstructionArgs { + max_amount_in: self + .instruction + .max_amount_in + .clone() + .expect("max_amount_in is not set"), + amount_out: self + .instruction + .amount_out + .clone() + .expect("amount_out is not set"), + }; + let instruction = SwapBaseOutputCpi { + __program: self.instruction.__program, + + payer: self.instruction.payer.expect("payer is not set"), + + authority: self.instruction.authority.expect("authority is not set"), + + amm_config: self.instruction.amm_config.expect("amm_config is not set"), + + pool_state: self.instruction.pool_state.expect("pool_state is not set"), + + input_token_account: self + .instruction + .input_token_account + .expect("input_token_account is not set"), + + output_token_account: self + .instruction + .output_token_account + .expect("output_token_account is not set"), + + input_vault: self + .instruction + .input_vault + .expect("input_vault is not set"), + + output_vault: self + .instruction + .output_vault + .expect("output_vault is not set"), + + input_token_program: self + .instruction + .input_token_program + .expect("input_token_program is not set"), + + output_token_program: self + .instruction + .output_token_program + .expect("output_token_program is not set"), + + input_token_mint: self + .instruction + .input_token_mint + .expect("input_token_mint is not set"), + + output_token_mint: self + .instruction + .output_token_mint + .expect("output_token_mint is not set"), + + observation_state: self + .instruction + .observation_state + .expect("observation_state is not set"), + __args: args, + }; + instruction.invoke_signed_with_remaining_accounts( + signers_seeds, + &self.instruction.__remaining_accounts, + ) + } +} + +#[derive(Clone, Debug)] +struct SwapBaseOutputCpiBuilderInstruction<'a, 'b> { + __program: &'b solana_account_info::AccountInfo<'a>, + payer: Option<&'b solana_account_info::AccountInfo<'a>>, + authority: Option<&'b solana_account_info::AccountInfo<'a>>, + amm_config: Option<&'b solana_account_info::AccountInfo<'a>>, + pool_state: Option<&'b solana_account_info::AccountInfo<'a>>, + input_token_account: Option<&'b solana_account_info::AccountInfo<'a>>, + output_token_account: Option<&'b solana_account_info::AccountInfo<'a>>, + input_vault: Option<&'b solana_account_info::AccountInfo<'a>>, + output_vault: Option<&'b solana_account_info::AccountInfo<'a>>, + input_token_program: Option<&'b solana_account_info::AccountInfo<'a>>, + output_token_program: Option<&'b solana_account_info::AccountInfo<'a>>, + input_token_mint: Option<&'b solana_account_info::AccountInfo<'a>>, + output_token_mint: Option<&'b solana_account_info::AccountInfo<'a>>, + observation_state: Option<&'b solana_account_info::AccountInfo<'a>>, + max_amount_in: Option, + amount_out: Option, + /// Additional instruction accounts `(AccountInfo, is_writable, is_signer)`. + __remaining_accounts: Vec<(&'b solana_account_info::AccountInfo<'a>, bool, bool)>, +} diff --git a/e2e/raydium-cpmm/src/generated/instructions/update_amm_config.rs b/e2e/raydium-cpmm/src/generated/instructions/update_amm_config.rs new file mode 100644 index 0000000..d5ace99 --- /dev/null +++ b/e2e/raydium-cpmm/src/generated/instructions/update_amm_config.rs @@ -0,0 +1,370 @@ +//! This code was AUTOGENERATED using the codama library. +//! Please DO NOT EDIT THIS FILE, instead use visitors +//! to add features, then rerun codama to update it. +//! +//! +//! + +use borsh::BorshDeserialize; +use borsh::BorshSerialize; + +pub const UPDATE_AMM_CONFIG_DISCRIMINATOR: [u8; 8] = [49, 60, 174, 136, 154, 28, 116, 200]; + +/// Accounts. +#[derive(Debug)] +pub struct UpdateAmmConfig { + /// The amm config owner or admin + pub owner: solana_address::Address, + /// Amm config account to be changed + pub amm_config: solana_address::Address, +} + +impl UpdateAmmConfig { + pub fn instruction( + &self, + args: UpdateAmmConfigInstructionArgs, + ) -> solana_instruction::Instruction { + self.instruction_with_remaining_accounts(args, &[]) + } + #[allow(clippy::arithmetic_side_effects)] + #[allow(clippy::vec_init_then_push)] + pub fn instruction_with_remaining_accounts( + &self, + args: UpdateAmmConfigInstructionArgs, + remaining_accounts: &[solana_instruction::AccountMeta], + ) -> solana_instruction::Instruction { + let mut accounts = Vec::with_capacity(2 + remaining_accounts.len()); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.owner, true, + )); + accounts.push(solana_instruction::AccountMeta::new(self.amm_config, false)); + accounts.extend_from_slice(remaining_accounts); + let mut data = UpdateAmmConfigInstructionData::new().try_to_vec().unwrap(); + let mut args = args.try_to_vec().unwrap(); + data.append(&mut args); + + solana_instruction::Instruction { + program_id: crate::RAYDIUM_CP_SWAP_ID, + accounts, + data, + } + } +} + +#[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] +pub struct UpdateAmmConfigInstructionData { + discriminator: [u8; 8], +} + +impl UpdateAmmConfigInstructionData { + pub fn new() -> Self { + Self { + discriminator: [49, 60, 174, 136, 154, 28, 116, 200], + } + } + + pub(crate) fn try_to_vec(&self) -> Result, std::io::Error> { + borsh::to_vec(self) + } +} + +impl Default for UpdateAmmConfigInstructionData { + fn default() -> Self { + Self::new() + } +} + +#[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] +pub struct UpdateAmmConfigInstructionArgs { + pub param: u8, + pub value: u64, +} + +impl UpdateAmmConfigInstructionArgs { + pub(crate) fn try_to_vec(&self) -> Result, std::io::Error> { + borsh::to_vec(self) + } +} + +/// Instruction builder for `UpdateAmmConfig`. +/// +/// ### Accounts: +/// +/// 0. `[signer, optional]` owner (default to `GThUX1Atko4tqhN2NaiTazWSeFWMuiUvfFnyJyUghFMJ`) +/// 1. `[writable]` amm_config +#[derive(Clone, Debug, Default)] +pub struct UpdateAmmConfigBuilder { + owner: Option, + amm_config: Option, + param: Option, + value: Option, + __remaining_accounts: Vec, +} + +impl UpdateAmmConfigBuilder { + pub fn new() -> Self { + Self::default() + } + /// `[optional account, default to 'GThUX1Atko4tqhN2NaiTazWSeFWMuiUvfFnyJyUghFMJ']` + /// The amm config owner or admin + #[inline(always)] + pub fn owner(&mut self, owner: solana_address::Address) -> &mut Self { + self.owner = Some(owner); + self + } + /// Amm config account to be changed + #[inline(always)] + pub fn amm_config(&mut self, amm_config: solana_address::Address) -> &mut Self { + self.amm_config = Some(amm_config); + self + } + #[inline(always)] + pub fn param(&mut self, param: u8) -> &mut Self { + self.param = Some(param); + self + } + #[inline(always)] + pub fn value(&mut self, value: u64) -> &mut Self { + self.value = Some(value); + self + } + /// Add an additional account to the instruction. + #[inline(always)] + pub fn add_remaining_account(&mut self, account: solana_instruction::AccountMeta) -> &mut Self { + self.__remaining_accounts.push(account); + self + } + /// Add additional accounts to the instruction. + #[inline(always)] + pub fn add_remaining_accounts( + &mut self, + accounts: &[solana_instruction::AccountMeta], + ) -> &mut Self { + self.__remaining_accounts.extend_from_slice(accounts); + self + } + #[allow(clippy::clone_on_copy)] + pub fn instruction(&self) -> solana_instruction::Instruction { + let accounts = UpdateAmmConfig { + owner: self.owner.unwrap_or(solana_address::address!( + "GThUX1Atko4tqhN2NaiTazWSeFWMuiUvfFnyJyUghFMJ" + )), + amm_config: self.amm_config.expect("amm_config is not set"), + }; + let args = UpdateAmmConfigInstructionArgs { + param: self.param.clone().expect("param is not set"), + value: self.value.clone().expect("value is not set"), + }; + + accounts.instruction_with_remaining_accounts(args, &self.__remaining_accounts) + } +} + +/// `update_amm_config` CPI accounts. +pub struct UpdateAmmConfigCpiAccounts<'a, 'b> { + /// The amm config owner or admin + pub owner: &'b solana_account_info::AccountInfo<'a>, + /// Amm config account to be changed + pub amm_config: &'b solana_account_info::AccountInfo<'a>, +} + +/// `update_amm_config` CPI instruction. +pub struct UpdateAmmConfigCpi<'a, 'b> { + /// The program to invoke. + pub __program: &'b solana_account_info::AccountInfo<'a>, + /// The amm config owner or admin + pub owner: &'b solana_account_info::AccountInfo<'a>, + /// Amm config account to be changed + pub amm_config: &'b solana_account_info::AccountInfo<'a>, + /// The arguments for the instruction. + pub __args: UpdateAmmConfigInstructionArgs, +} + +impl<'a, 'b> UpdateAmmConfigCpi<'a, 'b> { + pub fn new( + program: &'b solana_account_info::AccountInfo<'a>, + accounts: UpdateAmmConfigCpiAccounts<'a, 'b>, + args: UpdateAmmConfigInstructionArgs, + ) -> Self { + Self { + __program: program, + owner: accounts.owner, + amm_config: accounts.amm_config, + __args: args, + } + } + #[inline(always)] + pub fn invoke(&self) -> solana_program_error::ProgramResult { + self.invoke_signed_with_remaining_accounts(&[], &[]) + } + #[inline(always)] + pub fn invoke_with_remaining_accounts( + &self, + remaining_accounts: &[(&'b solana_account_info::AccountInfo<'a>, bool, bool)], + ) -> solana_program_error::ProgramResult { + self.invoke_signed_with_remaining_accounts(&[], remaining_accounts) + } + #[inline(always)] + pub fn invoke_signed(&self, signers_seeds: &[&[&[u8]]]) -> solana_program_error::ProgramResult { + self.invoke_signed_with_remaining_accounts(signers_seeds, &[]) + } + #[allow(clippy::arithmetic_side_effects)] + #[allow(clippy::clone_on_copy)] + #[allow(clippy::vec_init_then_push)] + pub fn invoke_signed_with_remaining_accounts( + &self, + signers_seeds: &[&[&[u8]]], + remaining_accounts: &[(&'b solana_account_info::AccountInfo<'a>, bool, bool)], + ) -> solana_program_error::ProgramResult { + let mut accounts = Vec::with_capacity(2 + remaining_accounts.len()); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.owner.key, + true, + )); + accounts.push(solana_instruction::AccountMeta::new( + *self.amm_config.key, + false, + )); + remaining_accounts.iter().for_each(|remaining_account| { + accounts.push(solana_instruction::AccountMeta { + pubkey: *remaining_account.0.key, + is_signer: remaining_account.1, + is_writable: remaining_account.2, + }) + }); + let mut data = UpdateAmmConfigInstructionData::new().try_to_vec().unwrap(); + let mut args = self.__args.try_to_vec().unwrap(); + data.append(&mut args); + + let instruction = solana_instruction::Instruction { + program_id: crate::RAYDIUM_CP_SWAP_ID, + accounts, + data, + }; + let mut account_infos = Vec::with_capacity(3 + remaining_accounts.len()); + account_infos.push(self.__program.clone()); + account_infos.push(self.owner.clone()); + account_infos.push(self.amm_config.clone()); + remaining_accounts + .iter() + .for_each(|remaining_account| account_infos.push(remaining_account.0.clone())); + + if signers_seeds.is_empty() { + solana_cpi::invoke(&instruction, &account_infos) + } else { + solana_cpi::invoke_signed(&instruction, &account_infos, signers_seeds) + } + } +} + +/// Instruction builder for `UpdateAmmConfig` via CPI. +/// +/// ### Accounts: +/// +/// 0. `[signer]` owner +/// 1. `[writable]` amm_config +#[derive(Clone, Debug)] +pub struct UpdateAmmConfigCpiBuilder<'a, 'b> { + instruction: Box>, +} + +impl<'a, 'b> UpdateAmmConfigCpiBuilder<'a, 'b> { + pub fn new(program: &'b solana_account_info::AccountInfo<'a>) -> Self { + let instruction = Box::new(UpdateAmmConfigCpiBuilderInstruction { + __program: program, + owner: None, + amm_config: None, + param: None, + value: None, + __remaining_accounts: Vec::new(), + }); + Self { instruction } + } + /// The amm config owner or admin + #[inline(always)] + pub fn owner(&mut self, owner: &'b solana_account_info::AccountInfo<'a>) -> &mut Self { + self.instruction.owner = Some(owner); + self + } + /// Amm config account to be changed + #[inline(always)] + pub fn amm_config( + &mut self, + amm_config: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.amm_config = Some(amm_config); + self + } + #[inline(always)] + pub fn param(&mut self, param: u8) -> &mut Self { + self.instruction.param = Some(param); + self + } + #[inline(always)] + pub fn value(&mut self, value: u64) -> &mut Self { + self.instruction.value = Some(value); + self + } + /// Add an additional account to the instruction. + #[inline(always)] + pub fn add_remaining_account( + &mut self, + account: &'b solana_account_info::AccountInfo<'a>, + is_writable: bool, + is_signer: bool, + ) -> &mut Self { + self.instruction + .__remaining_accounts + .push((account, is_writable, is_signer)); + self + } + /// Add additional accounts to the instruction. + /// + /// Each account is represented by a tuple of the `AccountInfo`, a `bool` indicating whether the account is writable or not, + /// and a `bool` indicating whether the account is a signer or not. + #[inline(always)] + pub fn add_remaining_accounts( + &mut self, + accounts: &[(&'b solana_account_info::AccountInfo<'a>, bool, bool)], + ) -> &mut Self { + self.instruction + .__remaining_accounts + .extend_from_slice(accounts); + self + } + #[inline(always)] + pub fn invoke(&self) -> solana_program_error::ProgramResult { + self.invoke_signed(&[]) + } + #[allow(clippy::clone_on_copy)] + #[allow(clippy::vec_init_then_push)] + pub fn invoke_signed(&self, signers_seeds: &[&[&[u8]]]) -> solana_program_error::ProgramResult { + let args = UpdateAmmConfigInstructionArgs { + param: self.instruction.param.clone().expect("param is not set"), + value: self.instruction.value.clone().expect("value is not set"), + }; + let instruction = UpdateAmmConfigCpi { + __program: self.instruction.__program, + + owner: self.instruction.owner.expect("owner is not set"), + + amm_config: self.instruction.amm_config.expect("amm_config is not set"), + __args: args, + }; + instruction.invoke_signed_with_remaining_accounts( + signers_seeds, + &self.instruction.__remaining_accounts, + ) + } +} + +#[derive(Clone, Debug)] +struct UpdateAmmConfigCpiBuilderInstruction<'a, 'b> { + __program: &'b solana_account_info::AccountInfo<'a>, + owner: Option<&'b solana_account_info::AccountInfo<'a>>, + amm_config: Option<&'b solana_account_info::AccountInfo<'a>>, + param: Option, + value: Option, + /// Additional instruction accounts `(AccountInfo, is_writable, is_signer)`. + __remaining_accounts: Vec<(&'b solana_account_info::AccountInfo<'a>, bool, bool)>, +} diff --git a/e2e/raydium-cpmm/src/generated/instructions/update_pool_status.rs b/e2e/raydium-cpmm/src/generated/instructions/update_pool_status.rs new file mode 100644 index 0000000..7880400 --- /dev/null +++ b/e2e/raydium-cpmm/src/generated/instructions/update_pool_status.rs @@ -0,0 +1,349 @@ +//! This code was AUTOGENERATED using the codama library. +//! Please DO NOT EDIT THIS FILE, instead use visitors +//! to add features, then rerun codama to update it. +//! +//! +//! + +use borsh::BorshDeserialize; +use borsh::BorshSerialize; + +pub const UPDATE_POOL_STATUS_DISCRIMINATOR: [u8; 8] = [130, 87, 108, 6, 46, 224, 117, 123]; + +/// Accounts. +#[derive(Debug)] +pub struct UpdatePoolStatus { + pub authority: solana_address::Address, + + pub pool_state: solana_address::Address, +} + +impl UpdatePoolStatus { + pub fn instruction( + &self, + args: UpdatePoolStatusInstructionArgs, + ) -> solana_instruction::Instruction { + self.instruction_with_remaining_accounts(args, &[]) + } + #[allow(clippy::arithmetic_side_effects)] + #[allow(clippy::vec_init_then_push)] + pub fn instruction_with_remaining_accounts( + &self, + args: UpdatePoolStatusInstructionArgs, + remaining_accounts: &[solana_instruction::AccountMeta], + ) -> solana_instruction::Instruction { + let mut accounts = Vec::with_capacity(2 + remaining_accounts.len()); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.authority, + true, + )); + accounts.push(solana_instruction::AccountMeta::new(self.pool_state, false)); + accounts.extend_from_slice(remaining_accounts); + let mut data = UpdatePoolStatusInstructionData::new().try_to_vec().unwrap(); + let mut args = args.try_to_vec().unwrap(); + data.append(&mut args); + + solana_instruction::Instruction { + program_id: crate::RAYDIUM_CP_SWAP_ID, + accounts, + data, + } + } +} + +#[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] +pub struct UpdatePoolStatusInstructionData { + discriminator: [u8; 8], +} + +impl UpdatePoolStatusInstructionData { + pub fn new() -> Self { + Self { + discriminator: [130, 87, 108, 6, 46, 224, 117, 123], + } + } + + pub(crate) fn try_to_vec(&self) -> Result, std::io::Error> { + borsh::to_vec(self) + } +} + +impl Default for UpdatePoolStatusInstructionData { + fn default() -> Self { + Self::new() + } +} + +#[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] +pub struct UpdatePoolStatusInstructionArgs { + pub status: u8, +} + +impl UpdatePoolStatusInstructionArgs { + pub(crate) fn try_to_vec(&self) -> Result, std::io::Error> { + borsh::to_vec(self) + } +} + +/// Instruction builder for `UpdatePoolStatus`. +/// +/// ### Accounts: +/// +/// 0. `[signer, optional]` authority (default to `GThUX1Atko4tqhN2NaiTazWSeFWMuiUvfFnyJyUghFMJ`) +/// 1. `[writable]` pool_state +#[derive(Clone, Debug, Default)] +pub struct UpdatePoolStatusBuilder { + authority: Option, + pool_state: Option, + status: Option, + __remaining_accounts: Vec, +} + +impl UpdatePoolStatusBuilder { + pub fn new() -> Self { + Self::default() + } + /// `[optional account, default to 'GThUX1Atko4tqhN2NaiTazWSeFWMuiUvfFnyJyUghFMJ']` + #[inline(always)] + pub fn authority(&mut self, authority: solana_address::Address) -> &mut Self { + self.authority = Some(authority); + self + } + #[inline(always)] + pub fn pool_state(&mut self, pool_state: solana_address::Address) -> &mut Self { + self.pool_state = Some(pool_state); + self + } + #[inline(always)] + pub fn status(&mut self, status: u8) -> &mut Self { + self.status = Some(status); + self + } + /// Add an additional account to the instruction. + #[inline(always)] + pub fn add_remaining_account(&mut self, account: solana_instruction::AccountMeta) -> &mut Self { + self.__remaining_accounts.push(account); + self + } + /// Add additional accounts to the instruction. + #[inline(always)] + pub fn add_remaining_accounts( + &mut self, + accounts: &[solana_instruction::AccountMeta], + ) -> &mut Self { + self.__remaining_accounts.extend_from_slice(accounts); + self + } + #[allow(clippy::clone_on_copy)] + pub fn instruction(&self) -> solana_instruction::Instruction { + let accounts = UpdatePoolStatus { + authority: self.authority.unwrap_or(solana_address::address!( + "GThUX1Atko4tqhN2NaiTazWSeFWMuiUvfFnyJyUghFMJ" + )), + pool_state: self.pool_state.expect("pool_state is not set"), + }; + let args = UpdatePoolStatusInstructionArgs { + status: self.status.clone().expect("status is not set"), + }; + + accounts.instruction_with_remaining_accounts(args, &self.__remaining_accounts) + } +} + +/// `update_pool_status` CPI accounts. +pub struct UpdatePoolStatusCpiAccounts<'a, 'b> { + pub authority: &'b solana_account_info::AccountInfo<'a>, + + pub pool_state: &'b solana_account_info::AccountInfo<'a>, +} + +/// `update_pool_status` CPI instruction. +pub struct UpdatePoolStatusCpi<'a, 'b> { + /// The program to invoke. + pub __program: &'b solana_account_info::AccountInfo<'a>, + + pub authority: &'b solana_account_info::AccountInfo<'a>, + + pub pool_state: &'b solana_account_info::AccountInfo<'a>, + /// The arguments for the instruction. + pub __args: UpdatePoolStatusInstructionArgs, +} + +impl<'a, 'b> UpdatePoolStatusCpi<'a, 'b> { + pub fn new( + program: &'b solana_account_info::AccountInfo<'a>, + accounts: UpdatePoolStatusCpiAccounts<'a, 'b>, + args: UpdatePoolStatusInstructionArgs, + ) -> Self { + Self { + __program: program, + authority: accounts.authority, + pool_state: accounts.pool_state, + __args: args, + } + } + #[inline(always)] + pub fn invoke(&self) -> solana_program_error::ProgramResult { + self.invoke_signed_with_remaining_accounts(&[], &[]) + } + #[inline(always)] + pub fn invoke_with_remaining_accounts( + &self, + remaining_accounts: &[(&'b solana_account_info::AccountInfo<'a>, bool, bool)], + ) -> solana_program_error::ProgramResult { + self.invoke_signed_with_remaining_accounts(&[], remaining_accounts) + } + #[inline(always)] + pub fn invoke_signed(&self, signers_seeds: &[&[&[u8]]]) -> solana_program_error::ProgramResult { + self.invoke_signed_with_remaining_accounts(signers_seeds, &[]) + } + #[allow(clippy::arithmetic_side_effects)] + #[allow(clippy::clone_on_copy)] + #[allow(clippy::vec_init_then_push)] + pub fn invoke_signed_with_remaining_accounts( + &self, + signers_seeds: &[&[&[u8]]], + remaining_accounts: &[(&'b solana_account_info::AccountInfo<'a>, bool, bool)], + ) -> solana_program_error::ProgramResult { + let mut accounts = Vec::with_capacity(2 + remaining_accounts.len()); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.authority.key, + true, + )); + accounts.push(solana_instruction::AccountMeta::new( + *self.pool_state.key, + false, + )); + remaining_accounts.iter().for_each(|remaining_account| { + accounts.push(solana_instruction::AccountMeta { + pubkey: *remaining_account.0.key, + is_signer: remaining_account.1, + is_writable: remaining_account.2, + }) + }); + let mut data = UpdatePoolStatusInstructionData::new().try_to_vec().unwrap(); + let mut args = self.__args.try_to_vec().unwrap(); + data.append(&mut args); + + let instruction = solana_instruction::Instruction { + program_id: crate::RAYDIUM_CP_SWAP_ID, + accounts, + data, + }; + let mut account_infos = Vec::with_capacity(3 + remaining_accounts.len()); + account_infos.push(self.__program.clone()); + account_infos.push(self.authority.clone()); + account_infos.push(self.pool_state.clone()); + remaining_accounts + .iter() + .for_each(|remaining_account| account_infos.push(remaining_account.0.clone())); + + if signers_seeds.is_empty() { + solana_cpi::invoke(&instruction, &account_infos) + } else { + solana_cpi::invoke_signed(&instruction, &account_infos, signers_seeds) + } + } +} + +/// Instruction builder for `UpdatePoolStatus` via CPI. +/// +/// ### Accounts: +/// +/// 0. `[signer]` authority +/// 1. `[writable]` pool_state +#[derive(Clone, Debug)] +pub struct UpdatePoolStatusCpiBuilder<'a, 'b> { + instruction: Box>, +} + +impl<'a, 'b> UpdatePoolStatusCpiBuilder<'a, 'b> { + pub fn new(program: &'b solana_account_info::AccountInfo<'a>) -> Self { + let instruction = Box::new(UpdatePoolStatusCpiBuilderInstruction { + __program: program, + authority: None, + pool_state: None, + status: None, + __remaining_accounts: Vec::new(), + }); + Self { instruction } + } + #[inline(always)] + pub fn authority(&mut self, authority: &'b solana_account_info::AccountInfo<'a>) -> &mut Self { + self.instruction.authority = Some(authority); + self + } + #[inline(always)] + pub fn pool_state( + &mut self, + pool_state: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.pool_state = Some(pool_state); + self + } + #[inline(always)] + pub fn status(&mut self, status: u8) -> &mut Self { + self.instruction.status = Some(status); + self + } + /// Add an additional account to the instruction. + #[inline(always)] + pub fn add_remaining_account( + &mut self, + account: &'b solana_account_info::AccountInfo<'a>, + is_writable: bool, + is_signer: bool, + ) -> &mut Self { + self.instruction + .__remaining_accounts + .push((account, is_writable, is_signer)); + self + } + /// Add additional accounts to the instruction. + /// + /// Each account is represented by a tuple of the `AccountInfo`, a `bool` indicating whether the account is writable or not, + /// and a `bool` indicating whether the account is a signer or not. + #[inline(always)] + pub fn add_remaining_accounts( + &mut self, + accounts: &[(&'b solana_account_info::AccountInfo<'a>, bool, bool)], + ) -> &mut Self { + self.instruction + .__remaining_accounts + .extend_from_slice(accounts); + self + } + #[inline(always)] + pub fn invoke(&self) -> solana_program_error::ProgramResult { + self.invoke_signed(&[]) + } + #[allow(clippy::clone_on_copy)] + #[allow(clippy::vec_init_then_push)] + pub fn invoke_signed(&self, signers_seeds: &[&[&[u8]]]) -> solana_program_error::ProgramResult { + let args = UpdatePoolStatusInstructionArgs { + status: self.instruction.status.clone().expect("status is not set"), + }; + let instruction = UpdatePoolStatusCpi { + __program: self.instruction.__program, + + authority: self.instruction.authority.expect("authority is not set"), + + pool_state: self.instruction.pool_state.expect("pool_state is not set"), + __args: args, + }; + instruction.invoke_signed_with_remaining_accounts( + signers_seeds, + &self.instruction.__remaining_accounts, + ) + } +} + +#[derive(Clone, Debug)] +struct UpdatePoolStatusCpiBuilderInstruction<'a, 'b> { + __program: &'b solana_account_info::AccountInfo<'a>, + authority: Option<&'b solana_account_info::AccountInfo<'a>>, + pool_state: Option<&'b solana_account_info::AccountInfo<'a>>, + status: Option, + /// Additional instruction accounts `(AccountInfo, is_writable, is_signer)`. + __remaining_accounts: Vec<(&'b solana_account_info::AccountInfo<'a>, bool, bool)>, +} diff --git a/e2e/raydium-cpmm/src/generated/instructions/withdraw.rs b/e2e/raydium-cpmm/src/generated/instructions/withdraw.rs new file mode 100644 index 0000000..26e855e --- /dev/null +++ b/e2e/raydium-cpmm/src/generated/instructions/withdraw.rs @@ -0,0 +1,897 @@ +//! This code was AUTOGENERATED using the codama library. +//! Please DO NOT EDIT THIS FILE, instead use visitors +//! to add features, then rerun codama to update it. +//! +//! +//! + +use borsh::BorshDeserialize; +use borsh::BorshSerialize; + +pub const WITHDRAW_DISCRIMINATOR: [u8; 8] = [183, 18, 70, 156, 148, 109, 161, 34]; + +/// Accounts. +#[derive(Debug)] +pub struct Withdraw { + /// Pays to mint the position + pub owner: solana_address::Address, + + pub authority: solana_address::Address, + /// Pool state account + pub pool_state: solana_address::Address, + /// Owner lp token account + pub owner_lp_token: solana_address::Address, + /// The token account for receive token_0, + pub token0_account: solana_address::Address, + /// The token account for receive token_1 + pub token1_account: solana_address::Address, + /// The address that holds pool tokens for token_0 + pub token0_vault: solana_address::Address, + /// The address that holds pool tokens for token_1 + pub token1_vault: solana_address::Address, + /// token Program + pub token_program: solana_address::Address, + /// Token program 2022 + pub token_program2022: solana_address::Address, + /// The mint of token_0 vault + pub vault0_mint: solana_address::Address, + /// The mint of token_1 vault + pub vault1_mint: solana_address::Address, + /// Pool lp token mint + pub lp_mint: solana_address::Address, + /// memo program + pub memo_program: solana_address::Address, +} + +impl Withdraw { + pub fn instruction(&self, args: WithdrawInstructionArgs) -> solana_instruction::Instruction { + self.instruction_with_remaining_accounts(args, &[]) + } + #[allow(clippy::arithmetic_side_effects)] + #[allow(clippy::vec_init_then_push)] + pub fn instruction_with_remaining_accounts( + &self, + args: WithdrawInstructionArgs, + remaining_accounts: &[solana_instruction::AccountMeta], + ) -> solana_instruction::Instruction { + let mut accounts = Vec::with_capacity(14 + remaining_accounts.len()); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.owner, true, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.authority, + false, + )); + accounts.push(solana_instruction::AccountMeta::new(self.pool_state, false)); + accounts.push(solana_instruction::AccountMeta::new( + self.owner_lp_token, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + self.token0_account, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + self.token1_account, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + self.token0_vault, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + self.token1_vault, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.token_program, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.token_program2022, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.vault0_mint, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.vault1_mint, + false, + )); + accounts.push(solana_instruction::AccountMeta::new(self.lp_mint, false)); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.memo_program, + false, + )); + accounts.extend_from_slice(remaining_accounts); + let mut data = WithdrawInstructionData::new().try_to_vec().unwrap(); + let mut args = args.try_to_vec().unwrap(); + data.append(&mut args); + + solana_instruction::Instruction { + program_id: crate::RAYDIUM_CP_SWAP_ID, + accounts, + data, + } + } +} + +#[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] +pub struct WithdrawInstructionData { + discriminator: [u8; 8], +} + +impl WithdrawInstructionData { + pub fn new() -> Self { + Self { + discriminator: [183, 18, 70, 156, 148, 109, 161, 34], + } + } + + pub(crate) fn try_to_vec(&self) -> Result, std::io::Error> { + borsh::to_vec(self) + } +} + +impl Default for WithdrawInstructionData { + fn default() -> Self { + Self::new() + } +} + +#[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] +pub struct WithdrawInstructionArgs { + pub lp_token_amount: u64, + pub minimum_token0_amount: u64, + pub minimum_token1_amount: u64, +} + +impl WithdrawInstructionArgs { + pub(crate) fn try_to_vec(&self) -> Result, std::io::Error> { + borsh::to_vec(self) + } +} + +/// Instruction builder for `Withdraw`. +/// +/// ### Accounts: +/// +/// 0. `[signer]` owner +/// 1. `[]` authority +/// 2. `[writable]` pool_state +/// 3. `[writable]` owner_lp_token +/// 4. `[writable]` token0_account +/// 5. `[writable]` token1_account +/// 6. `[writable]` token0_vault +/// 7. `[writable]` token1_vault +/// 8. `[optional]` token_program (default to `TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA`) +/// 9. `[optional]` token_program2022 (default to `TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb`) +/// 10. `[]` vault0_mint +/// 11. `[]` vault1_mint +/// 12. `[writable]` lp_mint +/// 13. `[optional]` memo_program (default to `MemoSq4gqABAXKb96qnH8TysNcWxMyWCqXgDLGmfcHr`) +#[derive(Clone, Debug, Default)] +pub struct WithdrawBuilder { + owner: Option, + authority: Option, + pool_state: Option, + owner_lp_token: Option, + token0_account: Option, + token1_account: Option, + token0_vault: Option, + token1_vault: Option, + token_program: Option, + token_program2022: Option, + vault0_mint: Option, + vault1_mint: Option, + lp_mint: Option, + memo_program: Option, + lp_token_amount: Option, + minimum_token0_amount: Option, + minimum_token1_amount: Option, + __remaining_accounts: Vec, +} + +impl WithdrawBuilder { + pub fn new() -> Self { + Self::default() + } + /// Pays to mint the position + #[inline(always)] + pub fn owner(&mut self, owner: solana_address::Address) -> &mut Self { + self.owner = Some(owner); + self + } + #[inline(always)] + pub fn authority(&mut self, authority: solana_address::Address) -> &mut Self { + self.authority = Some(authority); + self + } + /// Pool state account + #[inline(always)] + pub fn pool_state(&mut self, pool_state: solana_address::Address) -> &mut Self { + self.pool_state = Some(pool_state); + self + } + /// Owner lp token account + #[inline(always)] + pub fn owner_lp_token(&mut self, owner_lp_token: solana_address::Address) -> &mut Self { + self.owner_lp_token = Some(owner_lp_token); + self + } + /// The token account for receive token_0, + #[inline(always)] + pub fn token0_account(&mut self, token0_account: solana_address::Address) -> &mut Self { + self.token0_account = Some(token0_account); + self + } + /// The token account for receive token_1 + #[inline(always)] + pub fn token1_account(&mut self, token1_account: solana_address::Address) -> &mut Self { + self.token1_account = Some(token1_account); + self + } + /// The address that holds pool tokens for token_0 + #[inline(always)] + pub fn token0_vault(&mut self, token0_vault: solana_address::Address) -> &mut Self { + self.token0_vault = Some(token0_vault); + self + } + /// The address that holds pool tokens for token_1 + #[inline(always)] + pub fn token1_vault(&mut self, token1_vault: solana_address::Address) -> &mut Self { + self.token1_vault = Some(token1_vault); + self + } + /// `[optional account, default to 'TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA']` + /// token Program + #[inline(always)] + pub fn token_program(&mut self, token_program: solana_address::Address) -> &mut Self { + self.token_program = Some(token_program); + self + } + /// `[optional account, default to 'TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb']` + /// Token program 2022 + #[inline(always)] + pub fn token_program2022(&mut self, token_program2022: solana_address::Address) -> &mut Self { + self.token_program2022 = Some(token_program2022); + self + } + /// The mint of token_0 vault + #[inline(always)] + pub fn vault0_mint(&mut self, vault0_mint: solana_address::Address) -> &mut Self { + self.vault0_mint = Some(vault0_mint); + self + } + /// The mint of token_1 vault + #[inline(always)] + pub fn vault1_mint(&mut self, vault1_mint: solana_address::Address) -> &mut Self { + self.vault1_mint = Some(vault1_mint); + self + } + /// Pool lp token mint + #[inline(always)] + pub fn lp_mint(&mut self, lp_mint: solana_address::Address) -> &mut Self { + self.lp_mint = Some(lp_mint); + self + } + /// `[optional account, default to 'MemoSq4gqABAXKb96qnH8TysNcWxMyWCqXgDLGmfcHr']` + /// memo program + #[inline(always)] + pub fn memo_program(&mut self, memo_program: solana_address::Address) -> &mut Self { + self.memo_program = Some(memo_program); + self + } + #[inline(always)] + pub fn lp_token_amount(&mut self, lp_token_amount: u64) -> &mut Self { + self.lp_token_amount = Some(lp_token_amount); + self + } + #[inline(always)] + pub fn minimum_token0_amount(&mut self, minimum_token0_amount: u64) -> &mut Self { + self.minimum_token0_amount = Some(minimum_token0_amount); + self + } + #[inline(always)] + pub fn minimum_token1_amount(&mut self, minimum_token1_amount: u64) -> &mut Self { + self.minimum_token1_amount = Some(minimum_token1_amount); + self + } + /// Add an additional account to the instruction. + #[inline(always)] + pub fn add_remaining_account(&mut self, account: solana_instruction::AccountMeta) -> &mut Self { + self.__remaining_accounts.push(account); + self + } + /// Add additional accounts to the instruction. + #[inline(always)] + pub fn add_remaining_accounts( + &mut self, + accounts: &[solana_instruction::AccountMeta], + ) -> &mut Self { + self.__remaining_accounts.extend_from_slice(accounts); + self + } + #[allow(clippy::clone_on_copy)] + pub fn instruction(&self) -> solana_instruction::Instruction { + let accounts = Withdraw { + owner: self.owner.expect("owner is not set"), + authority: self.authority.expect("authority is not set"), + pool_state: self.pool_state.expect("pool_state is not set"), + owner_lp_token: self.owner_lp_token.expect("owner_lp_token is not set"), + token0_account: self.token0_account.expect("token0_account is not set"), + token1_account: self.token1_account.expect("token1_account is not set"), + token0_vault: self.token0_vault.expect("token0_vault is not set"), + token1_vault: self.token1_vault.expect("token1_vault is not set"), + token_program: self.token_program.unwrap_or(solana_address::address!( + "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA" + )), + token_program2022: self.token_program2022.unwrap_or(solana_address::address!( + "TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb" + )), + vault0_mint: self.vault0_mint.expect("vault0_mint is not set"), + vault1_mint: self.vault1_mint.expect("vault1_mint is not set"), + lp_mint: self.lp_mint.expect("lp_mint is not set"), + memo_program: self.memo_program.unwrap_or(solana_address::address!( + "MemoSq4gqABAXKb96qnH8TysNcWxMyWCqXgDLGmfcHr" + )), + }; + let args = WithdrawInstructionArgs { + lp_token_amount: self + .lp_token_amount + .clone() + .expect("lp_token_amount is not set"), + minimum_token0_amount: self + .minimum_token0_amount + .clone() + .expect("minimum_token0_amount is not set"), + minimum_token1_amount: self + .minimum_token1_amount + .clone() + .expect("minimum_token1_amount is not set"), + }; + + accounts.instruction_with_remaining_accounts(args, &self.__remaining_accounts) + } +} + +/// `withdraw` CPI accounts. +pub struct WithdrawCpiAccounts<'a, 'b> { + /// Pays to mint the position + pub owner: &'b solana_account_info::AccountInfo<'a>, + + pub authority: &'b solana_account_info::AccountInfo<'a>, + /// Pool state account + pub pool_state: &'b solana_account_info::AccountInfo<'a>, + /// Owner lp token account + pub owner_lp_token: &'b solana_account_info::AccountInfo<'a>, + /// The token account for receive token_0, + pub token0_account: &'b solana_account_info::AccountInfo<'a>, + /// The token account for receive token_1 + pub token1_account: &'b solana_account_info::AccountInfo<'a>, + /// The address that holds pool tokens for token_0 + pub token0_vault: &'b solana_account_info::AccountInfo<'a>, + /// The address that holds pool tokens for token_1 + pub token1_vault: &'b solana_account_info::AccountInfo<'a>, + /// token Program + pub token_program: &'b solana_account_info::AccountInfo<'a>, + /// Token program 2022 + pub token_program2022: &'b solana_account_info::AccountInfo<'a>, + /// The mint of token_0 vault + pub vault0_mint: &'b solana_account_info::AccountInfo<'a>, + /// The mint of token_1 vault + pub vault1_mint: &'b solana_account_info::AccountInfo<'a>, + /// Pool lp token mint + pub lp_mint: &'b solana_account_info::AccountInfo<'a>, + /// memo program + pub memo_program: &'b solana_account_info::AccountInfo<'a>, +} + +/// `withdraw` CPI instruction. +pub struct WithdrawCpi<'a, 'b> { + /// The program to invoke. + pub __program: &'b solana_account_info::AccountInfo<'a>, + /// Pays to mint the position + pub owner: &'b solana_account_info::AccountInfo<'a>, + + pub authority: &'b solana_account_info::AccountInfo<'a>, + /// Pool state account + pub pool_state: &'b solana_account_info::AccountInfo<'a>, + /// Owner lp token account + pub owner_lp_token: &'b solana_account_info::AccountInfo<'a>, + /// The token account for receive token_0, + pub token0_account: &'b solana_account_info::AccountInfo<'a>, + /// The token account for receive token_1 + pub token1_account: &'b solana_account_info::AccountInfo<'a>, + /// The address that holds pool tokens for token_0 + pub token0_vault: &'b solana_account_info::AccountInfo<'a>, + /// The address that holds pool tokens for token_1 + pub token1_vault: &'b solana_account_info::AccountInfo<'a>, + /// token Program + pub token_program: &'b solana_account_info::AccountInfo<'a>, + /// Token program 2022 + pub token_program2022: &'b solana_account_info::AccountInfo<'a>, + /// The mint of token_0 vault + pub vault0_mint: &'b solana_account_info::AccountInfo<'a>, + /// The mint of token_1 vault + pub vault1_mint: &'b solana_account_info::AccountInfo<'a>, + /// Pool lp token mint + pub lp_mint: &'b solana_account_info::AccountInfo<'a>, + /// memo program + pub memo_program: &'b solana_account_info::AccountInfo<'a>, + /// The arguments for the instruction. + pub __args: WithdrawInstructionArgs, +} + +impl<'a, 'b> WithdrawCpi<'a, 'b> { + pub fn new( + program: &'b solana_account_info::AccountInfo<'a>, + accounts: WithdrawCpiAccounts<'a, 'b>, + args: WithdrawInstructionArgs, + ) -> Self { + Self { + __program: program, + owner: accounts.owner, + authority: accounts.authority, + pool_state: accounts.pool_state, + owner_lp_token: accounts.owner_lp_token, + token0_account: accounts.token0_account, + token1_account: accounts.token1_account, + token0_vault: accounts.token0_vault, + token1_vault: accounts.token1_vault, + token_program: accounts.token_program, + token_program2022: accounts.token_program2022, + vault0_mint: accounts.vault0_mint, + vault1_mint: accounts.vault1_mint, + lp_mint: accounts.lp_mint, + memo_program: accounts.memo_program, + __args: args, + } + } + #[inline(always)] + pub fn invoke(&self) -> solana_program_error::ProgramResult { + self.invoke_signed_with_remaining_accounts(&[], &[]) + } + #[inline(always)] + pub fn invoke_with_remaining_accounts( + &self, + remaining_accounts: &[(&'b solana_account_info::AccountInfo<'a>, bool, bool)], + ) -> solana_program_error::ProgramResult { + self.invoke_signed_with_remaining_accounts(&[], remaining_accounts) + } + #[inline(always)] + pub fn invoke_signed(&self, signers_seeds: &[&[&[u8]]]) -> solana_program_error::ProgramResult { + self.invoke_signed_with_remaining_accounts(signers_seeds, &[]) + } + #[allow(clippy::arithmetic_side_effects)] + #[allow(clippy::clone_on_copy)] + #[allow(clippy::vec_init_then_push)] + pub fn invoke_signed_with_remaining_accounts( + &self, + signers_seeds: &[&[&[u8]]], + remaining_accounts: &[(&'b solana_account_info::AccountInfo<'a>, bool, bool)], + ) -> solana_program_error::ProgramResult { + let mut accounts = Vec::with_capacity(14 + remaining_accounts.len()); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.owner.key, + true, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.authority.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + *self.pool_state.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + *self.owner_lp_token.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + *self.token0_account.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + *self.token1_account.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + *self.token0_vault.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + *self.token1_vault.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.token_program.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.token_program2022.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.vault0_mint.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.vault1_mint.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + *self.lp_mint.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.memo_program.key, + false, + )); + remaining_accounts.iter().for_each(|remaining_account| { + accounts.push(solana_instruction::AccountMeta { + pubkey: *remaining_account.0.key, + is_signer: remaining_account.1, + is_writable: remaining_account.2, + }) + }); + let mut data = WithdrawInstructionData::new().try_to_vec().unwrap(); + let mut args = self.__args.try_to_vec().unwrap(); + data.append(&mut args); + + let instruction = solana_instruction::Instruction { + program_id: crate::RAYDIUM_CP_SWAP_ID, + accounts, + data, + }; + let mut account_infos = Vec::with_capacity(15 + remaining_accounts.len()); + account_infos.push(self.__program.clone()); + account_infos.push(self.owner.clone()); + account_infos.push(self.authority.clone()); + account_infos.push(self.pool_state.clone()); + account_infos.push(self.owner_lp_token.clone()); + account_infos.push(self.token0_account.clone()); + account_infos.push(self.token1_account.clone()); + account_infos.push(self.token0_vault.clone()); + account_infos.push(self.token1_vault.clone()); + account_infos.push(self.token_program.clone()); + account_infos.push(self.token_program2022.clone()); + account_infos.push(self.vault0_mint.clone()); + account_infos.push(self.vault1_mint.clone()); + account_infos.push(self.lp_mint.clone()); + account_infos.push(self.memo_program.clone()); + remaining_accounts + .iter() + .for_each(|remaining_account| account_infos.push(remaining_account.0.clone())); + + if signers_seeds.is_empty() { + solana_cpi::invoke(&instruction, &account_infos) + } else { + solana_cpi::invoke_signed(&instruction, &account_infos, signers_seeds) + } + } +} + +/// Instruction builder for `Withdraw` via CPI. +/// +/// ### Accounts: +/// +/// 0. `[signer]` owner +/// 1. `[]` authority +/// 2. `[writable]` pool_state +/// 3. `[writable]` owner_lp_token +/// 4. `[writable]` token0_account +/// 5. `[writable]` token1_account +/// 6. `[writable]` token0_vault +/// 7. `[writable]` token1_vault +/// 8. `[]` token_program +/// 9. `[]` token_program2022 +/// 10. `[]` vault0_mint +/// 11. `[]` vault1_mint +/// 12. `[writable]` lp_mint +/// 13. `[]` memo_program +#[derive(Clone, Debug)] +pub struct WithdrawCpiBuilder<'a, 'b> { + instruction: Box>, +} + +impl<'a, 'b> WithdrawCpiBuilder<'a, 'b> { + pub fn new(program: &'b solana_account_info::AccountInfo<'a>) -> Self { + let instruction = Box::new(WithdrawCpiBuilderInstruction { + __program: program, + owner: None, + authority: None, + pool_state: None, + owner_lp_token: None, + token0_account: None, + token1_account: None, + token0_vault: None, + token1_vault: None, + token_program: None, + token_program2022: None, + vault0_mint: None, + vault1_mint: None, + lp_mint: None, + memo_program: None, + lp_token_amount: None, + minimum_token0_amount: None, + minimum_token1_amount: None, + __remaining_accounts: Vec::new(), + }); + Self { instruction } + } + /// Pays to mint the position + #[inline(always)] + pub fn owner(&mut self, owner: &'b solana_account_info::AccountInfo<'a>) -> &mut Self { + self.instruction.owner = Some(owner); + self + } + #[inline(always)] + pub fn authority(&mut self, authority: &'b solana_account_info::AccountInfo<'a>) -> &mut Self { + self.instruction.authority = Some(authority); + self + } + /// Pool state account + #[inline(always)] + pub fn pool_state( + &mut self, + pool_state: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.pool_state = Some(pool_state); + self + } + /// Owner lp token account + #[inline(always)] + pub fn owner_lp_token( + &mut self, + owner_lp_token: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.owner_lp_token = Some(owner_lp_token); + self + } + /// The token account for receive token_0, + #[inline(always)] + pub fn token0_account( + &mut self, + token0_account: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.token0_account = Some(token0_account); + self + } + /// The token account for receive token_1 + #[inline(always)] + pub fn token1_account( + &mut self, + token1_account: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.token1_account = Some(token1_account); + self + } + /// The address that holds pool tokens for token_0 + #[inline(always)] + pub fn token0_vault( + &mut self, + token0_vault: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.token0_vault = Some(token0_vault); + self + } + /// The address that holds pool tokens for token_1 + #[inline(always)] + pub fn token1_vault( + &mut self, + token1_vault: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.token1_vault = Some(token1_vault); + self + } + /// token Program + #[inline(always)] + pub fn token_program( + &mut self, + token_program: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.token_program = Some(token_program); + self + } + /// Token program 2022 + #[inline(always)] + pub fn token_program2022( + &mut self, + token_program2022: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.token_program2022 = Some(token_program2022); + self + } + /// The mint of token_0 vault + #[inline(always)] + pub fn vault0_mint( + &mut self, + vault0_mint: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.vault0_mint = Some(vault0_mint); + self + } + /// The mint of token_1 vault + #[inline(always)] + pub fn vault1_mint( + &mut self, + vault1_mint: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.vault1_mint = Some(vault1_mint); + self + } + /// Pool lp token mint + #[inline(always)] + pub fn lp_mint(&mut self, lp_mint: &'b solana_account_info::AccountInfo<'a>) -> &mut Self { + self.instruction.lp_mint = Some(lp_mint); + self + } + /// memo program + #[inline(always)] + pub fn memo_program( + &mut self, + memo_program: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.memo_program = Some(memo_program); + self + } + #[inline(always)] + pub fn lp_token_amount(&mut self, lp_token_amount: u64) -> &mut Self { + self.instruction.lp_token_amount = Some(lp_token_amount); + self + } + #[inline(always)] + pub fn minimum_token0_amount(&mut self, minimum_token0_amount: u64) -> &mut Self { + self.instruction.minimum_token0_amount = Some(minimum_token0_amount); + self + } + #[inline(always)] + pub fn minimum_token1_amount(&mut self, minimum_token1_amount: u64) -> &mut Self { + self.instruction.minimum_token1_amount = Some(minimum_token1_amount); + self + } + /// Add an additional account to the instruction. + #[inline(always)] + pub fn add_remaining_account( + &mut self, + account: &'b solana_account_info::AccountInfo<'a>, + is_writable: bool, + is_signer: bool, + ) -> &mut Self { + self.instruction + .__remaining_accounts + .push((account, is_writable, is_signer)); + self + } + /// Add additional accounts to the instruction. + /// + /// Each account is represented by a tuple of the `AccountInfo`, a `bool` indicating whether the account is writable or not, + /// and a `bool` indicating whether the account is a signer or not. + #[inline(always)] + pub fn add_remaining_accounts( + &mut self, + accounts: &[(&'b solana_account_info::AccountInfo<'a>, bool, bool)], + ) -> &mut Self { + self.instruction + .__remaining_accounts + .extend_from_slice(accounts); + self + } + #[inline(always)] + pub fn invoke(&self) -> solana_program_error::ProgramResult { + self.invoke_signed(&[]) + } + #[allow(clippy::clone_on_copy)] + #[allow(clippy::vec_init_then_push)] + pub fn invoke_signed(&self, signers_seeds: &[&[&[u8]]]) -> solana_program_error::ProgramResult { + let args = WithdrawInstructionArgs { + lp_token_amount: self + .instruction + .lp_token_amount + .clone() + .expect("lp_token_amount is not set"), + minimum_token0_amount: self + .instruction + .minimum_token0_amount + .clone() + .expect("minimum_token0_amount is not set"), + minimum_token1_amount: self + .instruction + .minimum_token1_amount + .clone() + .expect("minimum_token1_amount is not set"), + }; + let instruction = WithdrawCpi { + __program: self.instruction.__program, + + owner: self.instruction.owner.expect("owner is not set"), + + authority: self.instruction.authority.expect("authority is not set"), + + pool_state: self.instruction.pool_state.expect("pool_state is not set"), + + owner_lp_token: self + .instruction + .owner_lp_token + .expect("owner_lp_token is not set"), + + token0_account: self + .instruction + .token0_account + .expect("token0_account is not set"), + + token1_account: self + .instruction + .token1_account + .expect("token1_account is not set"), + + token0_vault: self + .instruction + .token0_vault + .expect("token0_vault is not set"), + + token1_vault: self + .instruction + .token1_vault + .expect("token1_vault is not set"), + + token_program: self + .instruction + .token_program + .expect("token_program is not set"), + + token_program2022: self + .instruction + .token_program2022 + .expect("token_program2022 is not set"), + + vault0_mint: self + .instruction + .vault0_mint + .expect("vault0_mint is not set"), + + vault1_mint: self + .instruction + .vault1_mint + .expect("vault1_mint is not set"), + + lp_mint: self.instruction.lp_mint.expect("lp_mint is not set"), + + memo_program: self + .instruction + .memo_program + .expect("memo_program is not set"), + __args: args, + }; + instruction.invoke_signed_with_remaining_accounts( + signers_seeds, + &self.instruction.__remaining_accounts, + ) + } +} + +#[derive(Clone, Debug)] +struct WithdrawCpiBuilderInstruction<'a, 'b> { + __program: &'b solana_account_info::AccountInfo<'a>, + owner: Option<&'b solana_account_info::AccountInfo<'a>>, + authority: Option<&'b solana_account_info::AccountInfo<'a>>, + pool_state: Option<&'b solana_account_info::AccountInfo<'a>>, + owner_lp_token: Option<&'b solana_account_info::AccountInfo<'a>>, + token0_account: Option<&'b solana_account_info::AccountInfo<'a>>, + token1_account: Option<&'b solana_account_info::AccountInfo<'a>>, + token0_vault: Option<&'b solana_account_info::AccountInfo<'a>>, + token1_vault: Option<&'b solana_account_info::AccountInfo<'a>>, + token_program: Option<&'b solana_account_info::AccountInfo<'a>>, + token_program2022: Option<&'b solana_account_info::AccountInfo<'a>>, + vault0_mint: Option<&'b solana_account_info::AccountInfo<'a>>, + vault1_mint: Option<&'b solana_account_info::AccountInfo<'a>>, + lp_mint: Option<&'b solana_account_info::AccountInfo<'a>>, + memo_program: Option<&'b solana_account_info::AccountInfo<'a>>, + lp_token_amount: Option, + minimum_token0_amount: Option, + minimum_token1_amount: Option, + /// Additional instruction accounts `(AccountInfo, is_writable, is_signer)`. + __remaining_accounts: Vec<(&'b solana_account_info::AccountInfo<'a>, bool, bool)>, +} diff --git a/e2e/raydium-cpmm/src/generated/mod.rs b/e2e/raydium-cpmm/src/generated/mod.rs new file mode 100644 index 0000000..e0d740a --- /dev/null +++ b/e2e/raydium-cpmm/src/generated/mod.rs @@ -0,0 +1,15 @@ +//! This code was AUTOGENERATED using the codama library. +//! Please DO NOT EDIT THIS FILE, instead use visitors +//! to add features, then rerun codama to update it. +//! +//! +//! + +pub mod accounts; +pub mod errors; +pub mod instructions; +pub mod programs; +pub mod shared; +pub mod types; + +pub(crate) use programs::*; diff --git a/e2e/raydium-cpmm/src/generated/programs.rs b/e2e/raydium-cpmm/src/generated/programs.rs new file mode 100644 index 0000000..69d4d08 --- /dev/null +++ b/e2e/raydium-cpmm/src/generated/programs.rs @@ -0,0 +1,11 @@ +//! This code was AUTOGENERATED using the codama library. +//! Please DO NOT EDIT THIS FILE, instead use visitors +//! to add features, then rerun codama to update it. +//! +//! +//! + +use solana_address::{address, Address}; + +/// `raydium_cp_swap` program ID. +pub const RAYDIUM_CP_SWAP_ID: Address = address!("CPMMoo8L3F4NbTegBCKVNunggL7H1ZpdTHKxQB5qKP1C"); diff --git a/e2e/raydium-cpmm/src/generated/shared.rs b/e2e/raydium-cpmm/src/generated/shared.rs new file mode 100644 index 0000000..42eae7f --- /dev/null +++ b/e2e/raydium-cpmm/src/generated/shared.rs @@ -0,0 +1,21 @@ +//! This code was AUTOGENERATED using the codama library. +//! Please DO NOT EDIT THIS FILE, instead use visitors +//! to add features, then rerun codama to update it. +//! +//! +//! + +#[cfg(feature = "fetch")] +#[derive(Debug, Clone)] +pub struct DecodedAccount { + pub address: solana_address::Address, + pub account: solana_account::Account, + pub data: T, +} + +#[cfg(feature = "fetch")] +#[derive(Debug, Clone)] +pub enum MaybeAccount { + Exists(DecodedAccount), + NotFound(solana_address::Address), +} diff --git a/e2e/raydium-cpmm/src/generated/types/mod.rs b/e2e/raydium-cpmm/src/generated/types/mod.rs new file mode 100644 index 0000000..86bb676 --- /dev/null +++ b/e2e/raydium-cpmm/src/generated/types/mod.rs @@ -0,0 +1,10 @@ +//! This code was AUTOGENERATED using the codama library. +//! Please DO NOT EDIT THIS FILE, instead use visitors +//! to add features, then rerun codama to update it. +//! +//! +//! + +pub(crate) mod r#observation; + +pub use self::r#observation::*; diff --git a/e2e/raydium-cpmm/src/generated/types/observation.rs b/e2e/raydium-cpmm/src/generated/types/observation.rs new file mode 100644 index 0000000..ce27025 --- /dev/null +++ b/e2e/raydium-cpmm/src/generated/types/observation.rs @@ -0,0 +1,20 @@ +//! This code was AUTOGENERATED using the codama library. +//! Please DO NOT EDIT THIS FILE, instead use visitors +//! to add features, then rerun codama to update it. +//! +//! +//! + +use borsh::BorshDeserialize; +use borsh::BorshSerialize; + +/// The element of observations in ObservationState +#[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] +pub struct Observation { + /// The block timestamp of the observation + pub block_timestamp: u64, + /// the cumulative of token0 price during the duration time, Q32.32, the remaining 64 bit for overflow + pub cumulative_token0_price_x32: u128, + /// the cumulative of token1 price during the duration time, Q32.32, the remaining 64 bit for overflow + pub cumulative_token1_price_x32: u128, +} diff --git a/e2e/raydium-cpmm/src/lib.rs b/e2e/raydium-cpmm/src/lib.rs new file mode 100644 index 0000000..39f6b55 --- /dev/null +++ b/e2e/raydium-cpmm/src/lib.rs @@ -0,0 +1,4 @@ +mod generated; + +pub use generated::programs::RAYDIUM_CP_SWAP_ID as ID; +pub use generated::*; diff --git a/e2e/test.sh b/e2e/test.sh index 498b7a4..74582ab 100755 --- a/e2e/test.sh +++ b/e2e/test.sh @@ -19,4 +19,5 @@ test_project dummy test_project system test_project memo # test_project meteora # TODO: uncomment after some internal fixes -test_anchor_project anchor \ No newline at end of file +test_anchor_project anchor +test_anchor_project raydium-cpmm \ No newline at end of file From 1060a7dd4bfeb7259dfe79200fd943cb3b130d47 Mon Sep 17 00:00:00 2001 From: ioxde <228087182+ioxde@users.noreply.github.com> Date: Fri, 17 Apr 2026 10:46:00 -0700 Subject: [PATCH 03/24] Add Raydium Launchpad e2e fixture --- Cargo.lock | 18 + e2e/raydium-launchpad/Cargo.toml | 24 + e2e/raydium-launchpad/idl.json | 4304 +++++++++++++++++ .../src/generated/accounts/global_config.rs | 166 + .../src/generated/accounts/mod.rs | 16 + .../src/generated/accounts/platform_config.rs | 152 + .../src/generated/accounts/pool_state.rs | 194 + .../src/generated/accounts/vesting_record.rs | 142 + .../src/generated/errors/mod.rs | 10 + .../src/generated/errors/raydium_launchpad.rs | 67 + .../generated/instructions/buy_exact_in.rs | 980 ++++ .../generated/instructions/buy_exact_out.rs | 980 ++++ .../instructions/claim_platform_fee.rs | 672 +++ .../instructions/claim_vested_token.rs | 671 +++ .../src/generated/instructions/collect_fee.rs | 557 +++ .../instructions/collect_migrate_fee.rs | 561 +++ .../generated/instructions/create_config.rs | 712 +++ .../instructions/create_platform_config.rs | 579 +++ .../instructions/create_vesting_account.rs | 489 ++ .../src/generated/instructions/initialize.rs | 1104 +++++ .../generated/instructions/migrate_to_amm.rs | 1631 +++++++ .../instructions/migrate_to_cpswap.rs | 1468 ++++++ .../src/generated/instructions/mod.rs | 40 + .../generated/instructions/sell_exact_in.rs | 980 ++++ .../generated/instructions/sell_exact_out.rs | 983 ++++ .../generated/instructions/update_config.rs | 376 ++ .../instructions/update_platform_config.rs | 369 ++ e2e/raydium-launchpad/src/generated/mod.rs | 15 + .../src/generated/programs.rs | 11 + e2e/raydium-launchpad/src/generated/shared.rs | 21 + .../src/generated/types/constant_curve.rs | 17 + .../src/generated/types/curve_params.rs | 19 + .../src/generated/types/fixed_curve.rs | 16 + .../src/generated/types/linear_curve.rs | 16 + .../src/generated/types/migrate_nft_info.rs | 23 + .../src/generated/types/mint_params.rs | 23 + .../src/generated/types/mod.rs | 30 + .../generated/types/platform_config_param.rs | 22 + .../src/generated/types/pool_status.rs | 32 + .../src/generated/types/trade_direction.rs | 29 + .../src/generated/types/vesting_params.rs | 16 + .../src/generated/types/vesting_schedule.rs | 19 + e2e/raydium-launchpad/src/lib.rs | 4 + e2e/test.sh | 3 +- src/utils/cargoToml.ts | 3 +- 45 files changed, 18562 insertions(+), 2 deletions(-) create mode 100644 e2e/raydium-launchpad/Cargo.toml create mode 100644 e2e/raydium-launchpad/idl.json create mode 100644 e2e/raydium-launchpad/src/generated/accounts/global_config.rs create mode 100644 e2e/raydium-launchpad/src/generated/accounts/mod.rs create mode 100644 e2e/raydium-launchpad/src/generated/accounts/platform_config.rs create mode 100644 e2e/raydium-launchpad/src/generated/accounts/pool_state.rs create mode 100644 e2e/raydium-launchpad/src/generated/accounts/vesting_record.rs create mode 100644 e2e/raydium-launchpad/src/generated/errors/mod.rs create mode 100644 e2e/raydium-launchpad/src/generated/errors/raydium_launchpad.rs create mode 100644 e2e/raydium-launchpad/src/generated/instructions/buy_exact_in.rs create mode 100644 e2e/raydium-launchpad/src/generated/instructions/buy_exact_out.rs create mode 100644 e2e/raydium-launchpad/src/generated/instructions/claim_platform_fee.rs create mode 100644 e2e/raydium-launchpad/src/generated/instructions/claim_vested_token.rs create mode 100644 e2e/raydium-launchpad/src/generated/instructions/collect_fee.rs create mode 100644 e2e/raydium-launchpad/src/generated/instructions/collect_migrate_fee.rs create mode 100644 e2e/raydium-launchpad/src/generated/instructions/create_config.rs create mode 100644 e2e/raydium-launchpad/src/generated/instructions/create_platform_config.rs create mode 100644 e2e/raydium-launchpad/src/generated/instructions/create_vesting_account.rs create mode 100644 e2e/raydium-launchpad/src/generated/instructions/initialize.rs create mode 100644 e2e/raydium-launchpad/src/generated/instructions/migrate_to_amm.rs create mode 100644 e2e/raydium-launchpad/src/generated/instructions/migrate_to_cpswap.rs create mode 100644 e2e/raydium-launchpad/src/generated/instructions/mod.rs create mode 100644 e2e/raydium-launchpad/src/generated/instructions/sell_exact_in.rs create mode 100644 e2e/raydium-launchpad/src/generated/instructions/sell_exact_out.rs create mode 100644 e2e/raydium-launchpad/src/generated/instructions/update_config.rs create mode 100644 e2e/raydium-launchpad/src/generated/instructions/update_platform_config.rs create mode 100644 e2e/raydium-launchpad/src/generated/mod.rs create mode 100644 e2e/raydium-launchpad/src/generated/programs.rs create mode 100644 e2e/raydium-launchpad/src/generated/shared.rs create mode 100644 e2e/raydium-launchpad/src/generated/types/constant_curve.rs create mode 100644 e2e/raydium-launchpad/src/generated/types/curve_params.rs create mode 100644 e2e/raydium-launchpad/src/generated/types/fixed_curve.rs create mode 100644 e2e/raydium-launchpad/src/generated/types/linear_curve.rs create mode 100644 e2e/raydium-launchpad/src/generated/types/migrate_nft_info.rs create mode 100644 e2e/raydium-launchpad/src/generated/types/mint_params.rs create mode 100644 e2e/raydium-launchpad/src/generated/types/mod.rs create mode 100644 e2e/raydium-launchpad/src/generated/types/platform_config_param.rs create mode 100644 e2e/raydium-launchpad/src/generated/types/pool_status.rs create mode 100644 e2e/raydium-launchpad/src/generated/types/trade_direction.rs create mode 100644 e2e/raydium-launchpad/src/generated/types/vesting_params.rs create mode 100644 e2e/raydium-launchpad/src/generated/types/vesting_schedule.rs create mode 100644 e2e/raydium-launchpad/src/lib.rs diff --git a/Cargo.lock b/Cargo.lock index ff5c422..f600abf 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -771,6 +771,24 @@ dependencies = [ "thiserror 1.0.69", ] +[[package]] +name = "codama-renderers-rust-e2e-raydium-launchpad" +version = "0.0.0" +dependencies = [ + "anchor-lang", + "borsh 1.5.7", + "num-derive", + "num-traits", + "solana-account 3.0.0", + "solana-account-info 3.1.0", + "solana-address 2.2.0", + "solana-client", + "solana-cpi 3.1.0", + "solana-instruction 3.2.0", + "solana-program-error 3.0.0", + "thiserror 1.0.69", +] + [[package]] name = "codama-renderers-rust-e2e-system" version = "0.0.0" diff --git a/e2e/raydium-launchpad/Cargo.toml b/e2e/raydium-launchpad/Cargo.toml new file mode 100644 index 0000000..de19540 --- /dev/null +++ b/e2e/raydium-launchpad/Cargo.toml @@ -0,0 +1,24 @@ +[package] +name = "codama-renderers-rust-e2e-raydium-launchpad" +version = "0.0.0" +edition = "2021" + +[features] +anchor = ["dep:anchor-lang"] +anchor-idl-build = ["anchor", "anchor-lang?/idl-build"] +test-sbf = [] +fetch = ["dep:solana-client"] + +[dependencies] +anchor-lang = { workspace = true, optional = true } +borsh = { workspace = true } +num-derive = { workspace = true } +num-traits = { workspace = true } +solana-account = { workspace = true } +solana-account-info = { workspace = true } +solana-address = { workspace = true, features = ["borsh", "copy", "curve25519", "decode"] } +solana-client = { workspace = true, optional = true } +solana-cpi = { workspace = true } +solana-instruction = { workspace = true } +solana-program-error = { workspace = true } +thiserror = { workspace = true } diff --git a/e2e/raydium-launchpad/idl.json b/e2e/raydium-launchpad/idl.json new file mode 100644 index 0000000..a1737e6 --- /dev/null +++ b/e2e/raydium-launchpad/idl.json @@ -0,0 +1,4304 @@ +{ + "address": "LanMV9sAd7wArD4vJFi2qDdfnVhFxYSUg6eADduJ3uj", + "metadata": { + "name": "raydium_launchpad", + "version": "0.1.0", + "spec": "0.1.0", + "description": "Created with Anchor" + }, + "instructions": [ + { + "name": "buy_exact_in", + "docs": [ + "Use the given amount of quote tokens to purchase base tokens.", + "# Arguments", + "", + "* `ctx` - The context of accounts", + "* `amount_in` - Amount of quote token to purchase", + "* `minimum_amount_out` - Minimum amount of base token to receive (slippage protection)", + "* `share_fee_rate` - Fee rate for the share", + "" + ], + "discriminator": [ + 250, + 234, + 13, + 123, + 213, + 156, + 19, + 236 + ], + "accounts": [ + { + "name": "payer", + "docs": [ + "The user performing the swap operation", + "Must sign the transaction and pay for fees" + ], + "signer": true + }, + { + "name": "authority", + "docs": [ + "PDA that acts as the authority for pool vault operations", + "Generated using AUTH_SEED" + ], + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 118, + 97, + 117, + 108, + 116, + 95, + 97, + 117, + 116, + 104, + 95, + 115, + 101, + 101, + 100 + ] + } + ] + } + }, + { + "name": "global_config", + "docs": [ + "Global configuration account containing protocol-wide settings", + "Used to read protocol fee rates and curve type" + ] + }, + { + "name": "platform_config", + "docs": [ + "Platform configuration account containing platform-wide settings", + "Used to read platform fee rate" + ] + }, + { + "name": "pool_state", + "docs": [ + "The pool state account where the swap will be performed", + "Contains current pool parameters and balances" + ], + "writable": true + }, + { + "name": "user_base_token", + "docs": [ + "The user's token account for base tokens (tokens being bought)", + "Will receive the output tokens after the swap" + ], + "writable": true + }, + { + "name": "user_quote_token", + "docs": [ + "The user's token account for quote tokens (tokens being sold)", + "Will be debited for the input amount" + ], + "writable": true + }, + { + "name": "base_vault", + "docs": [ + "The pool's vault for base tokens", + "Will be debited to send tokens to the user" + ], + "writable": true + }, + { + "name": "quote_vault", + "docs": [ + "The pool's vault for quote tokens", + "Will receive the input tokens from the user" + ], + "writable": true + }, + { + "name": "base_token_mint", + "docs": [ + "The mint of the base token", + "Used for transfer fee calculations if applicable" + ] + }, + { + "name": "quote_token_mint", + "docs": [ + "The mint of the quote token" + ] + }, + { + "name": "base_token_program", + "docs": [ + "SPL Token program for base token transfers" + ] + }, + { + "name": "quote_token_program", + "docs": [ + "SPL Token program for quote token transfers" + ], + "address": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA" + }, + { + "name": "event_authority", + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 95, + 95, + 101, + 118, + 101, + 110, + 116, + 95, + 97, + 117, + 116, + 104, + 111, + 114, + 105, + 116, + 121 + ] + } + ] + } + }, + { + "name": "program" + } + ], + "args": [ + { + "name": "amount_in", + "type": "u64" + }, + { + "name": "minimum_amount_out", + "type": "u64" + }, + { + "name": "share_fee_rate", + "type": "u64" + } + ] + }, + { + "name": "buy_exact_out", + "docs": [ + "Use quote tokens to purchase the given amount of base tokens.", + "# Arguments", + "", + "* `ctx` - The context of accounts", + "* `amount_out` - Amount of base token to receive", + "* `maximum_amount_in` - Maximum amount of quote token to purchase (slippage protection)", + "* `share_fee_rate` - Fee rate for the share" + ], + "discriminator": [ + 24, + 211, + 116, + 40, + 105, + 3, + 153, + 56 + ], + "accounts": [ + { + "name": "payer", + "docs": [ + "The user performing the swap operation", + "Must sign the transaction and pay for fees" + ], + "signer": true + }, + { + "name": "authority", + "docs": [ + "PDA that acts as the authority for pool vault operations", + "Generated using AUTH_SEED" + ], + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 118, + 97, + 117, + 108, + 116, + 95, + 97, + 117, + 116, + 104, + 95, + 115, + 101, + 101, + 100 + ] + } + ] + } + }, + { + "name": "global_config", + "docs": [ + "Global configuration account containing protocol-wide settings", + "Used to read protocol fee rates and curve type" + ] + }, + { + "name": "platform_config", + "docs": [ + "Platform configuration account containing platform-wide settings", + "Used to read platform fee rate" + ] + }, + { + "name": "pool_state", + "docs": [ + "The pool state account where the swap will be performed", + "Contains current pool parameters and balances" + ], + "writable": true + }, + { + "name": "user_base_token", + "docs": [ + "The user's token account for base tokens (tokens being bought)", + "Will receive the output tokens after the swap" + ], + "writable": true + }, + { + "name": "user_quote_token", + "docs": [ + "The user's token account for quote tokens (tokens being sold)", + "Will be debited for the input amount" + ], + "writable": true + }, + { + "name": "base_vault", + "docs": [ + "The pool's vault for base tokens", + "Will be debited to send tokens to the user" + ], + "writable": true + }, + { + "name": "quote_vault", + "docs": [ + "The pool's vault for quote tokens", + "Will receive the input tokens from the user" + ], + "writable": true + }, + { + "name": "base_token_mint", + "docs": [ + "The mint of the base token", + "Used for transfer fee calculations if applicable" + ] + }, + { + "name": "quote_token_mint", + "docs": [ + "The mint of the quote token" + ] + }, + { + "name": "base_token_program", + "docs": [ + "SPL Token program for base token transfers" + ] + }, + { + "name": "quote_token_program", + "docs": [ + "SPL Token program for quote token transfers" + ], + "address": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA" + }, + { + "name": "event_authority", + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 95, + 95, + 101, + 118, + 101, + 110, + 116, + 95, + 97, + 117, + 116, + 104, + 111, + 114, + 105, + 116, + 121 + ] + } + ] + } + }, + { + "name": "program" + } + ], + "args": [ + { + "name": "amount_out", + "type": "u64" + }, + { + "name": "maximum_amount_in", + "type": "u64" + }, + { + "name": "share_fee_rate", + "type": "u64" + } + ] + }, + { + "name": "claim_platform_fee", + "docs": [ + "Claim platform fee", + "# Arguments", + "", + "* `ctx` - The context of accounts", + "" + ], + "discriminator": [ + 156, + 39, + 208, + 135, + 76, + 237, + 61, + 72 + ], + "accounts": [ + { + "name": "platform_fee_wallet", + "docs": [ + "Only the wallet stored in platform_config can collect platform fees" + ], + "writable": true, + "signer": true + }, + { + "name": "authority", + "docs": [ + "PDA that acts as the authority for pool vault and mint operations", + "Generated using AUTH_SEED" + ], + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 118, + 97, + 117, + 108, + 116, + 95, + 97, + 117, + 116, + 104, + 95, + 115, + 101, + 101, + 100 + ] + } + ] + } + }, + { + "name": "pool_state", + "docs": [ + "Account that stores the pool's state and parameters", + "PDA generated using POOL_SEED and both token mints" + ], + "writable": true + }, + { + "name": "platform_config", + "docs": [ + "The platform config account" + ] + }, + { + "name": "quote_vault", + "writable": true + }, + { + "name": "recipient_token_account", + "docs": [ + "The address that receives the collected quote token fees" + ], + "writable": true, + "pda": { + "seeds": [ + { + "kind": "account", + "path": "platform_fee_wallet" + }, + { + "kind": "const", + "value": [ + 6, + 221, + 246, + 225, + 215, + 101, + 161, + 147, + 217, + 203, + 225, + 70, + 206, + 235, + 121, + 172, + 28, + 180, + 133, + 237, + 95, + 91, + 55, + 145, + 58, + 140, + 245, + 133, + 126, + 255, + 0, + 169 + ] + }, + { + "kind": "account", + "path": "quote_mint" + } + ], + "program": { + "kind": "const", + "value": [ + 140, + 151, + 37, + 143, + 78, + 36, + 137, + 241, + 187, + 61, + 16, + 41, + 20, + 142, + 13, + 131, + 11, + 90, + 19, + 153, + 218, + 255, + 16, + 132, + 4, + 142, + 123, + 216, + 219, + 233, + 248, + 89 + ] + } + } + }, + { + "name": "quote_mint", + "docs": [ + "The mint of quote token vault" + ] + }, + { + "name": "token_program", + "docs": [ + "SPL program for input token transfers" + ], + "address": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA" + }, + { + "name": "system_program", + "docs": [ + "Required for account creation" + ], + "address": "11111111111111111111111111111111" + }, + { + "name": "associated_token_program", + "docs": [ + "Required for associated token program" + ], + "address": "ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL" + } + ], + "args": [] + }, + { + "name": "claim_vested_token", + "docs": [ + "Claim vested token", + "# Arguments" + ], + "discriminator": [ + 49, + 33, + 104, + 30, + 189, + 157, + 79, + 35 + ], + "accounts": [ + { + "name": "beneficiary", + "docs": [ + "The beneficiary of the vesting account" + ], + "writable": true, + "signer": true + }, + { + "name": "authority", + "docs": [ + "PDA that acts as the authority for pool vault and mint operations", + "Generated using AUTH_SEED" + ], + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 118, + 97, + 117, + 108, + 116, + 95, + 97, + 117, + 116, + 104, + 95, + 115, + 101, + 101, + 100 + ] + } + ] + } + }, + { + "name": "pool_state", + "docs": [ + "Account that stores the pool's state and parameters", + "PDA generated using POOL_SEED and both token mints" + ], + "writable": true + }, + { + "name": "vesting_record", + "docs": [ + "The vesting record account" + ], + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 112, + 111, + 111, + 108, + 95, + 118, + 101, + 115, + 116, + 105, + 110, + 103 + ] + }, + { + "kind": "account", + "path": "pool_state" + }, + { + "kind": "account", + "path": "beneficiary" + } + ] + } + }, + { + "name": "base_vault", + "docs": [ + "The pool's vault for base tokens", + "Will be debited to send tokens to the user" + ], + "writable": true + }, + { + "name": "user_base_token", + "writable": true, + "signer": true + }, + { + "name": "base_token_mint", + "docs": [ + "The mint for the base token (token being sold)", + "Created in this instruction with specified decimals" + ] + }, + { + "name": "base_token_program", + "docs": [ + "SPL Token program for the base token", + "Must be the standard Token program" + ], + "address": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA" + }, + { + "name": "system_program", + "docs": [ + "Required for account creation" + ], + "address": "11111111111111111111111111111111" + }, + { + "name": "associated_token_program", + "docs": [ + "Required for associated token program" + ], + "address": "ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL" + } + ], + "args": [] + }, + { + "name": "collect_fee", + "docs": [ + "Collects accumulated fees from the pool", + "# Arguments", + "", + "* `ctx` - The context of accounts", + "" + ], + "discriminator": [ + 60, + 173, + 247, + 103, + 4, + 93, + 130, + 48 + ], + "accounts": [ + { + "name": "owner", + "docs": [ + "Only protocol_fee_owner saved in global_config can collect protocol fee now" + ], + "signer": true + }, + { + "name": "authority", + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 118, + 97, + 117, + 108, + 116, + 95, + 97, + 117, + 116, + 104, + 95, + 115, + 101, + 101, + 100 + ] + } + ] + } + }, + { + "name": "pool_state", + "docs": [ + "Pool state stores accumulated protocol fee amount" + ], + "writable": true + }, + { + "name": "global_config", + "docs": [ + "Global config account stores owner" + ] + }, + { + "name": "quote_vault", + "docs": [ + "The address that holds pool tokens for quote token" + ], + "writable": true + }, + { + "name": "quote_mint", + "docs": [ + "The mint of quote token vault" + ] + }, + { + "name": "recipient_token_account", + "docs": [ + "The address that receives the collected quote token fees" + ], + "writable": true + }, + { + "name": "token_program", + "docs": [ + "SPL program for input token transfers" + ], + "address": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA" + } + ], + "args": [] + }, + { + "name": "collect_migrate_fee", + "docs": [ + "Collects migrate fees from the pool", + "# Arguments", + "", + "* `ctx` - The context of accounts", + "" + ], + "discriminator": [ + 255, + 186, + 150, + 223, + 235, + 118, + 201, + 186 + ], + "accounts": [ + { + "name": "owner", + "docs": [ + "Only migrate_fee_owner saved in global_config can collect migrate fee now" + ], + "signer": true + }, + { + "name": "authority", + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 118, + 97, + 117, + 108, + 116, + 95, + 97, + 117, + 116, + 104, + 95, + 115, + 101, + 101, + 100 + ] + } + ] + } + }, + { + "name": "pool_state", + "docs": [ + "Pool state stores accumulated protocol fee amount" + ], + "writable": true + }, + { + "name": "global_config", + "docs": [ + "Global config account stores owner" + ] + }, + { + "name": "quote_vault", + "docs": [ + "The address that holds pool tokens for quote token" + ], + "writable": true + }, + { + "name": "quote_mint", + "docs": [ + "The mint of quote token vault" + ] + }, + { + "name": "recipient_token_account", + "docs": [ + "The address that receives the collected quote token fees" + ], + "writable": true + }, + { + "name": "token_program", + "docs": [ + "SPL program for input token transfers" + ], + "address": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA" + } + ], + "args": [] + }, + { + "name": "create_config", + "docs": [ + "Creates a new configuration", + "# Arguments", + "", + "* `ctx` - The accounts needed by instruction", + "* `curve_type` - The type of bonding curve (0: ConstantProduct)", + "* `index` - The index of config, there may be multiple config with the same curve type.", + "* `trade_fee_rate` - Trade fee rate, must be less than RATE_DENOMINATOR_VALUE", + "" + ], + "discriminator": [ + 201, + 207, + 243, + 114, + 75, + 111, + 47, + 189 + ], + "accounts": [ + { + "name": "owner", + "docs": [ + "The protocol owner/admin account", + "Must match the predefined admin address", + "Has authority to create and modify protocol configurations" + ], + "writable": true, + "signer": true, + "address": "GThUX1Atko4tqhN2NaiTazWSeFWMuiUvfFnyJyUghFMJ" + }, + { + "name": "global_config", + "docs": [ + "Global configuration account that stores protocol-wide settings", + "PDA generated using GLOBAL_CONFIG_SEED, quote token mint, and curve type", + "Stores fee rates and protocol parameters" + ], + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 103, + 108, + 111, + 98, + 97, + 108, + 95, + 99, + 111, + 110, + 102, + 105, + 103 + ] + }, + { + "kind": "account", + "path": "quote_token_mint" + }, + { + "kind": "arg", + "path": "curve_type" + }, + { + "kind": "arg", + "path": "index" + } + ] + } + }, + { + "name": "quote_token_mint", + "docs": [ + "The mint address of the quote token (token used for buying)", + "This will be the standard token used for all pools with this config" + ] + }, + { + "name": "protocol_fee_owner", + "docs": [ + "Account that will receive protocol fees" + ] + }, + { + "name": "migrate_fee_owner", + "docs": [ + "Account that will receive migrate fees" + ] + }, + { + "name": "migrate_to_amm_wallet", + "docs": [ + "The control wallet address for migrating to amm" + ] + }, + { + "name": "migrate_to_cpswap_wallet", + "docs": [ + "The control wallet address for migrating to cpswap" + ] + }, + { + "name": "system_program", + "docs": [ + "Required for account creation" + ], + "address": "11111111111111111111111111111111" + } + ], + "args": [ + { + "name": "curve_type", + "type": "u8" + }, + { + "name": "index", + "type": "u16" + }, + { + "name": "migrate_fee", + "type": "u64" + }, + { + "name": "trade_fee_rate", + "type": "u64" + } + ] + }, + { + "name": "create_platform_config", + "docs": [ + "Create platform config account", + "# Arguments", + "", + "* `ctx` - The context of accounts", + "# Fields", + "* `fee_rate` - Fee rate of the platform", + "* `name` - Name of the platform", + "* `web` - Website of the platform", + "* `img` - Image link of the platform", + "" + ], + "discriminator": [ + 176, + 90, + 196, + 175, + 253, + 113, + 220, + 20 + ], + "accounts": [ + { + "name": "platform_admin", + "docs": [ + "The account paying for the initialization costs" + ], + "writable": true, + "signer": true + }, + { + "name": "platform_fee_wallet" + }, + { + "name": "platform_nft_wallet" + }, + { + "name": "platform_config", + "docs": [ + "The platform config account" + ], + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 112, + 108, + 97, + 116, + 102, + 111, + 114, + 109, + 95, + 99, + 111, + 110, + 102, + 105, + 103 + ] + }, + { + "kind": "account", + "path": "platform_admin" + } + ] + } + }, + { + "name": "system_program", + "docs": [ + "Required for account creation" + ], + "address": "11111111111111111111111111111111" + } + ], + "args": [ + { + "name": "platform_params", + "type": { + "defined": { + "name": "PlatformParams" + } + } + } + ] + }, + { + "name": "create_vesting_account", + "docs": [ + "Create vesting account", + "# Arguments", + "", + "* `ctx` - The context of accounts", + "* `share` - The share amount of base token to be vested", + "" + ], + "discriminator": [ + 129, + 178, + 2, + 13, + 217, + 172, + 230, + 218 + ], + "accounts": [ + { + "name": "creator", + "docs": [ + "The account paying for the initialization costs", + "This can be any account with sufficient SOL to cover the transaction" + ], + "writable": true, + "signer": true + }, + { + "name": "beneficiary", + "writable": true + }, + { + "name": "pool_state", + "docs": [ + "The pool state account" + ], + "writable": true + }, + { + "name": "vesting_record", + "docs": [ + "The vesting record account" + ], + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 112, + 111, + 111, + 108, + 95, + 118, + 101, + 115, + 116, + 105, + 110, + 103 + ] + }, + { + "kind": "account", + "path": "pool_state" + }, + { + "kind": "account", + "path": "beneficiary" + } + ] + } + }, + { + "name": "system_program", + "docs": [ + "Required for account creation" + ], + "address": "11111111111111111111111111111111" + } + ], + "args": [ + { + "name": "share_amount", + "type": "u64" + } + ] + }, + { + "name": "initialize", + "docs": [ + "Initializes a new trading pool", + "# Arguments", + "", + "* `ctx` - The context of accounts containing pool and token information", + "" + ], + "discriminator": [ + 175, + 175, + 109, + 31, + 13, + 152, + 155, + 237 + ], + "accounts": [ + { + "name": "payer", + "docs": [ + "The account paying for the initialization costs", + "This can be any account with sufficient SOL to cover the transaction" + ], + "writable": true, + "signer": true + }, + { + "name": "creator" + }, + { + "name": "global_config", + "docs": [ + "Global configuration account containing protocol-wide settings", + "Includes settings like quote token mint and fee parameters" + ] + }, + { + "name": "platform_config", + "docs": [ + "Platform configuration account containing platform info", + "Includes settings like the fee_rate, name, web, img of the platform" + ] + }, + { + "name": "authority", + "docs": [ + "PDA that acts as the authority for pool vault and mint operations", + "Generated using AUTH_SEED" + ], + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 118, + 97, + 117, + 108, + 116, + 95, + 97, + 117, + 116, + 104, + 95, + 115, + 101, + 101, + 100 + ] + } + ] + } + }, + { + "name": "pool_state", + "docs": [ + "Account that stores the pool's state and parameters", + "PDA generated using POOL_SEED and both token mints" + ], + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 112, + 111, + 111, + 108 + ] + }, + { + "kind": "account", + "path": "base_mint" + }, + { + "kind": "account", + "path": "quote_mint" + } + ] + } + }, + { + "name": "base_mint", + "docs": [ + "The mint for the base token (token being sold)", + "Created in this instruction with specified decimals" + ], + "writable": true, + "signer": true + }, + { + "name": "quote_mint", + "docs": [ + "The mint for the quote token (token used to buy)", + "Must match the quote_mint specified in global config" + ] + }, + { + "name": "base_vault", + "docs": [ + "Token account that holds the pool's base tokens", + "PDA generated using POOL_VAULT_SEED" + ], + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 112, + 111, + 111, + 108, + 95, + 118, + 97, + 117, + 108, + 116 + ] + }, + { + "kind": "account", + "path": "pool_state" + }, + { + "kind": "account", + "path": "base_mint" + } + ] + } + }, + { + "name": "quote_vault", + "docs": [ + "Token account that holds the pool's quote tokens", + "PDA generated using POOL_VAULT_SEED" + ], + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 112, + 111, + 111, + 108, + 95, + 118, + 97, + 117, + 108, + 116 + ] + }, + { + "kind": "account", + "path": "pool_state" + }, + { + "kind": "account", + "path": "quote_mint" + } + ] + } + }, + { + "name": "metadata_account", + "docs": [ + "Account to store the base token's metadata", + "Created using Metaplex metadata program" + ], + "writable": true + }, + { + "name": "base_token_program", + "docs": [ + "SPL Token program for the base token", + "Must be the standard Token program" + ], + "address": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA" + }, + { + "name": "quote_token_program", + "docs": [ + "SPL Token program for the quote token" + ], + "address": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA" + }, + { + "name": "metadata_program", + "docs": [ + "Metaplex Token Metadata program", + "Used to create metadata for the base token" + ], + "address": "metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s" + }, + { + "name": "system_program", + "docs": [ + "Required for account creation" + ], + "address": "11111111111111111111111111111111" + }, + { + "name": "rent_program", + "docs": [ + "Required for rent exempt calculations" + ], + "address": "SysvarRent111111111111111111111111111111111" + }, + { + "name": "event_authority", + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 95, + 95, + 101, + 118, + 101, + 110, + 116, + 95, + 97, + 117, + 116, + 104, + 111, + 114, + 105, + 116, + 121 + ] + } + ] + } + }, + { + "name": "program" + } + ], + "args": [ + { + "name": "base_mint_param", + "type": { + "defined": { + "name": "MintParams" + } + } + }, + { + "name": "curve_param", + "type": { + "defined": { + "name": "CurveParams" + } + } + }, + { + "name": "vesting_param", + "type": { + "defined": { + "name": "VestingParams" + } + } + } + ] + }, + { + "name": "migrate_to_amm", + "docs": [ + "# Arguments", + "", + "* `ctx` - The context of accounts", + "" + ], + "discriminator": [ + 207, + 82, + 192, + 145, + 254, + 207, + 145, + 223 + ], + "accounts": [ + { + "name": "payer", + "docs": [ + "Only migrate_to_amm_wallet can migrate to cpswap pool", + "This signer must match the migrate_to_amm_wallet saved in global_config" + ], + "writable": true, + "signer": true + }, + { + "name": "base_mint", + "docs": [ + "The mint for the base token (token being sold)" + ] + }, + { + "name": "quote_mint", + "docs": [ + "The mint for the quote token (token used to buy)" + ] + }, + { + "name": "openbook_program", + "address": "srmqPvymJeFKQ4zGQed1GFppgkRHL9kaELCbyksJtPX" + }, + { + "name": "market", + "docs": [ + "Account created and asigned to openbook_program but not been initialized" + ], + "writable": true + }, + { + "name": "request_queue", + "docs": [ + "Account created and asigned to openbook_program but not been initialized" + ], + "writable": true + }, + { + "name": "event_queue", + "docs": [ + "Account created and asigned to openbook_program but not been initialized" + ], + "writable": true + }, + { + "name": "bids", + "docs": [ + "Account created and asigned to openbook_program but not been initialized" + ], + "writable": true + }, + { + "name": "asks", + "docs": [ + "Account created and asigned to openbook_program but not been initialized" + ], + "writable": true + }, + { + "name": "market_vault_signer" + }, + { + "name": "market_base_vault", + "docs": [ + "Token account that holds the market's base tokens" + ], + "writable": true + }, + { + "name": "market_quote_vault", + "docs": [ + "Token account that holds the market's quote tokens" + ], + "writable": true + }, + { + "name": "amm_program", + "address": "675kPX9MHTjS2zt1qfr1NYHuzeLXfQM9H24wFSUt1Mp8" + }, + { + "name": "amm_pool", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "account", + "path": "amm_program" + }, + { + "kind": "account", + "path": "market" + }, + { + "kind": "const", + "value": [ + 97, + 109, + 109, + 95, + 97, + 115, + 115, + 111, + 99, + 105, + 97, + 116, + 101, + 100, + 95, + 115, + 101, + 101, + 100 + ] + } + ], + "program": { + "kind": "account", + "path": "amm_program" + } + } + }, + { + "name": "amm_authority", + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 97, + 109, + 109, + 32, + 97, + 117, + 116, + 104, + 111, + 114, + 105, + 116, + 121 + ] + } + ], + "program": { + "kind": "account", + "path": "amm_program" + } + } + }, + { + "name": "amm_open_orders", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "account", + "path": "amm_program" + }, + { + "kind": "account", + "path": "market" + }, + { + "kind": "const", + "value": [ + 111, + 112, + 101, + 110, + 95, + 111, + 114, + 100, + 101, + 114, + 95, + 97, + 115, + 115, + 111, + 99, + 105, + 97, + 116, + 101, + 100, + 95, + 115, + 101, + 101, + 100 + ] + } + ], + "program": { + "kind": "account", + "path": "amm_program" + } + } + }, + { + "name": "amm_lp_mint", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "account", + "path": "amm_program" + }, + { + "kind": "account", + "path": "market" + }, + { + "kind": "const", + "value": [ + 108, + 112, + 95, + 109, + 105, + 110, + 116, + 95, + 97, + 115, + 115, + 111, + 99, + 105, + 97, + 116, + 101, + 100, + 95, + 115, + 101, + 101, + 100 + ] + } + ], + "program": { + "kind": "account", + "path": "amm_program" + } + } + }, + { + "name": "amm_base_vault", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "account", + "path": "amm_program" + }, + { + "kind": "account", + "path": "market" + }, + { + "kind": "const", + "value": [ + 99, + 111, + 105, + 110, + 95, + 118, + 97, + 117, + 108, + 116, + 95, + 97, + 115, + 115, + 111, + 99, + 105, + 97, + 116, + 101, + 100, + 95, + 115, + 101, + 101, + 100 + ] + } + ], + "program": { + "kind": "account", + "path": "amm_program" + } + } + }, + { + "name": "amm_quote_vault", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "account", + "path": "amm_program" + }, + { + "kind": "account", + "path": "market" + }, + { + "kind": "const", + "value": [ + 112, + 99, + 95, + 118, + 97, + 117, + 108, + 116, + 95, + 97, + 115, + 115, + 111, + 99, + 105, + 97, + 116, + 101, + 100, + 95, + 115, + 101, + 101, + 100 + ] + } + ], + "program": { + "kind": "account", + "path": "amm_program" + } + } + }, + { + "name": "amm_target_orders", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "account", + "path": "amm_program" + }, + { + "kind": "account", + "path": "market" + }, + { + "kind": "const", + "value": [ + 116, + 97, + 114, + 103, + 101, + 116, + 95, + 97, + 115, + 115, + 111, + 99, + 105, + 97, + 116, + 101, + 100, + 95, + 115, + 101, + 101, + 100 + ] + } + ], + "program": { + "kind": "account", + "path": "amm_program" + } + } + }, + { + "name": "amm_config", + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 97, + 109, + 109, + 95, + 99, + 111, + 110, + 102, + 105, + 103, + 95, + 97, + 99, + 99, + 111, + 117, + 110, + 116, + 95, + 115, + 101, + 101, + 100 + ] + } + ], + "program": { + "kind": "account", + "path": "amm_program" + } + } + }, + { + "name": "amm_create_fee_destination", + "writable": true + }, + { + "name": "authority", + "docs": [ + "PDA that acts as the authority for pool vault operations", + "Generated using AUTH_SEED" + ], + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 118, + 97, + 117, + 108, + 116, + 95, + 97, + 117, + 116, + 104, + 95, + 115, + 101, + 101, + 100 + ] + } + ] + } + }, + { + "name": "pool_state", + "docs": [ + "Account that stores the pool's state and parameters", + "PDA generated using POOL_SEED and both token mints" + ], + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 112, + 111, + 111, + 108 + ] + }, + { + "kind": "account", + "path": "base_mint" + }, + { + "kind": "account", + "path": "quote_mint" + } + ] + } + }, + { + "name": "global_config", + "docs": [ + "Global config account stores owner" + ] + }, + { + "name": "base_vault", + "docs": [ + "The pool's vault for base tokens", + "Will be fully drained during migration" + ], + "writable": true + }, + { + "name": "quote_vault", + "docs": [ + "The pool's vault for quote tokens", + "Will be fully drained during migration" + ], + "writable": true + }, + { + "name": "pool_lp_token", + "writable": true + }, + { + "name": "spl_token_program", + "docs": [ + "SPL Token program for the base token", + "Must be the standard Token program" + ], + "address": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA" + }, + { + "name": "associated_token_program", + "docs": [ + "Program to create an ATA for receiving fee NFT" + ], + "address": "ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL" + }, + { + "name": "system_program", + "docs": [ + "Required for account creation" + ], + "address": "11111111111111111111111111111111" + }, + { + "name": "rent_program", + "docs": [ + "Required for rent exempt calculations" + ], + "address": "SysvarRent111111111111111111111111111111111" + } + ], + "args": [ + { + "name": "base_lot_size", + "type": "u64" + }, + { + "name": "quote_lot_size", + "type": "u64" + }, + { + "name": "market_vault_signer_nonce", + "type": "u8" + } + ] + }, + { + "name": "migrate_to_cpswap", + "docs": [ + "# Arguments", + "", + "* `ctx` - The context of accounts", + "" + ], + "discriminator": [ + 136, + 92, + 200, + 103, + 28, + 218, + 144, + 140 + ], + "accounts": [ + { + "name": "payer", + "docs": [ + "Only migrate_to_cpswap_wallet can migrate to cpswap pool", + "This signer must match the migrate_to_cpswap_wallet saved in global_config" + ], + "writable": true, + "signer": true + }, + { + "name": "base_mint", + "docs": [ + "The mint for the base token (token being sold)" + ] + }, + { + "name": "quote_mint", + "docs": [ + "The mint for the quote token (token used to buy)" + ] + }, + { + "name": "platform_config", + "docs": [ + "Platform configuration account containing platform-wide settings", + "Used to read platform fee rate" + ] + }, + { + "name": "cpswap_program", + "address": "CPMMoo8L3F4NbTegBCKVNunggL7H1ZpdTHKxQB5qKP1C" + }, + { + "name": "cpswap_pool", + "docs": [ + "PDA account:", + "seeds = [", + "b\"pool\",", + "cpswap_config.key().as_ref(),", + "token_0_mint.key().as_ref(),", + "token_1_mint.key().as_ref(),", + "],", + "seeds::program = cpswap_program,", + "", + "Or random account: must be signed by cli" + ], + "writable": true + }, + { + "name": "cpswap_authority", + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 118, + 97, + 117, + 108, + 116, + 95, + 97, + 110, + 100, + 95, + 108, + 112, + 95, + 109, + 105, + 110, + 116, + 95, + 97, + 117, + 116, + 104, + 95, + 115, + 101, + 101, + 100 + ] + } + ], + "program": { + "kind": "account", + "path": "cpswap_program" + } + } + }, + { + "name": "cpswap_lp_mint", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 112, + 111, + 111, + 108, + 95, + 108, + 112, + 95, + 109, + 105, + 110, + 116 + ] + }, + { + "kind": "account", + "path": "cpswap_pool" + } + ], + "program": { + "kind": "account", + "path": "cpswap_program" + } + } + }, + { + "name": "cpswap_base_vault", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 112, + 111, + 111, + 108, + 95, + 118, + 97, + 117, + 108, + 116 + ] + }, + { + "kind": "account", + "path": "cpswap_pool" + }, + { + "kind": "account", + "path": "base_mint" + } + ], + "program": { + "kind": "account", + "path": "cpswap_program" + } + } + }, + { + "name": "cpswap_quote_vault", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 112, + 111, + 111, + 108, + 95, + 118, + 97, + 117, + 108, + 116 + ] + }, + { + "kind": "account", + "path": "cpswap_pool" + }, + { + "kind": "account", + "path": "quote_mint" + } + ], + "program": { + "kind": "account", + "path": "cpswap_program" + } + } + }, + { + "name": "cpswap_config" + }, + { + "name": "cpswap_create_pool_fee", + "writable": true + }, + { + "name": "cpswap_observation", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 111, + 98, + 115, + 101, + 114, + 118, + 97, + 116, + 105, + 111, + 110 + ] + }, + { + "kind": "account", + "path": "cpswap_pool" + } + ], + "program": { + "kind": "account", + "path": "cpswap_program" + } + } + }, + { + "name": "lock_program", + "address": "LockrWmn6K5twhz3y9w1dQERbmgSaRkfnTeTKbpofwE" + }, + { + "name": "lock_authority", + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 108, + 111, + 99, + 107, + 95, + 99, + 112, + 95, + 97, + 117, + 116, + 104, + 111, + 114, + 105, + 116, + 121, + 95, + 115, + 101, + 101, + 100 + ] + } + ], + "program": { + "kind": "account", + "path": "lock_program" + } + } + }, + { + "name": "lock_lp_vault", + "writable": true + }, + { + "name": "authority", + "docs": [ + "PDA that acts as the authority for pool vault operations", + "Generated using AUTH_SEED" + ], + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 118, + 97, + 117, + 108, + 116, + 95, + 97, + 117, + 116, + 104, + 95, + 115, + 101, + 101, + 100 + ] + } + ] + } + }, + { + "name": "pool_state", + "docs": [ + "Account that stores the pool's state and parameters", + "PDA generated using POOL_SEED and both token mints" + ], + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 112, + 111, + 111, + 108 + ] + }, + { + "kind": "account", + "path": "base_mint" + }, + { + "kind": "account", + "path": "quote_mint" + } + ] + } + }, + { + "name": "global_config", + "docs": [ + "Global config account stores owner" + ] + }, + { + "name": "base_vault", + "docs": [ + "The pool's vault for base tokens", + "Will be fully drained during migration" + ], + "writable": true + }, + { + "name": "quote_vault", + "docs": [ + "The pool's vault for quote tokens", + "Will be fully drained during migration" + ], + "writable": true + }, + { + "name": "pool_lp_token", + "writable": true + }, + { + "name": "base_token_program", + "docs": [ + "SPL Token program for the base token", + "Must be the standard Token program" + ], + "address": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA" + }, + { + "name": "quote_token_program", + "docs": [ + "SPL Token program for the quote token" + ], + "address": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA" + }, + { + "name": "associated_token_program", + "docs": [ + "Program to create an ATA for receiving fee NFT" + ], + "address": "ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL" + }, + { + "name": "system_program", + "docs": [ + "Required for account creation" + ], + "address": "11111111111111111111111111111111" + }, + { + "name": "rent_program", + "docs": [ + "Required for rent exempt calculations" + ], + "address": "SysvarRent111111111111111111111111111111111" + }, + { + "name": "metadata_program", + "docs": [ + "Program to create NFT metadata accunt" + ], + "address": "metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s" + } + ], + "args": [] + }, + { + "name": "sell_exact_in", + "docs": [ + "Use the given amount of base tokens to sell for quote tokens.", + "# Arguments", + "", + "* `ctx` - The context of accounts", + "* `amount_in` - Amount of base token to sell", + "* `minimum_amount_out` - Minimum amount of quote token to receive (slippage protection)", + "* `share_fee_rate` - Fee rate for the share", + "" + ], + "discriminator": [ + 149, + 39, + 222, + 155, + 211, + 124, + 152, + 26 + ], + "accounts": [ + { + "name": "payer", + "docs": [ + "The user performing the swap operation", + "Must sign the transaction and pay for fees" + ], + "signer": true + }, + { + "name": "authority", + "docs": [ + "PDA that acts as the authority for pool vault operations", + "Generated using AUTH_SEED" + ], + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 118, + 97, + 117, + 108, + 116, + 95, + 97, + 117, + 116, + 104, + 95, + 115, + 101, + 101, + 100 + ] + } + ] + } + }, + { + "name": "global_config", + "docs": [ + "Global configuration account containing protocol-wide settings", + "Used to read protocol fee rates and curve type" + ] + }, + { + "name": "platform_config", + "docs": [ + "Platform configuration account containing platform-wide settings", + "Used to read platform fee rate" + ] + }, + { + "name": "pool_state", + "docs": [ + "The pool state account where the swap will be performed", + "Contains current pool parameters and balances" + ], + "writable": true + }, + { + "name": "user_base_token", + "docs": [ + "The user's token account for base tokens (tokens being bought)", + "Will receive the output tokens after the swap" + ], + "writable": true + }, + { + "name": "user_quote_token", + "docs": [ + "The user's token account for quote tokens (tokens being sold)", + "Will be debited for the input amount" + ], + "writable": true + }, + { + "name": "base_vault", + "docs": [ + "The pool's vault for base tokens", + "Will be debited to send tokens to the user" + ], + "writable": true + }, + { + "name": "quote_vault", + "docs": [ + "The pool's vault for quote tokens", + "Will receive the input tokens from the user" + ], + "writable": true + }, + { + "name": "base_token_mint", + "docs": [ + "The mint of the base token", + "Used for transfer fee calculations if applicable" + ] + }, + { + "name": "quote_token_mint", + "docs": [ + "The mint of the quote token" + ] + }, + { + "name": "base_token_program", + "docs": [ + "SPL Token program for base token transfers" + ] + }, + { + "name": "quote_token_program", + "docs": [ + "SPL Token program for quote token transfers" + ], + "address": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA" + }, + { + "name": "event_authority", + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 95, + 95, + 101, + 118, + 101, + 110, + 116, + 95, + 97, + 117, + 116, + 104, + 111, + 114, + 105, + 116, + 121 + ] + } + ] + } + }, + { + "name": "program" + } + ], + "args": [ + { + "name": "amount_in", + "type": "u64" + }, + { + "name": "minimum_amount_out", + "type": "u64" + }, + { + "name": "share_fee_rate", + "type": "u64" + } + ] + }, + { + "name": "sell_exact_out", + "docs": [ + "Sell base tokens for the given amount of quote tokens.", + "# Arguments", + "", + "* `ctx` - The context of accounts", + "* `amount_out` - Amount of quote token to receive", + "* `maximum_amount_in` - Maximum amount of base token to purchase (slippage protection)", + "* `share_fee_rate` - Fee rate for the share", + "" + ], + "discriminator": [ + 95, + 200, + 71, + 34, + 8, + 9, + 11, + 166 + ], + "accounts": [ + { + "name": "payer", + "docs": [ + "The user performing the swap operation", + "Must sign the transaction and pay for fees" + ], + "signer": true + }, + { + "name": "authority", + "docs": [ + "PDA that acts as the authority for pool vault operations", + "Generated using AUTH_SEED" + ], + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 118, + 97, + 117, + 108, + 116, + 95, + 97, + 117, + 116, + 104, + 95, + 115, + 101, + 101, + 100 + ] + } + ] + } + }, + { + "name": "global_config", + "docs": [ + "Global configuration account containing protocol-wide settings", + "Used to read protocol fee rates and curve type" + ] + }, + { + "name": "platform_config", + "docs": [ + "Platform configuration account containing platform-wide settings", + "Used to read platform fee rate" + ] + }, + { + "name": "pool_state", + "docs": [ + "The pool state account where the swap will be performed", + "Contains current pool parameters and balances" + ], + "writable": true + }, + { + "name": "user_base_token", + "docs": [ + "The user's token account for base tokens (tokens being bought)", + "Will receive the output tokens after the swap" + ], + "writable": true + }, + { + "name": "user_quote_token", + "docs": [ + "The user's token account for quote tokens (tokens being sold)", + "Will be debited for the input amount" + ], + "writable": true + }, + { + "name": "base_vault", + "docs": [ + "The pool's vault for base tokens", + "Will be debited to send tokens to the user" + ], + "writable": true + }, + { + "name": "quote_vault", + "docs": [ + "The pool's vault for quote tokens", + "Will receive the input tokens from the user" + ], + "writable": true + }, + { + "name": "base_token_mint", + "docs": [ + "The mint of the base token", + "Used for transfer fee calculations if applicable" + ] + }, + { + "name": "quote_token_mint", + "docs": [ + "The mint of the quote token" + ] + }, + { + "name": "base_token_program", + "docs": [ + "SPL Token program for base token transfers" + ] + }, + { + "name": "quote_token_program", + "docs": [ + "SPL Token program for quote token transfers" + ], + "address": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA" + }, + { + "name": "event_authority", + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 95, + 95, + 101, + 118, + 101, + 110, + 116, + 95, + 97, + 117, + 116, + 104, + 111, + 114, + 105, + 116, + 121 + ] + } + ] + } + }, + { + "name": "program" + } + ], + "args": [ + { + "name": "amount_out", + "type": "u64" + }, + { + "name": "maximum_amount_in", + "type": "u64" + }, + { + "name": "share_fee_rate", + "type": "u64" + } + ] + }, + { + "name": "update_config", + "docs": [ + "Updates configuration parameters", + "# Arguments", + "", + "* `ctx` - The context of accounts", + "* `param` - Parameter to update:", + "- 0: Update trade_fee_rate", + "- 1: Update fee owner", + "* `value` - New value for the selected parameter", + "" + ], + "discriminator": [ + 29, + 158, + 252, + 191, + 10, + 83, + 219, + 99 + ], + "accounts": [ + { + "name": "owner", + "docs": [ + "The global config owner or admin" + ], + "signer": true, + "address": "GThUX1Atko4tqhN2NaiTazWSeFWMuiUvfFnyJyUghFMJ" + }, + { + "name": "global_config", + "docs": [ + "Global config account to be changed" + ], + "writable": true + } + ], + "args": [ + { + "name": "param", + "type": "u8" + }, + { + "name": "value", + "type": "u64" + } + ] + }, + { + "name": "update_platform_config", + "docs": [ + "Update platform config", + "# Arguments", + "", + "* `ctx` - The context of accounts", + "* `param` - Parameter to update", + "" + ], + "discriminator": [ + 195, + 60, + 76, + 129, + 146, + 45, + 67, + 143 + ], + "accounts": [ + { + "name": "platform_admin", + "docs": [ + "The account paying for the initialization costs" + ], + "signer": true + }, + { + "name": "platform_config", + "docs": [ + "Platform config account to be changed" + ], + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 112, + 108, + 97, + 116, + 102, + 111, + 114, + 109, + 95, + 99, + 111, + 110, + 102, + 105, + 103 + ] + }, + { + "kind": "account", + "path": "platform_admin" + } + ] + } + } + ], + "args": [ + { + "name": "param", + "type": { + "defined": { + "name": "PlatformConfigParam" + } + } + } + ] + } + ], + "accounts": [ + { + "name": "GlobalConfig", + "discriminator": [ + 149, + 8, + 156, + 202, + 160, + 252, + 176, + 217 + ] + }, + { + "name": "PlatformConfig", + "discriminator": [ + 160, + 78, + 128, + 0, + 248, + 83, + 230, + 160 + ] + }, + { + "name": "PoolState", + "discriminator": [ + 247, + 237, + 227, + 245, + 215, + 195, + 222, + 70 + ] + }, + { + "name": "VestingRecord", + "discriminator": [ + 106, + 243, + 221, + 205, + 230, + 126, + 85, + 83 + ] + } + ], + "events": [ + { + "name": "ClaimVestedEvent", + "discriminator": [ + 21, + 194, + 114, + 87, + 120, + 211, + 226, + 32 + ] + }, + { + "name": "CreateVestingEvent", + "discriminator": [ + 150, + 152, + 11, + 179, + 52, + 210, + 191, + 125 + ] + }, + { + "name": "PoolCreateEvent", + "discriminator": [ + 151, + 215, + 226, + 9, + 118, + 161, + 115, + 174 + ] + }, + { + "name": "TradeEvent", + "discriminator": [ + 189, + 219, + 127, + 211, + 78, + 230, + 97, + 238 + ] + } + ], + "errors": [ + { + "code": 6000, + "name": "NotApproved", + "msg": "Not approved" + }, + { + "code": 6001, + "name": "InvalidOwner", + "msg": "Input account owner is not the program address" + }, + { + "code": 6002, + "name": "InvalidInput", + "msg": "InvalidInput" + }, + { + "code": 6003, + "name": "InputNotMatchCurveConfig", + "msg": "The input params are not match with curve type in config" + }, + { + "code": 6004, + "name": "ExceededSlippage", + "msg": "Exceeds desired slippage limit" + }, + { + "code": 6005, + "name": "PoolFunding", + "msg": "Pool funding" + }, + { + "code": 6006, + "name": "PoolMigrated", + "msg": "Pool migrated" + }, + { + "code": 6007, + "name": "MigrateTypeNotMatch", + "msg": "Migrate type not match" + }, + { + "code": 6008, + "name": "MathOverflow", + "msg": "Math overflow" + }, + { + "code": 6009, + "name": "NoAssetsToCollect", + "msg": "No assets to collect" + }, + { + "code": 6010, + "name": "VestingRatioTooHigh", + "msg": "Vesting ratio too high" + }, + { + "code": 6011, + "name": "VestingSettingEnded", + "msg": "Vesting setting ended" + }, + { + "code": 6012, + "name": "VestingNotStarted", + "msg": "Vesting not started" + }, + { + "code": 6013, + "name": "NoVestingSchedule", + "msg": "No vesting schedule" + }, + { + "code": 6014, + "name": "InvalidPlatformInfo", + "msg": "The platform info input is invalid" + }, + { + "code": 6015, + "name": "PoolNotMigrated", + "msg": "Pool not migrated" + } + ], + "types": [ + { + "name": "ClaimVestedEvent", + "docs": [ + "Emitted when vesting token claimed by beneficiary" + ], + "type": { + "kind": "struct", + "fields": [ + { + "name": "pool_state", + "type": "pubkey" + }, + { + "name": "beneficiary", + "type": "pubkey" + }, + { + "name": "claim_amount", + "type": "u64" + } + ] + } + }, + { + "name": "ConstantCurve", + "type": { + "kind": "struct", + "fields": [ + { + "name": "supply", + "type": "u64" + }, + { + "name": "total_base_sell", + "type": "u64" + }, + { + "name": "total_quote_fund_raising", + "type": "u64" + }, + { + "name": "migrate_type", + "type": "u8" + } + ] + } + }, + { + "name": "CreateVestingEvent", + "docs": [ + "Emitted when vest_account created" + ], + "type": { + "kind": "struct", + "fields": [ + { + "name": "pool_state", + "type": "pubkey" + }, + { + "name": "beneficiary", + "type": "pubkey" + }, + { + "name": "share_amount", + "type": "u64" + } + ] + } + }, + { + "name": "CurveParams", + "type": { + "kind": "enum", + "variants": [ + { + "name": "Constant", + "fields": [ + { + "name": "data", + "type": { + "defined": { + "name": "ConstantCurve" + } + } + } + ] + }, + { + "name": "Fixed", + "fields": [ + { + "name": "data", + "type": { + "defined": { + "name": "FixedCurve" + } + } + } + ] + }, + { + "name": "Linear", + "fields": [ + { + "name": "data", + "type": { + "defined": { + "name": "LinearCurve" + } + } + } + ] + } + ] + } + }, + { + "name": "FixedCurve", + "type": { + "kind": "struct", + "fields": [ + { + "name": "supply", + "type": "u64" + }, + { + "name": "total_quote_fund_raising", + "type": "u64" + }, + { + "name": "migrate_type", + "type": "u8" + } + ] + } + }, + { + "name": "GlobalConfig", + "docs": [ + "Holds the current owner of the factory" + ], + "type": { + "kind": "struct", + "fields": [ + { + "name": "epoch", + "docs": [ + "Account update epoch" + ], + "type": "u64" + }, + { + "name": "curve_type", + "docs": [ + "0: Constant Product Curve", + "1: Fixed Price Curve", + "2: Linear Price Curve" + ], + "type": "u8" + }, + { + "name": "index", + "docs": [ + "Config index" + ], + "type": "u16" + }, + { + "name": "migrate_fee", + "docs": [ + "The fee of migrate to amm" + ], + "type": "u64" + }, + { + "name": "trade_fee_rate", + "docs": [ + "The trade fee rate, denominated in hundredths of a bip (10^-6)" + ], + "type": "u64" + }, + { + "name": "max_share_fee_rate", + "docs": [ + "The maximum share fee rate, denominated in hundredths of a bip (10^-6)" + ], + "type": "u64" + }, + { + "name": "min_base_supply", + "docs": [ + "The minimum base supply, the value without decimals" + ], + "type": "u64" + }, + { + "name": "max_lock_rate", + "docs": [ + "The maximum lock rate, denominated in hundredths of a bip (10^-6)" + ], + "type": "u64" + }, + { + "name": "min_base_sell_rate", + "docs": [ + "The minimum base sell rate, denominated in hundredths of a bip (10^-6)" + ], + "type": "u64" + }, + { + "name": "min_base_migrate_rate", + "docs": [ + "The minimum base migrate rate, denominated in hundredths of a bip (10^-6)" + ], + "type": "u64" + }, + { + "name": "min_quote_fund_raising", + "docs": [ + "The minimum quote fund raising, the value with decimals" + ], + "type": "u64" + }, + { + "name": "quote_mint", + "docs": [ + "Mint information for quote token" + ], + "type": "pubkey" + }, + { + "name": "protocol_fee_owner", + "docs": [ + "Protocol Fee owner" + ], + "type": "pubkey" + }, + { + "name": "migrate_fee_owner", + "docs": [ + "Migrate Fee owner" + ], + "type": "pubkey" + }, + { + "name": "migrate_to_amm_wallet", + "docs": [ + "Migrate to amm control wallet" + ], + "type": "pubkey" + }, + { + "name": "migrate_to_cpswap_wallet", + "docs": [ + "Migrate to cpswap wallet" + ], + "type": "pubkey" + }, + { + "name": "padding", + "docs": [ + "padding for future updates" + ], + "type": { + "array": [ + "u64", + 16 + ] + } + } + ] + } + }, + { + "name": "LinearCurve", + "type": { + "kind": "struct", + "fields": [ + { + "name": "supply", + "type": "u64" + }, + { + "name": "total_quote_fund_raising", + "type": "u64" + }, + { + "name": "migrate_type", + "type": "u8" + } + ] + } + }, + { + "name": "MigrateNftInfo", + "docs": [ + "Represents the parameters for initializing a platform config account(Only support MigrateType::CPSWAP)", + "# Fields", + "* `platform_scale` - Scale of the platform liquidity quantity rights will be converted into NFT", + "* `creator_scale` - Scale of the token creator liquidity quantity rights will be converted into NFT", + "* `burn_scale` - Scale of liquidity directly to burn", + "", + "* platform_scale + creator_scale + burn_scale = RATE_DENOMINATOR_VALUE" + ], + "type": { + "kind": "struct", + "fields": [ + { + "name": "platform_scale", + "type": "u64" + }, + { + "name": "creator_scale", + "type": "u64" + }, + { + "name": "burn_scale", + "type": "u64" + } + ] + } + }, + { + "name": "MintParams", + "docs": [ + "Represents the parameters for initializing a new token mint", + "# Fields", + "* `decimals` - Number of decimal places for the token", + "* `name` - Name of the token", + "* `symbol` - Symbol/ticker of the token", + "* `uri` - URI pointing to token metadata" + ], + "type": { + "kind": "struct", + "fields": [ + { + "name": "decimals", + "type": "u8" + }, + { + "name": "name", + "type": "string" + }, + { + "name": "symbol", + "type": "string" + }, + { + "name": "uri", + "type": "string" + } + ] + } + }, + { + "name": "PlatformConfig", + "type": { + "kind": "struct", + "fields": [ + { + "name": "epoch", + "docs": [ + "The epoch for update interval" + ], + "type": "u64" + }, + { + "name": "platform_fee_wallet", + "docs": [ + "The platform fee wallet" + ], + "type": "pubkey" + }, + { + "name": "platform_nft_wallet", + "docs": [ + "The platform nft wallet to receive the platform NFT after migration if platform_scale is not 0(Only support MigrateType::CPSWAP)" + ], + "type": "pubkey" + }, + { + "name": "platform_scale", + "docs": [ + "Scale of the platform liquidity quantity rights will be converted into NFT(Only support MigrateType::CPSWAP)" + ], + "type": "u64" + }, + { + "name": "creator_scale", + "docs": [ + "Scale of the token creator liquidity quantity rights will be converted into NFT(Only support MigrateType::CPSWAP)" + ], + "type": "u64" + }, + { + "name": "burn_scale", + "docs": [ + "Scale of liquidity directly to burn" + ], + "type": "u64" + }, + { + "name": "fee_rate", + "docs": [ + "The platform fee rate" + ], + "type": "u64" + }, + { + "name": "name", + "docs": [ + "The platform name" + ], + "type": { + "array": [ + "u8", + 64 + ] + } + }, + { + "name": "web", + "docs": [ + "The platform website" + ], + "type": { + "array": [ + "u8", + 256 + ] + } + }, + { + "name": "img", + "docs": [ + "The platform img link" + ], + "type": { + "array": [ + "u8", + 256 + ] + } + }, + { + "name": "padding", + "docs": [ + "padding for future updates" + ], + "type": { + "array": [ + "u8", + 256 + ] + } + } + ] + } + }, + { + "name": "PlatformConfigParam", + "type": { + "kind": "enum", + "variants": [ + { + "name": "FeeWallet", + "fields": [ + "pubkey" + ] + }, + { + "name": "NFTWallet", + "fields": [ + "pubkey" + ] + }, + { + "name": "MigrateNftInfo", + "fields": [ + { + "defined": { + "name": "MigrateNftInfo" + } + } + ] + }, + { + "name": "FeeRate", + "fields": [ + "u64" + ] + }, + { + "name": "Name", + "fields": [ + "string" + ] + }, + { + "name": "Web", + "fields": [ + "string" + ] + }, + { + "name": "Img", + "fields": [ + "string" + ] + } + ] + } + }, + { + "name": "PlatformParams", + "docs": [ + "Represents the parameters for initializing a platform config account", + "# Fields", + "* `migrate_nft_info` - The platform configures liquidity info during migration(Only support MigrateType::CPSWAP)", + "* `fee_rate` - Fee rate of the platform", + "* `name` - Name of the platform", + "* `web` - Website of the platform", + "* `img` - Image link of the platform" + ], + "type": { + "kind": "struct", + "fields": [ + { + "name": "migrate_nft_info", + "type": { + "defined": { + "name": "MigrateNftInfo" + } + } + }, + { + "name": "fee_rate", + "type": "u64" + }, + { + "name": "name", + "type": "string" + }, + { + "name": "web", + "type": "string" + }, + { + "name": "img", + "type": "string" + } + ] + } + }, + { + "name": "PoolCreateEvent", + "docs": [ + "Emitted when pool created" + ], + "type": { + "kind": "struct", + "fields": [ + { + "name": "pool_state", + "type": "pubkey" + }, + { + "name": "creator", + "type": "pubkey" + }, + { + "name": "config", + "type": "pubkey" + }, + { + "name": "base_mint_param", + "type": { + "defined": { + "name": "MintParams" + } + } + }, + { + "name": "curve_param", + "type": { + "defined": { + "name": "CurveParams" + } + } + }, + { + "name": "vesting_param", + "type": { + "defined": { + "name": "VestingParams" + } + } + } + ] + } + }, + { + "name": "PoolState", + "docs": [ + "Represents the state of a trading pool in the protocol", + "Stores all essential information about pool balances, fees, and configuration" + ], + "type": { + "kind": "struct", + "fields": [ + { + "name": "epoch", + "docs": [ + "Account update epoch" + ], + "type": "u64" + }, + { + "name": "auth_bump", + "docs": [ + "Bump seed used for PDA address derivation" + ], + "type": "u8" + }, + { + "name": "status", + "docs": [ + "Current status of the pool", + "* 0: Pool is funding", + "* 1: Pool funding is end, waiting for migration", + "* 2: Pool migration is done" + ], + "type": "u8" + }, + { + "name": "base_decimals", + "docs": [ + "Decimals of the pool base token" + ], + "type": "u8" + }, + { + "name": "quote_decimals", + "docs": [ + "Decimals of the pool quote token" + ], + "type": "u8" + }, + { + "name": "migrate_type", + "docs": [ + "Migrate to AMM or CpSwap" + ], + "type": "u8" + }, + { + "name": "supply", + "docs": [ + "Supply of the pool base token" + ], + "type": "u64" + }, + { + "name": "total_base_sell", + "docs": [ + "Total sell amount of the base token" + ], + "type": "u64" + }, + { + "name": "virtual_base", + "docs": [ + "For different curves, virtual_base and virtual_quote have different meanings", + "For constant product curve, virtual_base and virtual_quote are virtual liquidity, virtual_quote/virtual_base is the initial price", + "For linear price curve, virtual_base is the price slope parameter a, virtual_quote has no effect", + "For fixed price curve, virtual_quote/virtual_base is the initial price" + ], + "type": "u64" + }, + { + "name": "virtual_quote", + "type": "u64" + }, + { + "name": "real_base", + "docs": [ + "Actual base token amount in the pool", + "Represents the real tokens available for trading" + ], + "type": "u64" + }, + { + "name": "real_quote", + "docs": [ + "Actual quote token amount in the pool", + "Represents the real tokens available for trading" + ], + "type": "u64" + }, + { + "name": "total_quote_fund_raising", + "docs": [ + "The total quote fund raising of the pool" + ], + "type": "u64" + }, + { + "name": "quote_protocol_fee", + "docs": [ + "Accumulated trading fees in quote tokens", + "Can be collected by the protocol fee owner" + ], + "type": "u64" + }, + { + "name": "platform_fee", + "docs": [ + "Accumulated platform fees in quote tokens", + "Can be collected by the platform wallet stored in platform config" + ], + "type": "u64" + }, + { + "name": "migrate_fee", + "docs": [ + "The fee of migrate to amm" + ], + "type": "u64" + }, + { + "name": "vesting_schedule", + "docs": [ + "Vesting schedule for the base token" + ], + "type": { + "defined": { + "name": "VestingSchedule" + } + } + }, + { + "name": "global_config", + "docs": [ + "Public key of the global configuration account", + "Contains protocol-wide settings this pool adheres to" + ], + "type": "pubkey" + }, + { + "name": "platform_config", + "docs": [ + "Public key of the platform configuration account", + "Contains platform-wide settings this pool adheres to" + ], + "type": "pubkey" + }, + { + "name": "base_mint", + "docs": [ + "Public key of the base mint address" + ], + "type": "pubkey" + }, + { + "name": "quote_mint", + "docs": [ + "Public key of the quote mint address" + ], + "type": "pubkey" + }, + { + "name": "base_vault", + "docs": [ + "Public key of the base token vault", + "Holds the actual base tokens owned by the pool" + ], + "type": "pubkey" + }, + { + "name": "quote_vault", + "docs": [ + "Public key of the quote token vault", + "Holds the actual quote tokens owned by the pool" + ], + "type": "pubkey" + }, + { + "name": "creator", + "docs": [ + "The creator of base token" + ], + "type": "pubkey" + }, + { + "name": "padding", + "docs": [ + "padding for future updates" + ], + "type": { + "array": [ + "u64", + 8 + ] + } + } + ] + } + }, + { + "name": "PoolStatus", + "docs": [ + "Represents the different states a pool can be in", + "* Fund - Initial state where pool is accepting funds", + "* Migrate - Pool funding has ended and waiting for migration", + "* Trade - Pool migration is complete and amm trading is enabled" + ], + "type": { + "kind": "enum", + "variants": [ + { + "name": "Fund" + }, + { + "name": "Migrate" + }, + { + "name": "Trade" + } + ] + } + }, + { + "name": "TradeDirection", + "docs": [ + "Specifies the direction of a trade in the bonding curve", + "This is important because curves can treat tokens differently through weights or offsets" + ], + "type": { + "kind": "enum", + "variants": [ + { + "name": "Buy" + }, + { + "name": "Sell" + } + ] + } + }, + { + "name": "TradeEvent", + "docs": [ + "Emitted when trade process" + ], + "type": { + "kind": "struct", + "fields": [ + { + "name": "pool_state", + "type": "pubkey" + }, + { + "name": "total_base_sell", + "type": "u64" + }, + { + "name": "virtual_base", + "type": "u64" + }, + { + "name": "virtual_quote", + "type": "u64" + }, + { + "name": "real_base_before", + "type": "u64" + }, + { + "name": "real_quote_before", + "type": "u64" + }, + { + "name": "real_base_after", + "type": "u64" + }, + { + "name": "real_quote_after", + "type": "u64" + }, + { + "name": "amount_in", + "type": "u64" + }, + { + "name": "amount_out", + "type": "u64" + }, + { + "name": "protocol_fee", + "type": "u64" + }, + { + "name": "platform_fee", + "type": "u64" + }, + { + "name": "share_fee", + "type": "u64" + }, + { + "name": "trade_direction", + "type": { + "defined": { + "name": "TradeDirection" + } + } + }, + { + "name": "pool_status", + "type": { + "defined": { + "name": "PoolStatus" + } + } + } + ] + } + }, + { + "name": "VestingParams", + "type": { + "kind": "struct", + "fields": [ + { + "name": "total_locked_amount", + "type": "u64" + }, + { + "name": "cliff_period", + "type": "u64" + }, + { + "name": "unlock_period", + "type": "u64" + } + ] + } + }, + { + "name": "VestingRecord", + "type": { + "kind": "struct", + "fields": [ + { + "name": "epoch", + "docs": [ + "Account update epoch" + ], + "type": "u64" + }, + { + "name": "pool", + "docs": [ + "The pool state account" + ], + "type": "pubkey" + }, + { + "name": "beneficiary", + "docs": [ + "The beneficiary of the vesting account" + ], + "type": "pubkey" + }, + { + "name": "claimed_amount", + "docs": [ + "The amount of tokens claimed" + ], + "type": "u64" + }, + { + "name": "token_share_amount", + "docs": [ + "The share amount of the token to be vested" + ], + "type": "u64" + }, + { + "name": "padding", + "docs": [ + "padding for future updates" + ], + "type": { + "array": [ + "u64", + 8 + ] + } + } + ] + } + }, + { + "name": "VestingSchedule", + "type": { + "kind": "struct", + "fields": [ + { + "name": "total_locked_amount", + "type": "u64" + }, + { + "name": "cliff_period", + "type": "u64" + }, + { + "name": "unlock_period", + "type": "u64" + }, + { + "name": "start_time", + "type": "u64" + }, + { + "name": "allocated_share_amount", + "docs": [ + "Total allocated share amount of the base token, not greater than total_locked_amount" + ], + "type": "u64" + } + ] + } + } + ] +} \ No newline at end of file diff --git a/e2e/raydium-launchpad/src/generated/accounts/global_config.rs b/e2e/raydium-launchpad/src/generated/accounts/global_config.rs new file mode 100644 index 0000000..0ac01aa --- /dev/null +++ b/e2e/raydium-launchpad/src/generated/accounts/global_config.rs @@ -0,0 +1,166 @@ +//! This code was AUTOGENERATED using the codama library. +//! Please DO NOT EDIT THIS FILE, instead use visitors +//! to add features, then rerun codama to update it. +//! +//! +//! + +use borsh::BorshDeserialize; +use borsh::BorshSerialize; +use solana_address::Address; + +#[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] +pub struct GlobalConfig { + pub discriminator: [u8; 8], + /// Account update epoch + pub epoch: u64, + /// 0: Constant Product Curve + /// 1: Fixed Price Curve + /// 2: Linear Price Curve + pub curve_type: u8, + /// Config index + pub index: u16, + /// The fee of migrate to amm + pub migrate_fee: u64, + /// The trade fee rate, denominated in hundredths of a bip (10^-6) + pub trade_fee_rate: u64, + /// The maximum share fee rate, denominated in hundredths of a bip (10^-6) + pub max_share_fee_rate: u64, + /// The minimum base supply, the value without decimals + pub min_base_supply: u64, + /// The maximum lock rate, denominated in hundredths of a bip (10^-6) + pub max_lock_rate: u64, + /// The minimum base sell rate, denominated in hundredths of a bip (10^-6) + pub min_base_sell_rate: u64, + /// The minimum base migrate rate, denominated in hundredths of a bip (10^-6) + pub min_base_migrate_rate: u64, + /// The minimum quote fund raising, the value with decimals + pub min_quote_fund_raising: u64, + /// Mint information for quote token + pub quote_mint: Address, + /// Protocol Fee owner + pub protocol_fee_owner: Address, + /// Migrate Fee owner + pub migrate_fee_owner: Address, + /// Migrate to amm control wallet + pub migrate_to_amm_wallet: Address, + /// Migrate to cpswap wallet + pub migrate_to_cpswap_wallet: Address, + /// padding for future updates + pub padding: [u64; 16], +} + +pub const GLOBAL_CONFIG_DISCRIMINATOR: [u8; 8] = [149, 8, 156, 202, 160, 252, 176, 217]; + +impl GlobalConfig { + pub const LEN: usize = 371; + + #[inline(always)] + pub fn from_bytes(data: &[u8]) -> Result { + let mut data = data; + Self::deserialize(&mut data) + } +} + +impl<'a> TryFrom<&solana_account_info::AccountInfo<'a>> for GlobalConfig { + type Error = std::io::Error; + + fn try_from(account_info: &solana_account_info::AccountInfo<'a>) -> Result { + let mut data: &[u8] = &(*account_info.data).borrow(); + Self::deserialize(&mut data) + } +} + +#[cfg(feature = "fetch")] +pub fn fetch_global_config( + rpc: &solana_client::rpc_client::RpcClient, + address: &solana_address::Address, +) -> Result, std::io::Error> { + let accounts = fetch_all_global_config(rpc, &[*address])?; + Ok(accounts[0].clone()) +} + +#[cfg(feature = "fetch")] +pub fn fetch_all_global_config( + rpc: &solana_client::rpc_client::RpcClient, + addresses: &[solana_address::Address], +) -> Result>, std::io::Error> { + let accounts = rpc + .get_multiple_accounts(addresses) + .map_err(|e| std::io::Error::other(e.to_string()))?; + let mut decoded_accounts: Vec> = Vec::new(); + for i in 0..addresses.len() { + let address = addresses[i]; + let account = accounts[i].as_ref().ok_or(std::io::Error::other(format!( + "Account not found: {address}" + )))?; + let data = GlobalConfig::from_bytes(&account.data)?; + decoded_accounts.push(crate::shared::DecodedAccount { + address, + account: account.clone(), + data, + }); + } + Ok(decoded_accounts) +} + +#[cfg(feature = "fetch")] +pub fn fetch_maybe_global_config( + rpc: &solana_client::rpc_client::RpcClient, + address: &solana_address::Address, +) -> Result, std::io::Error> { + let accounts = fetch_all_maybe_global_config(rpc, &[*address])?; + Ok(accounts[0].clone()) +} + +#[cfg(feature = "fetch")] +pub fn fetch_all_maybe_global_config( + rpc: &solana_client::rpc_client::RpcClient, + addresses: &[solana_address::Address], +) -> Result>, std::io::Error> { + let accounts = rpc + .get_multiple_accounts(addresses) + .map_err(|e| std::io::Error::other(e.to_string()))?; + let mut decoded_accounts: Vec> = Vec::new(); + for i in 0..addresses.len() { + let address = addresses[i]; + if let Some(account) = accounts[i].as_ref() { + let data = GlobalConfig::from_bytes(&account.data)?; + decoded_accounts.push(crate::shared::MaybeAccount::Exists( + crate::shared::DecodedAccount { + address, + account: account.clone(), + data, + }, + )); + } else { + decoded_accounts.push(crate::shared::MaybeAccount::NotFound(address)); + } + } + Ok(decoded_accounts) +} + +#[cfg(feature = "anchor")] +impl anchor_lang::AccountDeserialize for GlobalConfig { + fn try_deserialize_unchecked(buf: &mut &[u8]) -> anchor_lang::Result { + Ok(Self::deserialize(buf)?) + } +} + +#[cfg(feature = "anchor")] +impl anchor_lang::AccountSerialize for GlobalConfig {} + +#[cfg(feature = "anchor")] +impl anchor_lang::Owner for GlobalConfig { + fn owner() -> anchor_lang::solana_program::pubkey::Pubkey { + anchor_lang::solana_program::pubkey::Pubkey::from(crate::RAYDIUM_LAUNCHPAD_ID.to_bytes()) + } +} + +#[cfg(feature = "anchor-idl-build")] +impl anchor_lang::IdlBuild for GlobalConfig {} + +#[cfg(feature = "anchor-idl-build")] +impl anchor_lang::Discriminator for GlobalConfig { + const DISCRIMINATOR: &[u8] = &[0; 8]; +} diff --git a/e2e/raydium-launchpad/src/generated/accounts/mod.rs b/e2e/raydium-launchpad/src/generated/accounts/mod.rs new file mode 100644 index 0000000..1ea8d75 --- /dev/null +++ b/e2e/raydium-launchpad/src/generated/accounts/mod.rs @@ -0,0 +1,16 @@ +//! This code was AUTOGENERATED using the codama library. +//! Please DO NOT EDIT THIS FILE, instead use visitors +//! to add features, then rerun codama to update it. +//! +//! +//! + +pub(crate) mod r#global_config; +pub(crate) mod r#platform_config; +pub(crate) mod r#pool_state; +pub(crate) mod r#vesting_record; + +pub use self::r#global_config::*; +pub use self::r#platform_config::*; +pub use self::r#pool_state::*; +pub use self::r#vesting_record::*; diff --git a/e2e/raydium-launchpad/src/generated/accounts/platform_config.rs b/e2e/raydium-launchpad/src/generated/accounts/platform_config.rs new file mode 100644 index 0000000..fc4b97e --- /dev/null +++ b/e2e/raydium-launchpad/src/generated/accounts/platform_config.rs @@ -0,0 +1,152 @@ +//! This code was AUTOGENERATED using the codama library. +//! Please DO NOT EDIT THIS FILE, instead use visitors +//! to add features, then rerun codama to update it. +//! +//! +//! + +use borsh::BorshDeserialize; +use borsh::BorshSerialize; +use solana_address::Address; + +#[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] +pub struct PlatformConfig { + pub discriminator: [u8; 8], + /// The epoch for update interval + pub epoch: u64, + /// The platform fee wallet + pub platform_fee_wallet: Address, + /// The platform nft wallet to receive the platform NFT after migration if platform_scale is not 0(Only support MigrateType::CPSWAP) + pub platform_nft_wallet: Address, + /// Scale of the platform liquidity quantity rights will be converted into NFT(Only support MigrateType::CPSWAP) + pub platform_scale: u64, + /// Scale of the token creator liquidity quantity rights will be converted into NFT(Only support MigrateType::CPSWAP) + pub creator_scale: u64, + /// Scale of liquidity directly to burn + pub burn_scale: u64, + /// The platform fee rate + pub fee_rate: u64, + /// The platform name + pub name: [u8; 64], + /// The platform website + pub web: [u8; 256], + /// The platform img link + pub img: [u8; 256], + /// padding for future updates + pub padding: [u8; 256], +} + +pub const PLATFORM_CONFIG_DISCRIMINATOR: [u8; 8] = [160, 78, 128, 0, 248, 83, 230, 160]; + +impl PlatformConfig { + pub const LEN: usize = 944; + + #[inline(always)] + pub fn from_bytes(data: &[u8]) -> Result { + let mut data = data; + Self::deserialize(&mut data) + } +} + +impl<'a> TryFrom<&solana_account_info::AccountInfo<'a>> for PlatformConfig { + type Error = std::io::Error; + + fn try_from(account_info: &solana_account_info::AccountInfo<'a>) -> Result { + let mut data: &[u8] = &(*account_info.data).borrow(); + Self::deserialize(&mut data) + } +} + +#[cfg(feature = "fetch")] +pub fn fetch_platform_config( + rpc: &solana_client::rpc_client::RpcClient, + address: &solana_address::Address, +) -> Result, std::io::Error> { + let accounts = fetch_all_platform_config(rpc, &[*address])?; + Ok(accounts[0].clone()) +} + +#[cfg(feature = "fetch")] +pub fn fetch_all_platform_config( + rpc: &solana_client::rpc_client::RpcClient, + addresses: &[solana_address::Address], +) -> Result>, std::io::Error> { + let accounts = rpc + .get_multiple_accounts(addresses) + .map_err(|e| std::io::Error::other(e.to_string()))?; + let mut decoded_accounts: Vec> = Vec::new(); + for i in 0..addresses.len() { + let address = addresses[i]; + let account = accounts[i].as_ref().ok_or(std::io::Error::other(format!( + "Account not found: {address}" + )))?; + let data = PlatformConfig::from_bytes(&account.data)?; + decoded_accounts.push(crate::shared::DecodedAccount { + address, + account: account.clone(), + data, + }); + } + Ok(decoded_accounts) +} + +#[cfg(feature = "fetch")] +pub fn fetch_maybe_platform_config( + rpc: &solana_client::rpc_client::RpcClient, + address: &solana_address::Address, +) -> Result, std::io::Error> { + let accounts = fetch_all_maybe_platform_config(rpc, &[*address])?; + Ok(accounts[0].clone()) +} + +#[cfg(feature = "fetch")] +pub fn fetch_all_maybe_platform_config( + rpc: &solana_client::rpc_client::RpcClient, + addresses: &[solana_address::Address], +) -> Result>, std::io::Error> { + let accounts = rpc + .get_multiple_accounts(addresses) + .map_err(|e| std::io::Error::other(e.to_string()))?; + let mut decoded_accounts: Vec> = Vec::new(); + for i in 0..addresses.len() { + let address = addresses[i]; + if let Some(account) = accounts[i].as_ref() { + let data = PlatformConfig::from_bytes(&account.data)?; + decoded_accounts.push(crate::shared::MaybeAccount::Exists( + crate::shared::DecodedAccount { + address, + account: account.clone(), + data, + }, + )); + } else { + decoded_accounts.push(crate::shared::MaybeAccount::NotFound(address)); + } + } + Ok(decoded_accounts) +} + +#[cfg(feature = "anchor")] +impl anchor_lang::AccountDeserialize for PlatformConfig { + fn try_deserialize_unchecked(buf: &mut &[u8]) -> anchor_lang::Result { + Ok(Self::deserialize(buf)?) + } +} + +#[cfg(feature = "anchor")] +impl anchor_lang::AccountSerialize for PlatformConfig {} + +#[cfg(feature = "anchor")] +impl anchor_lang::Owner for PlatformConfig { + fn owner() -> anchor_lang::solana_program::pubkey::Pubkey { + anchor_lang::solana_program::pubkey::Pubkey::from(crate::RAYDIUM_LAUNCHPAD_ID.to_bytes()) + } +} + +#[cfg(feature = "anchor-idl-build")] +impl anchor_lang::IdlBuild for PlatformConfig {} + +#[cfg(feature = "anchor-idl-build")] +impl anchor_lang::Discriminator for PlatformConfig { + const DISCRIMINATOR: &[u8] = &[0; 8]; +} diff --git a/e2e/raydium-launchpad/src/generated/accounts/pool_state.rs b/e2e/raydium-launchpad/src/generated/accounts/pool_state.rs new file mode 100644 index 0000000..4fbb0df --- /dev/null +++ b/e2e/raydium-launchpad/src/generated/accounts/pool_state.rs @@ -0,0 +1,194 @@ +//! This code was AUTOGENERATED using the codama library. +//! Please DO NOT EDIT THIS FILE, instead use visitors +//! to add features, then rerun codama to update it. +//! +//! +//! + +use crate::generated::types::VestingSchedule; +use borsh::BorshDeserialize; +use borsh::BorshSerialize; +use solana_address::Address; + +#[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] +pub struct PoolState { + pub discriminator: [u8; 8], + /// Account update epoch + pub epoch: u64, + /// Bump seed used for PDA address derivation + pub auth_bump: u8, + /// Current status of the pool + /// * 0: Pool is funding + /// * 1: Pool funding is end, waiting for migration + /// * 2: Pool migration is done + pub status: u8, + /// Decimals of the pool base token + pub base_decimals: u8, + /// Decimals of the pool quote token + pub quote_decimals: u8, + /// Migrate to AMM or CpSwap + pub migrate_type: u8, + /// Supply of the pool base token + pub supply: u64, + /// Total sell amount of the base token + pub total_base_sell: u64, + /// For different curves, virtual_base and virtual_quote have different meanings + /// For constant product curve, virtual_base and virtual_quote are virtual liquidity, virtual_quote/virtual_base is the initial price + /// For linear price curve, virtual_base is the price slope parameter a, virtual_quote has no effect + /// For fixed price curve, virtual_quote/virtual_base is the initial price + pub virtual_base: u64, + pub virtual_quote: u64, + /// Actual base token amount in the pool + /// Represents the real tokens available for trading + pub real_base: u64, + /// Actual quote token amount in the pool + /// Represents the real tokens available for trading + pub real_quote: u64, + /// The total quote fund raising of the pool + pub total_quote_fund_raising: u64, + /// Accumulated trading fees in quote tokens + /// Can be collected by the protocol fee owner + pub quote_protocol_fee: u64, + /// Accumulated platform fees in quote tokens + /// Can be collected by the platform wallet stored in platform config + pub platform_fee: u64, + /// The fee of migrate to amm + pub migrate_fee: u64, + /// Vesting schedule for the base token + pub vesting_schedule: VestingSchedule, + /// Public key of the global configuration account + /// Contains protocol-wide settings this pool adheres to + pub global_config: Address, + /// Public key of the platform configuration account + /// Contains platform-wide settings this pool adheres to + pub platform_config: Address, + /// Public key of the base mint address + pub base_mint: Address, + /// Public key of the quote mint address + pub quote_mint: Address, + /// Public key of the base token vault + /// Holds the actual base tokens owned by the pool + pub base_vault: Address, + /// Public key of the quote token vault + /// Holds the actual quote tokens owned by the pool + pub quote_vault: Address, + /// The creator of base token + pub creator: Address, + /// padding for future updates + pub padding: [u64; 8], +} + +pub const POOL_STATE_DISCRIMINATOR: [u8; 8] = [247, 237, 227, 245, 215, 195, 222, 70]; + +impl PoolState { + pub const LEN: usize = 429; + + #[inline(always)] + pub fn from_bytes(data: &[u8]) -> Result { + let mut data = data; + Self::deserialize(&mut data) + } +} + +impl<'a> TryFrom<&solana_account_info::AccountInfo<'a>> for PoolState { + type Error = std::io::Error; + + fn try_from(account_info: &solana_account_info::AccountInfo<'a>) -> Result { + let mut data: &[u8] = &(*account_info.data).borrow(); + Self::deserialize(&mut data) + } +} + +#[cfg(feature = "fetch")] +pub fn fetch_pool_state( + rpc: &solana_client::rpc_client::RpcClient, + address: &solana_address::Address, +) -> Result, std::io::Error> { + let accounts = fetch_all_pool_state(rpc, &[*address])?; + Ok(accounts[0].clone()) +} + +#[cfg(feature = "fetch")] +pub fn fetch_all_pool_state( + rpc: &solana_client::rpc_client::RpcClient, + addresses: &[solana_address::Address], +) -> Result>, std::io::Error> { + let accounts = rpc + .get_multiple_accounts(addresses) + .map_err(|e| std::io::Error::other(e.to_string()))?; + let mut decoded_accounts: Vec> = Vec::new(); + for i in 0..addresses.len() { + let address = addresses[i]; + let account = accounts[i].as_ref().ok_or(std::io::Error::other(format!( + "Account not found: {address}" + )))?; + let data = PoolState::from_bytes(&account.data)?; + decoded_accounts.push(crate::shared::DecodedAccount { + address, + account: account.clone(), + data, + }); + } + Ok(decoded_accounts) +} + +#[cfg(feature = "fetch")] +pub fn fetch_maybe_pool_state( + rpc: &solana_client::rpc_client::RpcClient, + address: &solana_address::Address, +) -> Result, std::io::Error> { + let accounts = fetch_all_maybe_pool_state(rpc, &[*address])?; + Ok(accounts[0].clone()) +} + +#[cfg(feature = "fetch")] +pub fn fetch_all_maybe_pool_state( + rpc: &solana_client::rpc_client::RpcClient, + addresses: &[solana_address::Address], +) -> Result>, std::io::Error> { + let accounts = rpc + .get_multiple_accounts(addresses) + .map_err(|e| std::io::Error::other(e.to_string()))?; + let mut decoded_accounts: Vec> = Vec::new(); + for i in 0..addresses.len() { + let address = addresses[i]; + if let Some(account) = accounts[i].as_ref() { + let data = PoolState::from_bytes(&account.data)?; + decoded_accounts.push(crate::shared::MaybeAccount::Exists( + crate::shared::DecodedAccount { + address, + account: account.clone(), + data, + }, + )); + } else { + decoded_accounts.push(crate::shared::MaybeAccount::NotFound(address)); + } + } + Ok(decoded_accounts) +} + +#[cfg(feature = "anchor")] +impl anchor_lang::AccountDeserialize for PoolState { + fn try_deserialize_unchecked(buf: &mut &[u8]) -> anchor_lang::Result { + Ok(Self::deserialize(buf)?) + } +} + +#[cfg(feature = "anchor")] +impl anchor_lang::AccountSerialize for PoolState {} + +#[cfg(feature = "anchor")] +impl anchor_lang::Owner for PoolState { + fn owner() -> anchor_lang::solana_program::pubkey::Pubkey { + anchor_lang::solana_program::pubkey::Pubkey::from(crate::RAYDIUM_LAUNCHPAD_ID.to_bytes()) + } +} + +#[cfg(feature = "anchor-idl-build")] +impl anchor_lang::IdlBuild for PoolState {} + +#[cfg(feature = "anchor-idl-build")] +impl anchor_lang::Discriminator for PoolState { + const DISCRIMINATOR: &[u8] = &[0; 8]; +} diff --git a/e2e/raydium-launchpad/src/generated/accounts/vesting_record.rs b/e2e/raydium-launchpad/src/generated/accounts/vesting_record.rs new file mode 100644 index 0000000..5634944 --- /dev/null +++ b/e2e/raydium-launchpad/src/generated/accounts/vesting_record.rs @@ -0,0 +1,142 @@ +//! This code was AUTOGENERATED using the codama library. +//! Please DO NOT EDIT THIS FILE, instead use visitors +//! to add features, then rerun codama to update it. +//! +//! +//! + +use borsh::BorshDeserialize; +use borsh::BorshSerialize; +use solana_address::Address; + +#[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] +pub struct VestingRecord { + pub discriminator: [u8; 8], + /// Account update epoch + pub epoch: u64, + /// The pool state account + pub pool: Address, + /// The beneficiary of the vesting account + pub beneficiary: Address, + /// The amount of tokens claimed + pub claimed_amount: u64, + /// The share amount of the token to be vested + pub token_share_amount: u64, + /// padding for future updates + pub padding: [u64; 8], +} + +pub const VESTING_RECORD_DISCRIMINATOR: [u8; 8] = [106, 243, 221, 205, 230, 126, 85, 83]; + +impl VestingRecord { + pub const LEN: usize = 160; + + #[inline(always)] + pub fn from_bytes(data: &[u8]) -> Result { + let mut data = data; + Self::deserialize(&mut data) + } +} + +impl<'a> TryFrom<&solana_account_info::AccountInfo<'a>> for VestingRecord { + type Error = std::io::Error; + + fn try_from(account_info: &solana_account_info::AccountInfo<'a>) -> Result { + let mut data: &[u8] = &(*account_info.data).borrow(); + Self::deserialize(&mut data) + } +} + +#[cfg(feature = "fetch")] +pub fn fetch_vesting_record( + rpc: &solana_client::rpc_client::RpcClient, + address: &solana_address::Address, +) -> Result, std::io::Error> { + let accounts = fetch_all_vesting_record(rpc, &[*address])?; + Ok(accounts[0].clone()) +} + +#[cfg(feature = "fetch")] +pub fn fetch_all_vesting_record( + rpc: &solana_client::rpc_client::RpcClient, + addresses: &[solana_address::Address], +) -> Result>, std::io::Error> { + let accounts = rpc + .get_multiple_accounts(addresses) + .map_err(|e| std::io::Error::other(e.to_string()))?; + let mut decoded_accounts: Vec> = Vec::new(); + for i in 0..addresses.len() { + let address = addresses[i]; + let account = accounts[i].as_ref().ok_or(std::io::Error::other(format!( + "Account not found: {address}" + )))?; + let data = VestingRecord::from_bytes(&account.data)?; + decoded_accounts.push(crate::shared::DecodedAccount { + address, + account: account.clone(), + data, + }); + } + Ok(decoded_accounts) +} + +#[cfg(feature = "fetch")] +pub fn fetch_maybe_vesting_record( + rpc: &solana_client::rpc_client::RpcClient, + address: &solana_address::Address, +) -> Result, std::io::Error> { + let accounts = fetch_all_maybe_vesting_record(rpc, &[*address])?; + Ok(accounts[0].clone()) +} + +#[cfg(feature = "fetch")] +pub fn fetch_all_maybe_vesting_record( + rpc: &solana_client::rpc_client::RpcClient, + addresses: &[solana_address::Address], +) -> Result>, std::io::Error> { + let accounts = rpc + .get_multiple_accounts(addresses) + .map_err(|e| std::io::Error::other(e.to_string()))?; + let mut decoded_accounts: Vec> = Vec::new(); + for i in 0..addresses.len() { + let address = addresses[i]; + if let Some(account) = accounts[i].as_ref() { + let data = VestingRecord::from_bytes(&account.data)?; + decoded_accounts.push(crate::shared::MaybeAccount::Exists( + crate::shared::DecodedAccount { + address, + account: account.clone(), + data, + }, + )); + } else { + decoded_accounts.push(crate::shared::MaybeAccount::NotFound(address)); + } + } + Ok(decoded_accounts) +} + +#[cfg(feature = "anchor")] +impl anchor_lang::AccountDeserialize for VestingRecord { + fn try_deserialize_unchecked(buf: &mut &[u8]) -> anchor_lang::Result { + Ok(Self::deserialize(buf)?) + } +} + +#[cfg(feature = "anchor")] +impl anchor_lang::AccountSerialize for VestingRecord {} + +#[cfg(feature = "anchor")] +impl anchor_lang::Owner for VestingRecord { + fn owner() -> anchor_lang::solana_program::pubkey::Pubkey { + anchor_lang::solana_program::pubkey::Pubkey::from(crate::RAYDIUM_LAUNCHPAD_ID.to_bytes()) + } +} + +#[cfg(feature = "anchor-idl-build")] +impl anchor_lang::IdlBuild for VestingRecord {} + +#[cfg(feature = "anchor-idl-build")] +impl anchor_lang::Discriminator for VestingRecord { + const DISCRIMINATOR: &[u8] = &[0; 8]; +} diff --git a/e2e/raydium-launchpad/src/generated/errors/mod.rs b/e2e/raydium-launchpad/src/generated/errors/mod.rs new file mode 100644 index 0000000..60a45b0 --- /dev/null +++ b/e2e/raydium-launchpad/src/generated/errors/mod.rs @@ -0,0 +1,10 @@ +//! This code was AUTOGENERATED using the codama library. +//! Please DO NOT EDIT THIS FILE, instead use visitors +//! to add features, then rerun codama to update it. +//! +//! +//! + +pub(crate) mod raydium_launchpad; + +pub use self::raydium_launchpad::RaydiumLaunchpadError; diff --git a/e2e/raydium-launchpad/src/generated/errors/raydium_launchpad.rs b/e2e/raydium-launchpad/src/generated/errors/raydium_launchpad.rs new file mode 100644 index 0000000..f57d1d3 --- /dev/null +++ b/e2e/raydium-launchpad/src/generated/errors/raydium_launchpad.rs @@ -0,0 +1,67 @@ +//! This code was AUTOGENERATED using the codama library. +//! Please DO NOT EDIT THIS FILE, instead use visitors +//! to add features, then rerun codama to update it. +//! +//! +//! + +use num_derive::FromPrimitive; +use thiserror::Error; + +#[derive(Clone, Debug, Eq, Error, FromPrimitive, PartialEq)] +pub enum RaydiumLaunchpadError { + /// 6000 - Not approved + #[error("Not approved")] + NotApproved = 0x1770, + /// 6001 - Input account owner is not the program address + #[error("Input account owner is not the program address")] + InvalidOwner = 0x1771, + /// 6002 - InvalidInput + #[error("InvalidInput")] + InvalidInput = 0x1772, + /// 6003 - The input params are not match with curve type in config + #[error("The input params are not match with curve type in config")] + InputNotMatchCurveConfig = 0x1773, + /// 6004 - Exceeds desired slippage limit + #[error("Exceeds desired slippage limit")] + ExceededSlippage = 0x1774, + /// 6005 - Pool funding + #[error("Pool funding")] + PoolFunding = 0x1775, + /// 6006 - Pool migrated + #[error("Pool migrated")] + PoolMigrated = 0x1776, + /// 6007 - Migrate type not match + #[error("Migrate type not match")] + MigrateTypeNotMatch = 0x1777, + /// 6008 - Math overflow + #[error("Math overflow")] + MathOverflow = 0x1778, + /// 6009 - No assets to collect + #[error("No assets to collect")] + NoAssetsToCollect = 0x1779, + /// 6010 - Vesting ratio too high + #[error("Vesting ratio too high")] + VestingRatioTooHigh = 0x177A, + /// 6011 - Vesting setting ended + #[error("Vesting setting ended")] + VestingSettingEnded = 0x177B, + /// 6012 - Vesting not started + #[error("Vesting not started")] + VestingNotStarted = 0x177C, + /// 6013 - No vesting schedule + #[error("No vesting schedule")] + NoVestingSchedule = 0x177D, + /// 6014 - The platform info input is invalid + #[error("The platform info input is invalid")] + InvalidPlatformInfo = 0x177E, + /// 6015 - Pool not migrated + #[error("Pool not migrated")] + PoolNotMigrated = 0x177F, +} + +impl From for solana_program_error::ProgramError { + fn from(e: RaydiumLaunchpadError) -> Self { + solana_program_error::ProgramError::Custom(e as u32) + } +} diff --git a/e2e/raydium-launchpad/src/generated/instructions/buy_exact_in.rs b/e2e/raydium-launchpad/src/generated/instructions/buy_exact_in.rs new file mode 100644 index 0000000..b075328 --- /dev/null +++ b/e2e/raydium-launchpad/src/generated/instructions/buy_exact_in.rs @@ -0,0 +1,980 @@ +//! This code was AUTOGENERATED using the codama library. +//! Please DO NOT EDIT THIS FILE, instead use visitors +//! to add features, then rerun codama to update it. +//! +//! +//! + +use borsh::BorshDeserialize; +use borsh::BorshSerialize; + +pub const BUY_EXACT_IN_DISCRIMINATOR: [u8; 8] = [250, 234, 13, 123, 213, 156, 19, 236]; + +/// Accounts. +#[derive(Debug)] +pub struct BuyExactIn { + /// The user performing the swap operation + /// Must sign the transaction and pay for fees + pub payer: solana_address::Address, + /// PDA that acts as the authority for pool vault operations + /// Generated using AUTH_SEED + pub authority: solana_address::Address, + /// Global configuration account containing protocol-wide settings + /// Used to read protocol fee rates and curve type + pub global_config: solana_address::Address, + /// Platform configuration account containing platform-wide settings + /// Used to read platform fee rate + pub platform_config: solana_address::Address, + /// The pool state account where the swap will be performed + /// Contains current pool parameters and balances + pub pool_state: solana_address::Address, + /// The user's token account for base tokens (tokens being bought) + /// Will receive the output tokens after the swap + pub user_base_token: solana_address::Address, + /// The user's token account for quote tokens (tokens being sold) + /// Will be debited for the input amount + pub user_quote_token: solana_address::Address, + /// The pool's vault for base tokens + /// Will be debited to send tokens to the user + pub base_vault: solana_address::Address, + /// The pool's vault for quote tokens + /// Will receive the input tokens from the user + pub quote_vault: solana_address::Address, + /// The mint of the base token + /// Used for transfer fee calculations if applicable + pub base_token_mint: solana_address::Address, + /// The mint of the quote token + pub quote_token_mint: solana_address::Address, + /// SPL Token program for base token transfers + pub base_token_program: solana_address::Address, + /// SPL Token program for quote token transfers + pub quote_token_program: solana_address::Address, + + pub event_authority: solana_address::Address, + + pub program: solana_address::Address, +} + +impl BuyExactIn { + pub fn instruction(&self, args: BuyExactInInstructionArgs) -> solana_instruction::Instruction { + self.instruction_with_remaining_accounts(args, &[]) + } + #[allow(clippy::arithmetic_side_effects)] + #[allow(clippy::vec_init_then_push)] + pub fn instruction_with_remaining_accounts( + &self, + args: BuyExactInInstructionArgs, + remaining_accounts: &[solana_instruction::AccountMeta], + ) -> solana_instruction::Instruction { + let mut accounts = Vec::with_capacity(15 + remaining_accounts.len()); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.payer, true, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.authority, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.global_config, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.platform_config, + false, + )); + accounts.push(solana_instruction::AccountMeta::new(self.pool_state, false)); + accounts.push(solana_instruction::AccountMeta::new( + self.user_base_token, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + self.user_quote_token, + false, + )); + accounts.push(solana_instruction::AccountMeta::new(self.base_vault, false)); + accounts.push(solana_instruction::AccountMeta::new( + self.quote_vault, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.base_token_mint, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.quote_token_mint, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.base_token_program, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.quote_token_program, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.event_authority, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.program, + false, + )); + accounts.extend_from_slice(remaining_accounts); + let mut data = BuyExactInInstructionData::new().try_to_vec().unwrap(); + let mut args = args.try_to_vec().unwrap(); + data.append(&mut args); + + solana_instruction::Instruction { + program_id: crate::RAYDIUM_LAUNCHPAD_ID, + accounts, + data, + } + } +} + +#[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] +pub struct BuyExactInInstructionData { + discriminator: [u8; 8], +} + +impl BuyExactInInstructionData { + pub fn new() -> Self { + Self { + discriminator: [250, 234, 13, 123, 213, 156, 19, 236], + } + } + + pub(crate) fn try_to_vec(&self) -> Result, std::io::Error> { + borsh::to_vec(self) + } +} + +impl Default for BuyExactInInstructionData { + fn default() -> Self { + Self::new() + } +} + +#[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] +pub struct BuyExactInInstructionArgs { + pub amount_in: u64, + pub minimum_amount_out: u64, + pub share_fee_rate: u64, +} + +impl BuyExactInInstructionArgs { + pub(crate) fn try_to_vec(&self) -> Result, std::io::Error> { + borsh::to_vec(self) + } +} + +/// Instruction builder for `BuyExactIn`. +/// +/// ### Accounts: +/// +/// 0. `[signer]` payer +/// 1. `[]` authority +/// 2. `[]` global_config +/// 3. `[]` platform_config +/// 4. `[writable]` pool_state +/// 5. `[writable]` user_base_token +/// 6. `[writable]` user_quote_token +/// 7. `[writable]` base_vault +/// 8. `[writable]` quote_vault +/// 9. `[]` base_token_mint +/// 10. `[]` quote_token_mint +/// 11. `[]` base_token_program +/// 12. `[optional]` quote_token_program (default to `TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA`) +/// 13. `[]` event_authority +/// 14. `[]` program +#[derive(Clone, Debug, Default)] +pub struct BuyExactInBuilder { + payer: Option, + authority: Option, + global_config: Option, + platform_config: Option, + pool_state: Option, + user_base_token: Option, + user_quote_token: Option, + base_vault: Option, + quote_vault: Option, + base_token_mint: Option, + quote_token_mint: Option, + base_token_program: Option, + quote_token_program: Option, + event_authority: Option, + program: Option, + amount_in: Option, + minimum_amount_out: Option, + share_fee_rate: Option, + __remaining_accounts: Vec, +} + +impl BuyExactInBuilder { + pub fn new() -> Self { + Self::default() + } + /// The user performing the swap operation + /// Must sign the transaction and pay for fees + #[inline(always)] + pub fn payer(&mut self, payer: solana_address::Address) -> &mut Self { + self.payer = Some(payer); + self + } + /// PDA that acts as the authority for pool vault operations + /// Generated using AUTH_SEED + #[inline(always)] + pub fn authority(&mut self, authority: solana_address::Address) -> &mut Self { + self.authority = Some(authority); + self + } + /// Global configuration account containing protocol-wide settings + /// Used to read protocol fee rates and curve type + #[inline(always)] + pub fn global_config(&mut self, global_config: solana_address::Address) -> &mut Self { + self.global_config = Some(global_config); + self + } + /// Platform configuration account containing platform-wide settings + /// Used to read platform fee rate + #[inline(always)] + pub fn platform_config(&mut self, platform_config: solana_address::Address) -> &mut Self { + self.platform_config = Some(platform_config); + self + } + /// The pool state account where the swap will be performed + /// Contains current pool parameters and balances + #[inline(always)] + pub fn pool_state(&mut self, pool_state: solana_address::Address) -> &mut Self { + self.pool_state = Some(pool_state); + self + } + /// The user's token account for base tokens (tokens being bought) + /// Will receive the output tokens after the swap + #[inline(always)] + pub fn user_base_token(&mut self, user_base_token: solana_address::Address) -> &mut Self { + self.user_base_token = Some(user_base_token); + self + } + /// The user's token account for quote tokens (tokens being sold) + /// Will be debited for the input amount + #[inline(always)] + pub fn user_quote_token(&mut self, user_quote_token: solana_address::Address) -> &mut Self { + self.user_quote_token = Some(user_quote_token); + self + } + /// The pool's vault for base tokens + /// Will be debited to send tokens to the user + #[inline(always)] + pub fn base_vault(&mut self, base_vault: solana_address::Address) -> &mut Self { + self.base_vault = Some(base_vault); + self + } + /// The pool's vault for quote tokens + /// Will receive the input tokens from the user + #[inline(always)] + pub fn quote_vault(&mut self, quote_vault: solana_address::Address) -> &mut Self { + self.quote_vault = Some(quote_vault); + self + } + /// The mint of the base token + /// Used for transfer fee calculations if applicable + #[inline(always)] + pub fn base_token_mint(&mut self, base_token_mint: solana_address::Address) -> &mut Self { + self.base_token_mint = Some(base_token_mint); + self + } + /// The mint of the quote token + #[inline(always)] + pub fn quote_token_mint(&mut self, quote_token_mint: solana_address::Address) -> &mut Self { + self.quote_token_mint = Some(quote_token_mint); + self + } + /// SPL Token program for base token transfers + #[inline(always)] + pub fn base_token_program(&mut self, base_token_program: solana_address::Address) -> &mut Self { + self.base_token_program = Some(base_token_program); + self + } + /// `[optional account, default to 'TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA']` + /// SPL Token program for quote token transfers + #[inline(always)] + pub fn quote_token_program( + &mut self, + quote_token_program: solana_address::Address, + ) -> &mut Self { + self.quote_token_program = Some(quote_token_program); + self + } + #[inline(always)] + pub fn event_authority(&mut self, event_authority: solana_address::Address) -> &mut Self { + self.event_authority = Some(event_authority); + self + } + #[inline(always)] + pub fn program(&mut self, program: solana_address::Address) -> &mut Self { + self.program = Some(program); + self + } + #[inline(always)] + pub fn amount_in(&mut self, amount_in: u64) -> &mut Self { + self.amount_in = Some(amount_in); + self + } + #[inline(always)] + pub fn minimum_amount_out(&mut self, minimum_amount_out: u64) -> &mut Self { + self.minimum_amount_out = Some(minimum_amount_out); + self + } + #[inline(always)] + pub fn share_fee_rate(&mut self, share_fee_rate: u64) -> &mut Self { + self.share_fee_rate = Some(share_fee_rate); + self + } + /// Add an additional account to the instruction. + #[inline(always)] + pub fn add_remaining_account(&mut self, account: solana_instruction::AccountMeta) -> &mut Self { + self.__remaining_accounts.push(account); + self + } + /// Add additional accounts to the instruction. + #[inline(always)] + pub fn add_remaining_accounts( + &mut self, + accounts: &[solana_instruction::AccountMeta], + ) -> &mut Self { + self.__remaining_accounts.extend_from_slice(accounts); + self + } + #[allow(clippy::clone_on_copy)] + pub fn instruction(&self) -> solana_instruction::Instruction { + let accounts = BuyExactIn { + payer: self.payer.expect("payer is not set"), + authority: self.authority.expect("authority is not set"), + global_config: self.global_config.expect("global_config is not set"), + platform_config: self.platform_config.expect("platform_config is not set"), + pool_state: self.pool_state.expect("pool_state is not set"), + user_base_token: self.user_base_token.expect("user_base_token is not set"), + user_quote_token: self.user_quote_token.expect("user_quote_token is not set"), + base_vault: self.base_vault.expect("base_vault is not set"), + quote_vault: self.quote_vault.expect("quote_vault is not set"), + base_token_mint: self.base_token_mint.expect("base_token_mint is not set"), + quote_token_mint: self.quote_token_mint.expect("quote_token_mint is not set"), + base_token_program: self + .base_token_program + .expect("base_token_program is not set"), + quote_token_program: self.quote_token_program.unwrap_or(solana_address::address!( + "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA" + )), + event_authority: self.event_authority.expect("event_authority is not set"), + program: self.program.expect("program is not set"), + }; + let args = BuyExactInInstructionArgs { + amount_in: self.amount_in.clone().expect("amount_in is not set"), + minimum_amount_out: self + .minimum_amount_out + .clone() + .expect("minimum_amount_out is not set"), + share_fee_rate: self + .share_fee_rate + .clone() + .expect("share_fee_rate is not set"), + }; + + accounts.instruction_with_remaining_accounts(args, &self.__remaining_accounts) + } +} + +/// `buy_exact_in` CPI accounts. +pub struct BuyExactInCpiAccounts<'a, 'b> { + /// The user performing the swap operation + /// Must sign the transaction and pay for fees + pub payer: &'b solana_account_info::AccountInfo<'a>, + /// PDA that acts as the authority for pool vault operations + /// Generated using AUTH_SEED + pub authority: &'b solana_account_info::AccountInfo<'a>, + /// Global configuration account containing protocol-wide settings + /// Used to read protocol fee rates and curve type + pub global_config: &'b solana_account_info::AccountInfo<'a>, + /// Platform configuration account containing platform-wide settings + /// Used to read platform fee rate + pub platform_config: &'b solana_account_info::AccountInfo<'a>, + /// The pool state account where the swap will be performed + /// Contains current pool parameters and balances + pub pool_state: &'b solana_account_info::AccountInfo<'a>, + /// The user's token account for base tokens (tokens being bought) + /// Will receive the output tokens after the swap + pub user_base_token: &'b solana_account_info::AccountInfo<'a>, + /// The user's token account for quote tokens (tokens being sold) + /// Will be debited for the input amount + pub user_quote_token: &'b solana_account_info::AccountInfo<'a>, + /// The pool's vault for base tokens + /// Will be debited to send tokens to the user + pub base_vault: &'b solana_account_info::AccountInfo<'a>, + /// The pool's vault for quote tokens + /// Will receive the input tokens from the user + pub quote_vault: &'b solana_account_info::AccountInfo<'a>, + /// The mint of the base token + /// Used for transfer fee calculations if applicable + pub base_token_mint: &'b solana_account_info::AccountInfo<'a>, + /// The mint of the quote token + pub quote_token_mint: &'b solana_account_info::AccountInfo<'a>, + /// SPL Token program for base token transfers + pub base_token_program: &'b solana_account_info::AccountInfo<'a>, + /// SPL Token program for quote token transfers + pub quote_token_program: &'b solana_account_info::AccountInfo<'a>, + + pub event_authority: &'b solana_account_info::AccountInfo<'a>, + + pub program: &'b solana_account_info::AccountInfo<'a>, +} + +/// `buy_exact_in` CPI instruction. +pub struct BuyExactInCpi<'a, 'b> { + /// The program to invoke. + pub __program: &'b solana_account_info::AccountInfo<'a>, + /// The user performing the swap operation + /// Must sign the transaction and pay for fees + pub payer: &'b solana_account_info::AccountInfo<'a>, + /// PDA that acts as the authority for pool vault operations + /// Generated using AUTH_SEED + pub authority: &'b solana_account_info::AccountInfo<'a>, + /// Global configuration account containing protocol-wide settings + /// Used to read protocol fee rates and curve type + pub global_config: &'b solana_account_info::AccountInfo<'a>, + /// Platform configuration account containing platform-wide settings + /// Used to read platform fee rate + pub platform_config: &'b solana_account_info::AccountInfo<'a>, + /// The pool state account where the swap will be performed + /// Contains current pool parameters and balances + pub pool_state: &'b solana_account_info::AccountInfo<'a>, + /// The user's token account for base tokens (tokens being bought) + /// Will receive the output tokens after the swap + pub user_base_token: &'b solana_account_info::AccountInfo<'a>, + /// The user's token account for quote tokens (tokens being sold) + /// Will be debited for the input amount + pub user_quote_token: &'b solana_account_info::AccountInfo<'a>, + /// The pool's vault for base tokens + /// Will be debited to send tokens to the user + pub base_vault: &'b solana_account_info::AccountInfo<'a>, + /// The pool's vault for quote tokens + /// Will receive the input tokens from the user + pub quote_vault: &'b solana_account_info::AccountInfo<'a>, + /// The mint of the base token + /// Used for transfer fee calculations if applicable + pub base_token_mint: &'b solana_account_info::AccountInfo<'a>, + /// The mint of the quote token + pub quote_token_mint: &'b solana_account_info::AccountInfo<'a>, + /// SPL Token program for base token transfers + pub base_token_program: &'b solana_account_info::AccountInfo<'a>, + /// SPL Token program for quote token transfers + pub quote_token_program: &'b solana_account_info::AccountInfo<'a>, + + pub event_authority: &'b solana_account_info::AccountInfo<'a>, + + pub program: &'b solana_account_info::AccountInfo<'a>, + /// The arguments for the instruction. + pub __args: BuyExactInInstructionArgs, +} + +impl<'a, 'b> BuyExactInCpi<'a, 'b> { + pub fn new( + program: &'b solana_account_info::AccountInfo<'a>, + accounts: BuyExactInCpiAccounts<'a, 'b>, + args: BuyExactInInstructionArgs, + ) -> Self { + Self { + __program: program, + payer: accounts.payer, + authority: accounts.authority, + global_config: accounts.global_config, + platform_config: accounts.platform_config, + pool_state: accounts.pool_state, + user_base_token: accounts.user_base_token, + user_quote_token: accounts.user_quote_token, + base_vault: accounts.base_vault, + quote_vault: accounts.quote_vault, + base_token_mint: accounts.base_token_mint, + quote_token_mint: accounts.quote_token_mint, + base_token_program: accounts.base_token_program, + quote_token_program: accounts.quote_token_program, + event_authority: accounts.event_authority, + program: accounts.program, + __args: args, + } + } + #[inline(always)] + pub fn invoke(&self) -> solana_program_error::ProgramResult { + self.invoke_signed_with_remaining_accounts(&[], &[]) + } + #[inline(always)] + pub fn invoke_with_remaining_accounts( + &self, + remaining_accounts: &[(&'b solana_account_info::AccountInfo<'a>, bool, bool)], + ) -> solana_program_error::ProgramResult { + self.invoke_signed_with_remaining_accounts(&[], remaining_accounts) + } + #[inline(always)] + pub fn invoke_signed(&self, signers_seeds: &[&[&[u8]]]) -> solana_program_error::ProgramResult { + self.invoke_signed_with_remaining_accounts(signers_seeds, &[]) + } + #[allow(clippy::arithmetic_side_effects)] + #[allow(clippy::clone_on_copy)] + #[allow(clippy::vec_init_then_push)] + pub fn invoke_signed_with_remaining_accounts( + &self, + signers_seeds: &[&[&[u8]]], + remaining_accounts: &[(&'b solana_account_info::AccountInfo<'a>, bool, bool)], + ) -> solana_program_error::ProgramResult { + let mut accounts = Vec::with_capacity(15 + remaining_accounts.len()); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.payer.key, + true, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.authority.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.global_config.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.platform_config.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + *self.pool_state.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + *self.user_base_token.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + *self.user_quote_token.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + *self.base_vault.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + *self.quote_vault.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.base_token_mint.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.quote_token_mint.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.base_token_program.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.quote_token_program.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.event_authority.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.program.key, + false, + )); + remaining_accounts.iter().for_each(|remaining_account| { + accounts.push(solana_instruction::AccountMeta { + pubkey: *remaining_account.0.key, + is_signer: remaining_account.1, + is_writable: remaining_account.2, + }) + }); + let mut data = BuyExactInInstructionData::new().try_to_vec().unwrap(); + let mut args = self.__args.try_to_vec().unwrap(); + data.append(&mut args); + + let instruction = solana_instruction::Instruction { + program_id: crate::RAYDIUM_LAUNCHPAD_ID, + accounts, + data, + }; + let mut account_infos = Vec::with_capacity(16 + remaining_accounts.len()); + account_infos.push(self.__program.clone()); + account_infos.push(self.payer.clone()); + account_infos.push(self.authority.clone()); + account_infos.push(self.global_config.clone()); + account_infos.push(self.platform_config.clone()); + account_infos.push(self.pool_state.clone()); + account_infos.push(self.user_base_token.clone()); + account_infos.push(self.user_quote_token.clone()); + account_infos.push(self.base_vault.clone()); + account_infos.push(self.quote_vault.clone()); + account_infos.push(self.base_token_mint.clone()); + account_infos.push(self.quote_token_mint.clone()); + account_infos.push(self.base_token_program.clone()); + account_infos.push(self.quote_token_program.clone()); + account_infos.push(self.event_authority.clone()); + account_infos.push(self.program.clone()); + remaining_accounts + .iter() + .for_each(|remaining_account| account_infos.push(remaining_account.0.clone())); + + if signers_seeds.is_empty() { + solana_cpi::invoke(&instruction, &account_infos) + } else { + solana_cpi::invoke_signed(&instruction, &account_infos, signers_seeds) + } + } +} + +/// Instruction builder for `BuyExactIn` via CPI. +/// +/// ### Accounts: +/// +/// 0. `[signer]` payer +/// 1. `[]` authority +/// 2. `[]` global_config +/// 3. `[]` platform_config +/// 4. `[writable]` pool_state +/// 5. `[writable]` user_base_token +/// 6. `[writable]` user_quote_token +/// 7. `[writable]` base_vault +/// 8. `[writable]` quote_vault +/// 9. `[]` base_token_mint +/// 10. `[]` quote_token_mint +/// 11. `[]` base_token_program +/// 12. `[]` quote_token_program +/// 13. `[]` event_authority +/// 14. `[]` program +#[derive(Clone, Debug)] +pub struct BuyExactInCpiBuilder<'a, 'b> { + instruction: Box>, +} + +impl<'a, 'b> BuyExactInCpiBuilder<'a, 'b> { + pub fn new(program: &'b solana_account_info::AccountInfo<'a>) -> Self { + let instruction = Box::new(BuyExactInCpiBuilderInstruction { + __program: program, + payer: None, + authority: None, + global_config: None, + platform_config: None, + pool_state: None, + user_base_token: None, + user_quote_token: None, + base_vault: None, + quote_vault: None, + base_token_mint: None, + quote_token_mint: None, + base_token_program: None, + quote_token_program: None, + event_authority: None, + program: None, + amount_in: None, + minimum_amount_out: None, + share_fee_rate: None, + __remaining_accounts: Vec::new(), + }); + Self { instruction } + } + /// The user performing the swap operation + /// Must sign the transaction and pay for fees + #[inline(always)] + pub fn payer(&mut self, payer: &'b solana_account_info::AccountInfo<'a>) -> &mut Self { + self.instruction.payer = Some(payer); + self + } + /// PDA that acts as the authority for pool vault operations + /// Generated using AUTH_SEED + #[inline(always)] + pub fn authority(&mut self, authority: &'b solana_account_info::AccountInfo<'a>) -> &mut Self { + self.instruction.authority = Some(authority); + self + } + /// Global configuration account containing protocol-wide settings + /// Used to read protocol fee rates and curve type + #[inline(always)] + pub fn global_config( + &mut self, + global_config: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.global_config = Some(global_config); + self + } + /// Platform configuration account containing platform-wide settings + /// Used to read platform fee rate + #[inline(always)] + pub fn platform_config( + &mut self, + platform_config: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.platform_config = Some(platform_config); + self + } + /// The pool state account where the swap will be performed + /// Contains current pool parameters and balances + #[inline(always)] + pub fn pool_state( + &mut self, + pool_state: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.pool_state = Some(pool_state); + self + } + /// The user's token account for base tokens (tokens being bought) + /// Will receive the output tokens after the swap + #[inline(always)] + pub fn user_base_token( + &mut self, + user_base_token: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.user_base_token = Some(user_base_token); + self + } + /// The user's token account for quote tokens (tokens being sold) + /// Will be debited for the input amount + #[inline(always)] + pub fn user_quote_token( + &mut self, + user_quote_token: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.user_quote_token = Some(user_quote_token); + self + } + /// The pool's vault for base tokens + /// Will be debited to send tokens to the user + #[inline(always)] + pub fn base_vault( + &mut self, + base_vault: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.base_vault = Some(base_vault); + self + } + /// The pool's vault for quote tokens + /// Will receive the input tokens from the user + #[inline(always)] + pub fn quote_vault( + &mut self, + quote_vault: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.quote_vault = Some(quote_vault); + self + } + /// The mint of the base token + /// Used for transfer fee calculations if applicable + #[inline(always)] + pub fn base_token_mint( + &mut self, + base_token_mint: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.base_token_mint = Some(base_token_mint); + self + } + /// The mint of the quote token + #[inline(always)] + pub fn quote_token_mint( + &mut self, + quote_token_mint: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.quote_token_mint = Some(quote_token_mint); + self + } + /// SPL Token program for base token transfers + #[inline(always)] + pub fn base_token_program( + &mut self, + base_token_program: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.base_token_program = Some(base_token_program); + self + } + /// SPL Token program for quote token transfers + #[inline(always)] + pub fn quote_token_program( + &mut self, + quote_token_program: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.quote_token_program = Some(quote_token_program); + self + } + #[inline(always)] + pub fn event_authority( + &mut self, + event_authority: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.event_authority = Some(event_authority); + self + } + #[inline(always)] + pub fn program(&mut self, program: &'b solana_account_info::AccountInfo<'a>) -> &mut Self { + self.instruction.program = Some(program); + self + } + #[inline(always)] + pub fn amount_in(&mut self, amount_in: u64) -> &mut Self { + self.instruction.amount_in = Some(amount_in); + self + } + #[inline(always)] + pub fn minimum_amount_out(&mut self, minimum_amount_out: u64) -> &mut Self { + self.instruction.minimum_amount_out = Some(minimum_amount_out); + self + } + #[inline(always)] + pub fn share_fee_rate(&mut self, share_fee_rate: u64) -> &mut Self { + self.instruction.share_fee_rate = Some(share_fee_rate); + self + } + /// Add an additional account to the instruction. + #[inline(always)] + pub fn add_remaining_account( + &mut self, + account: &'b solana_account_info::AccountInfo<'a>, + is_writable: bool, + is_signer: bool, + ) -> &mut Self { + self.instruction + .__remaining_accounts + .push((account, is_writable, is_signer)); + self + } + /// Add additional accounts to the instruction. + /// + /// Each account is represented by a tuple of the `AccountInfo`, a `bool` indicating whether the account is writable or not, + /// and a `bool` indicating whether the account is a signer or not. + #[inline(always)] + pub fn add_remaining_accounts( + &mut self, + accounts: &[(&'b solana_account_info::AccountInfo<'a>, bool, bool)], + ) -> &mut Self { + self.instruction + .__remaining_accounts + .extend_from_slice(accounts); + self + } + #[inline(always)] + pub fn invoke(&self) -> solana_program_error::ProgramResult { + self.invoke_signed(&[]) + } + #[allow(clippy::clone_on_copy)] + #[allow(clippy::vec_init_then_push)] + pub fn invoke_signed(&self, signers_seeds: &[&[&[u8]]]) -> solana_program_error::ProgramResult { + let args = BuyExactInInstructionArgs { + amount_in: self + .instruction + .amount_in + .clone() + .expect("amount_in is not set"), + minimum_amount_out: self + .instruction + .minimum_amount_out + .clone() + .expect("minimum_amount_out is not set"), + share_fee_rate: self + .instruction + .share_fee_rate + .clone() + .expect("share_fee_rate is not set"), + }; + let instruction = BuyExactInCpi { + __program: self.instruction.__program, + + payer: self.instruction.payer.expect("payer is not set"), + + authority: self.instruction.authority.expect("authority is not set"), + + global_config: self + .instruction + .global_config + .expect("global_config is not set"), + + platform_config: self + .instruction + .platform_config + .expect("platform_config is not set"), + + pool_state: self.instruction.pool_state.expect("pool_state is not set"), + + user_base_token: self + .instruction + .user_base_token + .expect("user_base_token is not set"), + + user_quote_token: self + .instruction + .user_quote_token + .expect("user_quote_token is not set"), + + base_vault: self.instruction.base_vault.expect("base_vault is not set"), + + quote_vault: self + .instruction + .quote_vault + .expect("quote_vault is not set"), + + base_token_mint: self + .instruction + .base_token_mint + .expect("base_token_mint is not set"), + + quote_token_mint: self + .instruction + .quote_token_mint + .expect("quote_token_mint is not set"), + + base_token_program: self + .instruction + .base_token_program + .expect("base_token_program is not set"), + + quote_token_program: self + .instruction + .quote_token_program + .expect("quote_token_program is not set"), + + event_authority: self + .instruction + .event_authority + .expect("event_authority is not set"), + + program: self.instruction.program.expect("program is not set"), + __args: args, + }; + instruction.invoke_signed_with_remaining_accounts( + signers_seeds, + &self.instruction.__remaining_accounts, + ) + } +} + +#[derive(Clone, Debug)] +struct BuyExactInCpiBuilderInstruction<'a, 'b> { + __program: &'b solana_account_info::AccountInfo<'a>, + payer: Option<&'b solana_account_info::AccountInfo<'a>>, + authority: Option<&'b solana_account_info::AccountInfo<'a>>, + global_config: Option<&'b solana_account_info::AccountInfo<'a>>, + platform_config: Option<&'b solana_account_info::AccountInfo<'a>>, + pool_state: Option<&'b solana_account_info::AccountInfo<'a>>, + user_base_token: Option<&'b solana_account_info::AccountInfo<'a>>, + user_quote_token: Option<&'b solana_account_info::AccountInfo<'a>>, + base_vault: Option<&'b solana_account_info::AccountInfo<'a>>, + quote_vault: Option<&'b solana_account_info::AccountInfo<'a>>, + base_token_mint: Option<&'b solana_account_info::AccountInfo<'a>>, + quote_token_mint: Option<&'b solana_account_info::AccountInfo<'a>>, + base_token_program: Option<&'b solana_account_info::AccountInfo<'a>>, + quote_token_program: Option<&'b solana_account_info::AccountInfo<'a>>, + event_authority: Option<&'b solana_account_info::AccountInfo<'a>>, + program: Option<&'b solana_account_info::AccountInfo<'a>>, + amount_in: Option, + minimum_amount_out: Option, + share_fee_rate: Option, + /// Additional instruction accounts `(AccountInfo, is_writable, is_signer)`. + __remaining_accounts: Vec<(&'b solana_account_info::AccountInfo<'a>, bool, bool)>, +} diff --git a/e2e/raydium-launchpad/src/generated/instructions/buy_exact_out.rs b/e2e/raydium-launchpad/src/generated/instructions/buy_exact_out.rs new file mode 100644 index 0000000..cc902f2 --- /dev/null +++ b/e2e/raydium-launchpad/src/generated/instructions/buy_exact_out.rs @@ -0,0 +1,980 @@ +//! This code was AUTOGENERATED using the codama library. +//! Please DO NOT EDIT THIS FILE, instead use visitors +//! to add features, then rerun codama to update it. +//! +//! +//! + +use borsh::BorshDeserialize; +use borsh::BorshSerialize; + +pub const BUY_EXACT_OUT_DISCRIMINATOR: [u8; 8] = [24, 211, 116, 40, 105, 3, 153, 56]; + +/// Accounts. +#[derive(Debug)] +pub struct BuyExactOut { + /// The user performing the swap operation + /// Must sign the transaction and pay for fees + pub payer: solana_address::Address, + /// PDA that acts as the authority for pool vault operations + /// Generated using AUTH_SEED + pub authority: solana_address::Address, + /// Global configuration account containing protocol-wide settings + /// Used to read protocol fee rates and curve type + pub global_config: solana_address::Address, + /// Platform configuration account containing platform-wide settings + /// Used to read platform fee rate + pub platform_config: solana_address::Address, + /// The pool state account where the swap will be performed + /// Contains current pool parameters and balances + pub pool_state: solana_address::Address, + /// The user's token account for base tokens (tokens being bought) + /// Will receive the output tokens after the swap + pub user_base_token: solana_address::Address, + /// The user's token account for quote tokens (tokens being sold) + /// Will be debited for the input amount + pub user_quote_token: solana_address::Address, + /// The pool's vault for base tokens + /// Will be debited to send tokens to the user + pub base_vault: solana_address::Address, + /// The pool's vault for quote tokens + /// Will receive the input tokens from the user + pub quote_vault: solana_address::Address, + /// The mint of the base token + /// Used for transfer fee calculations if applicable + pub base_token_mint: solana_address::Address, + /// The mint of the quote token + pub quote_token_mint: solana_address::Address, + /// SPL Token program for base token transfers + pub base_token_program: solana_address::Address, + /// SPL Token program for quote token transfers + pub quote_token_program: solana_address::Address, + + pub event_authority: solana_address::Address, + + pub program: solana_address::Address, +} + +impl BuyExactOut { + pub fn instruction(&self, args: BuyExactOutInstructionArgs) -> solana_instruction::Instruction { + self.instruction_with_remaining_accounts(args, &[]) + } + #[allow(clippy::arithmetic_side_effects)] + #[allow(clippy::vec_init_then_push)] + pub fn instruction_with_remaining_accounts( + &self, + args: BuyExactOutInstructionArgs, + remaining_accounts: &[solana_instruction::AccountMeta], + ) -> solana_instruction::Instruction { + let mut accounts = Vec::with_capacity(15 + remaining_accounts.len()); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.payer, true, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.authority, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.global_config, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.platform_config, + false, + )); + accounts.push(solana_instruction::AccountMeta::new(self.pool_state, false)); + accounts.push(solana_instruction::AccountMeta::new( + self.user_base_token, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + self.user_quote_token, + false, + )); + accounts.push(solana_instruction::AccountMeta::new(self.base_vault, false)); + accounts.push(solana_instruction::AccountMeta::new( + self.quote_vault, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.base_token_mint, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.quote_token_mint, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.base_token_program, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.quote_token_program, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.event_authority, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.program, + false, + )); + accounts.extend_from_slice(remaining_accounts); + let mut data = BuyExactOutInstructionData::new().try_to_vec().unwrap(); + let mut args = args.try_to_vec().unwrap(); + data.append(&mut args); + + solana_instruction::Instruction { + program_id: crate::RAYDIUM_LAUNCHPAD_ID, + accounts, + data, + } + } +} + +#[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] +pub struct BuyExactOutInstructionData { + discriminator: [u8; 8], +} + +impl BuyExactOutInstructionData { + pub fn new() -> Self { + Self { + discriminator: [24, 211, 116, 40, 105, 3, 153, 56], + } + } + + pub(crate) fn try_to_vec(&self) -> Result, std::io::Error> { + borsh::to_vec(self) + } +} + +impl Default for BuyExactOutInstructionData { + fn default() -> Self { + Self::new() + } +} + +#[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] +pub struct BuyExactOutInstructionArgs { + pub amount_out: u64, + pub maximum_amount_in: u64, + pub share_fee_rate: u64, +} + +impl BuyExactOutInstructionArgs { + pub(crate) fn try_to_vec(&self) -> Result, std::io::Error> { + borsh::to_vec(self) + } +} + +/// Instruction builder for `BuyExactOut`. +/// +/// ### Accounts: +/// +/// 0. `[signer]` payer +/// 1. `[]` authority +/// 2. `[]` global_config +/// 3. `[]` platform_config +/// 4. `[writable]` pool_state +/// 5. `[writable]` user_base_token +/// 6. `[writable]` user_quote_token +/// 7. `[writable]` base_vault +/// 8. `[writable]` quote_vault +/// 9. `[]` base_token_mint +/// 10. `[]` quote_token_mint +/// 11. `[]` base_token_program +/// 12. `[optional]` quote_token_program (default to `TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA`) +/// 13. `[]` event_authority +/// 14. `[]` program +#[derive(Clone, Debug, Default)] +pub struct BuyExactOutBuilder { + payer: Option, + authority: Option, + global_config: Option, + platform_config: Option, + pool_state: Option, + user_base_token: Option, + user_quote_token: Option, + base_vault: Option, + quote_vault: Option, + base_token_mint: Option, + quote_token_mint: Option, + base_token_program: Option, + quote_token_program: Option, + event_authority: Option, + program: Option, + amount_out: Option, + maximum_amount_in: Option, + share_fee_rate: Option, + __remaining_accounts: Vec, +} + +impl BuyExactOutBuilder { + pub fn new() -> Self { + Self::default() + } + /// The user performing the swap operation + /// Must sign the transaction and pay for fees + #[inline(always)] + pub fn payer(&mut self, payer: solana_address::Address) -> &mut Self { + self.payer = Some(payer); + self + } + /// PDA that acts as the authority for pool vault operations + /// Generated using AUTH_SEED + #[inline(always)] + pub fn authority(&mut self, authority: solana_address::Address) -> &mut Self { + self.authority = Some(authority); + self + } + /// Global configuration account containing protocol-wide settings + /// Used to read protocol fee rates and curve type + #[inline(always)] + pub fn global_config(&mut self, global_config: solana_address::Address) -> &mut Self { + self.global_config = Some(global_config); + self + } + /// Platform configuration account containing platform-wide settings + /// Used to read platform fee rate + #[inline(always)] + pub fn platform_config(&mut self, platform_config: solana_address::Address) -> &mut Self { + self.platform_config = Some(platform_config); + self + } + /// The pool state account where the swap will be performed + /// Contains current pool parameters and balances + #[inline(always)] + pub fn pool_state(&mut self, pool_state: solana_address::Address) -> &mut Self { + self.pool_state = Some(pool_state); + self + } + /// The user's token account for base tokens (tokens being bought) + /// Will receive the output tokens after the swap + #[inline(always)] + pub fn user_base_token(&mut self, user_base_token: solana_address::Address) -> &mut Self { + self.user_base_token = Some(user_base_token); + self + } + /// The user's token account for quote tokens (tokens being sold) + /// Will be debited for the input amount + #[inline(always)] + pub fn user_quote_token(&mut self, user_quote_token: solana_address::Address) -> &mut Self { + self.user_quote_token = Some(user_quote_token); + self + } + /// The pool's vault for base tokens + /// Will be debited to send tokens to the user + #[inline(always)] + pub fn base_vault(&mut self, base_vault: solana_address::Address) -> &mut Self { + self.base_vault = Some(base_vault); + self + } + /// The pool's vault for quote tokens + /// Will receive the input tokens from the user + #[inline(always)] + pub fn quote_vault(&mut self, quote_vault: solana_address::Address) -> &mut Self { + self.quote_vault = Some(quote_vault); + self + } + /// The mint of the base token + /// Used for transfer fee calculations if applicable + #[inline(always)] + pub fn base_token_mint(&mut self, base_token_mint: solana_address::Address) -> &mut Self { + self.base_token_mint = Some(base_token_mint); + self + } + /// The mint of the quote token + #[inline(always)] + pub fn quote_token_mint(&mut self, quote_token_mint: solana_address::Address) -> &mut Self { + self.quote_token_mint = Some(quote_token_mint); + self + } + /// SPL Token program for base token transfers + #[inline(always)] + pub fn base_token_program(&mut self, base_token_program: solana_address::Address) -> &mut Self { + self.base_token_program = Some(base_token_program); + self + } + /// `[optional account, default to 'TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA']` + /// SPL Token program for quote token transfers + #[inline(always)] + pub fn quote_token_program( + &mut self, + quote_token_program: solana_address::Address, + ) -> &mut Self { + self.quote_token_program = Some(quote_token_program); + self + } + #[inline(always)] + pub fn event_authority(&mut self, event_authority: solana_address::Address) -> &mut Self { + self.event_authority = Some(event_authority); + self + } + #[inline(always)] + pub fn program(&mut self, program: solana_address::Address) -> &mut Self { + self.program = Some(program); + self + } + #[inline(always)] + pub fn amount_out(&mut self, amount_out: u64) -> &mut Self { + self.amount_out = Some(amount_out); + self + } + #[inline(always)] + pub fn maximum_amount_in(&mut self, maximum_amount_in: u64) -> &mut Self { + self.maximum_amount_in = Some(maximum_amount_in); + self + } + #[inline(always)] + pub fn share_fee_rate(&mut self, share_fee_rate: u64) -> &mut Self { + self.share_fee_rate = Some(share_fee_rate); + self + } + /// Add an additional account to the instruction. + #[inline(always)] + pub fn add_remaining_account(&mut self, account: solana_instruction::AccountMeta) -> &mut Self { + self.__remaining_accounts.push(account); + self + } + /// Add additional accounts to the instruction. + #[inline(always)] + pub fn add_remaining_accounts( + &mut self, + accounts: &[solana_instruction::AccountMeta], + ) -> &mut Self { + self.__remaining_accounts.extend_from_slice(accounts); + self + } + #[allow(clippy::clone_on_copy)] + pub fn instruction(&self) -> solana_instruction::Instruction { + let accounts = BuyExactOut { + payer: self.payer.expect("payer is not set"), + authority: self.authority.expect("authority is not set"), + global_config: self.global_config.expect("global_config is not set"), + platform_config: self.platform_config.expect("platform_config is not set"), + pool_state: self.pool_state.expect("pool_state is not set"), + user_base_token: self.user_base_token.expect("user_base_token is not set"), + user_quote_token: self.user_quote_token.expect("user_quote_token is not set"), + base_vault: self.base_vault.expect("base_vault is not set"), + quote_vault: self.quote_vault.expect("quote_vault is not set"), + base_token_mint: self.base_token_mint.expect("base_token_mint is not set"), + quote_token_mint: self.quote_token_mint.expect("quote_token_mint is not set"), + base_token_program: self + .base_token_program + .expect("base_token_program is not set"), + quote_token_program: self.quote_token_program.unwrap_or(solana_address::address!( + "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA" + )), + event_authority: self.event_authority.expect("event_authority is not set"), + program: self.program.expect("program is not set"), + }; + let args = BuyExactOutInstructionArgs { + amount_out: self.amount_out.clone().expect("amount_out is not set"), + maximum_amount_in: self + .maximum_amount_in + .clone() + .expect("maximum_amount_in is not set"), + share_fee_rate: self + .share_fee_rate + .clone() + .expect("share_fee_rate is not set"), + }; + + accounts.instruction_with_remaining_accounts(args, &self.__remaining_accounts) + } +} + +/// `buy_exact_out` CPI accounts. +pub struct BuyExactOutCpiAccounts<'a, 'b> { + /// The user performing the swap operation + /// Must sign the transaction and pay for fees + pub payer: &'b solana_account_info::AccountInfo<'a>, + /// PDA that acts as the authority for pool vault operations + /// Generated using AUTH_SEED + pub authority: &'b solana_account_info::AccountInfo<'a>, + /// Global configuration account containing protocol-wide settings + /// Used to read protocol fee rates and curve type + pub global_config: &'b solana_account_info::AccountInfo<'a>, + /// Platform configuration account containing platform-wide settings + /// Used to read platform fee rate + pub platform_config: &'b solana_account_info::AccountInfo<'a>, + /// The pool state account where the swap will be performed + /// Contains current pool parameters and balances + pub pool_state: &'b solana_account_info::AccountInfo<'a>, + /// The user's token account for base tokens (tokens being bought) + /// Will receive the output tokens after the swap + pub user_base_token: &'b solana_account_info::AccountInfo<'a>, + /// The user's token account for quote tokens (tokens being sold) + /// Will be debited for the input amount + pub user_quote_token: &'b solana_account_info::AccountInfo<'a>, + /// The pool's vault for base tokens + /// Will be debited to send tokens to the user + pub base_vault: &'b solana_account_info::AccountInfo<'a>, + /// The pool's vault for quote tokens + /// Will receive the input tokens from the user + pub quote_vault: &'b solana_account_info::AccountInfo<'a>, + /// The mint of the base token + /// Used for transfer fee calculations if applicable + pub base_token_mint: &'b solana_account_info::AccountInfo<'a>, + /// The mint of the quote token + pub quote_token_mint: &'b solana_account_info::AccountInfo<'a>, + /// SPL Token program for base token transfers + pub base_token_program: &'b solana_account_info::AccountInfo<'a>, + /// SPL Token program for quote token transfers + pub quote_token_program: &'b solana_account_info::AccountInfo<'a>, + + pub event_authority: &'b solana_account_info::AccountInfo<'a>, + + pub program: &'b solana_account_info::AccountInfo<'a>, +} + +/// `buy_exact_out` CPI instruction. +pub struct BuyExactOutCpi<'a, 'b> { + /// The program to invoke. + pub __program: &'b solana_account_info::AccountInfo<'a>, + /// The user performing the swap operation + /// Must sign the transaction and pay for fees + pub payer: &'b solana_account_info::AccountInfo<'a>, + /// PDA that acts as the authority for pool vault operations + /// Generated using AUTH_SEED + pub authority: &'b solana_account_info::AccountInfo<'a>, + /// Global configuration account containing protocol-wide settings + /// Used to read protocol fee rates and curve type + pub global_config: &'b solana_account_info::AccountInfo<'a>, + /// Platform configuration account containing platform-wide settings + /// Used to read platform fee rate + pub platform_config: &'b solana_account_info::AccountInfo<'a>, + /// The pool state account where the swap will be performed + /// Contains current pool parameters and balances + pub pool_state: &'b solana_account_info::AccountInfo<'a>, + /// The user's token account for base tokens (tokens being bought) + /// Will receive the output tokens after the swap + pub user_base_token: &'b solana_account_info::AccountInfo<'a>, + /// The user's token account for quote tokens (tokens being sold) + /// Will be debited for the input amount + pub user_quote_token: &'b solana_account_info::AccountInfo<'a>, + /// The pool's vault for base tokens + /// Will be debited to send tokens to the user + pub base_vault: &'b solana_account_info::AccountInfo<'a>, + /// The pool's vault for quote tokens + /// Will receive the input tokens from the user + pub quote_vault: &'b solana_account_info::AccountInfo<'a>, + /// The mint of the base token + /// Used for transfer fee calculations if applicable + pub base_token_mint: &'b solana_account_info::AccountInfo<'a>, + /// The mint of the quote token + pub quote_token_mint: &'b solana_account_info::AccountInfo<'a>, + /// SPL Token program for base token transfers + pub base_token_program: &'b solana_account_info::AccountInfo<'a>, + /// SPL Token program for quote token transfers + pub quote_token_program: &'b solana_account_info::AccountInfo<'a>, + + pub event_authority: &'b solana_account_info::AccountInfo<'a>, + + pub program: &'b solana_account_info::AccountInfo<'a>, + /// The arguments for the instruction. + pub __args: BuyExactOutInstructionArgs, +} + +impl<'a, 'b> BuyExactOutCpi<'a, 'b> { + pub fn new( + program: &'b solana_account_info::AccountInfo<'a>, + accounts: BuyExactOutCpiAccounts<'a, 'b>, + args: BuyExactOutInstructionArgs, + ) -> Self { + Self { + __program: program, + payer: accounts.payer, + authority: accounts.authority, + global_config: accounts.global_config, + platform_config: accounts.platform_config, + pool_state: accounts.pool_state, + user_base_token: accounts.user_base_token, + user_quote_token: accounts.user_quote_token, + base_vault: accounts.base_vault, + quote_vault: accounts.quote_vault, + base_token_mint: accounts.base_token_mint, + quote_token_mint: accounts.quote_token_mint, + base_token_program: accounts.base_token_program, + quote_token_program: accounts.quote_token_program, + event_authority: accounts.event_authority, + program: accounts.program, + __args: args, + } + } + #[inline(always)] + pub fn invoke(&self) -> solana_program_error::ProgramResult { + self.invoke_signed_with_remaining_accounts(&[], &[]) + } + #[inline(always)] + pub fn invoke_with_remaining_accounts( + &self, + remaining_accounts: &[(&'b solana_account_info::AccountInfo<'a>, bool, bool)], + ) -> solana_program_error::ProgramResult { + self.invoke_signed_with_remaining_accounts(&[], remaining_accounts) + } + #[inline(always)] + pub fn invoke_signed(&self, signers_seeds: &[&[&[u8]]]) -> solana_program_error::ProgramResult { + self.invoke_signed_with_remaining_accounts(signers_seeds, &[]) + } + #[allow(clippy::arithmetic_side_effects)] + #[allow(clippy::clone_on_copy)] + #[allow(clippy::vec_init_then_push)] + pub fn invoke_signed_with_remaining_accounts( + &self, + signers_seeds: &[&[&[u8]]], + remaining_accounts: &[(&'b solana_account_info::AccountInfo<'a>, bool, bool)], + ) -> solana_program_error::ProgramResult { + let mut accounts = Vec::with_capacity(15 + remaining_accounts.len()); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.payer.key, + true, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.authority.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.global_config.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.platform_config.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + *self.pool_state.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + *self.user_base_token.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + *self.user_quote_token.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + *self.base_vault.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + *self.quote_vault.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.base_token_mint.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.quote_token_mint.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.base_token_program.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.quote_token_program.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.event_authority.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.program.key, + false, + )); + remaining_accounts.iter().for_each(|remaining_account| { + accounts.push(solana_instruction::AccountMeta { + pubkey: *remaining_account.0.key, + is_signer: remaining_account.1, + is_writable: remaining_account.2, + }) + }); + let mut data = BuyExactOutInstructionData::new().try_to_vec().unwrap(); + let mut args = self.__args.try_to_vec().unwrap(); + data.append(&mut args); + + let instruction = solana_instruction::Instruction { + program_id: crate::RAYDIUM_LAUNCHPAD_ID, + accounts, + data, + }; + let mut account_infos = Vec::with_capacity(16 + remaining_accounts.len()); + account_infos.push(self.__program.clone()); + account_infos.push(self.payer.clone()); + account_infos.push(self.authority.clone()); + account_infos.push(self.global_config.clone()); + account_infos.push(self.platform_config.clone()); + account_infos.push(self.pool_state.clone()); + account_infos.push(self.user_base_token.clone()); + account_infos.push(self.user_quote_token.clone()); + account_infos.push(self.base_vault.clone()); + account_infos.push(self.quote_vault.clone()); + account_infos.push(self.base_token_mint.clone()); + account_infos.push(self.quote_token_mint.clone()); + account_infos.push(self.base_token_program.clone()); + account_infos.push(self.quote_token_program.clone()); + account_infos.push(self.event_authority.clone()); + account_infos.push(self.program.clone()); + remaining_accounts + .iter() + .for_each(|remaining_account| account_infos.push(remaining_account.0.clone())); + + if signers_seeds.is_empty() { + solana_cpi::invoke(&instruction, &account_infos) + } else { + solana_cpi::invoke_signed(&instruction, &account_infos, signers_seeds) + } + } +} + +/// Instruction builder for `BuyExactOut` via CPI. +/// +/// ### Accounts: +/// +/// 0. `[signer]` payer +/// 1. `[]` authority +/// 2. `[]` global_config +/// 3. `[]` platform_config +/// 4. `[writable]` pool_state +/// 5. `[writable]` user_base_token +/// 6. `[writable]` user_quote_token +/// 7. `[writable]` base_vault +/// 8. `[writable]` quote_vault +/// 9. `[]` base_token_mint +/// 10. `[]` quote_token_mint +/// 11. `[]` base_token_program +/// 12. `[]` quote_token_program +/// 13. `[]` event_authority +/// 14. `[]` program +#[derive(Clone, Debug)] +pub struct BuyExactOutCpiBuilder<'a, 'b> { + instruction: Box>, +} + +impl<'a, 'b> BuyExactOutCpiBuilder<'a, 'b> { + pub fn new(program: &'b solana_account_info::AccountInfo<'a>) -> Self { + let instruction = Box::new(BuyExactOutCpiBuilderInstruction { + __program: program, + payer: None, + authority: None, + global_config: None, + platform_config: None, + pool_state: None, + user_base_token: None, + user_quote_token: None, + base_vault: None, + quote_vault: None, + base_token_mint: None, + quote_token_mint: None, + base_token_program: None, + quote_token_program: None, + event_authority: None, + program: None, + amount_out: None, + maximum_amount_in: None, + share_fee_rate: None, + __remaining_accounts: Vec::new(), + }); + Self { instruction } + } + /// The user performing the swap operation + /// Must sign the transaction and pay for fees + #[inline(always)] + pub fn payer(&mut self, payer: &'b solana_account_info::AccountInfo<'a>) -> &mut Self { + self.instruction.payer = Some(payer); + self + } + /// PDA that acts as the authority for pool vault operations + /// Generated using AUTH_SEED + #[inline(always)] + pub fn authority(&mut self, authority: &'b solana_account_info::AccountInfo<'a>) -> &mut Self { + self.instruction.authority = Some(authority); + self + } + /// Global configuration account containing protocol-wide settings + /// Used to read protocol fee rates and curve type + #[inline(always)] + pub fn global_config( + &mut self, + global_config: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.global_config = Some(global_config); + self + } + /// Platform configuration account containing platform-wide settings + /// Used to read platform fee rate + #[inline(always)] + pub fn platform_config( + &mut self, + platform_config: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.platform_config = Some(platform_config); + self + } + /// The pool state account where the swap will be performed + /// Contains current pool parameters and balances + #[inline(always)] + pub fn pool_state( + &mut self, + pool_state: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.pool_state = Some(pool_state); + self + } + /// The user's token account for base tokens (tokens being bought) + /// Will receive the output tokens after the swap + #[inline(always)] + pub fn user_base_token( + &mut self, + user_base_token: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.user_base_token = Some(user_base_token); + self + } + /// The user's token account for quote tokens (tokens being sold) + /// Will be debited for the input amount + #[inline(always)] + pub fn user_quote_token( + &mut self, + user_quote_token: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.user_quote_token = Some(user_quote_token); + self + } + /// The pool's vault for base tokens + /// Will be debited to send tokens to the user + #[inline(always)] + pub fn base_vault( + &mut self, + base_vault: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.base_vault = Some(base_vault); + self + } + /// The pool's vault for quote tokens + /// Will receive the input tokens from the user + #[inline(always)] + pub fn quote_vault( + &mut self, + quote_vault: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.quote_vault = Some(quote_vault); + self + } + /// The mint of the base token + /// Used for transfer fee calculations if applicable + #[inline(always)] + pub fn base_token_mint( + &mut self, + base_token_mint: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.base_token_mint = Some(base_token_mint); + self + } + /// The mint of the quote token + #[inline(always)] + pub fn quote_token_mint( + &mut self, + quote_token_mint: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.quote_token_mint = Some(quote_token_mint); + self + } + /// SPL Token program for base token transfers + #[inline(always)] + pub fn base_token_program( + &mut self, + base_token_program: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.base_token_program = Some(base_token_program); + self + } + /// SPL Token program for quote token transfers + #[inline(always)] + pub fn quote_token_program( + &mut self, + quote_token_program: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.quote_token_program = Some(quote_token_program); + self + } + #[inline(always)] + pub fn event_authority( + &mut self, + event_authority: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.event_authority = Some(event_authority); + self + } + #[inline(always)] + pub fn program(&mut self, program: &'b solana_account_info::AccountInfo<'a>) -> &mut Self { + self.instruction.program = Some(program); + self + } + #[inline(always)] + pub fn amount_out(&mut self, amount_out: u64) -> &mut Self { + self.instruction.amount_out = Some(amount_out); + self + } + #[inline(always)] + pub fn maximum_amount_in(&mut self, maximum_amount_in: u64) -> &mut Self { + self.instruction.maximum_amount_in = Some(maximum_amount_in); + self + } + #[inline(always)] + pub fn share_fee_rate(&mut self, share_fee_rate: u64) -> &mut Self { + self.instruction.share_fee_rate = Some(share_fee_rate); + self + } + /// Add an additional account to the instruction. + #[inline(always)] + pub fn add_remaining_account( + &mut self, + account: &'b solana_account_info::AccountInfo<'a>, + is_writable: bool, + is_signer: bool, + ) -> &mut Self { + self.instruction + .__remaining_accounts + .push((account, is_writable, is_signer)); + self + } + /// Add additional accounts to the instruction. + /// + /// Each account is represented by a tuple of the `AccountInfo`, a `bool` indicating whether the account is writable or not, + /// and a `bool` indicating whether the account is a signer or not. + #[inline(always)] + pub fn add_remaining_accounts( + &mut self, + accounts: &[(&'b solana_account_info::AccountInfo<'a>, bool, bool)], + ) -> &mut Self { + self.instruction + .__remaining_accounts + .extend_from_slice(accounts); + self + } + #[inline(always)] + pub fn invoke(&self) -> solana_program_error::ProgramResult { + self.invoke_signed(&[]) + } + #[allow(clippy::clone_on_copy)] + #[allow(clippy::vec_init_then_push)] + pub fn invoke_signed(&self, signers_seeds: &[&[&[u8]]]) -> solana_program_error::ProgramResult { + let args = BuyExactOutInstructionArgs { + amount_out: self + .instruction + .amount_out + .clone() + .expect("amount_out is not set"), + maximum_amount_in: self + .instruction + .maximum_amount_in + .clone() + .expect("maximum_amount_in is not set"), + share_fee_rate: self + .instruction + .share_fee_rate + .clone() + .expect("share_fee_rate is not set"), + }; + let instruction = BuyExactOutCpi { + __program: self.instruction.__program, + + payer: self.instruction.payer.expect("payer is not set"), + + authority: self.instruction.authority.expect("authority is not set"), + + global_config: self + .instruction + .global_config + .expect("global_config is not set"), + + platform_config: self + .instruction + .platform_config + .expect("platform_config is not set"), + + pool_state: self.instruction.pool_state.expect("pool_state is not set"), + + user_base_token: self + .instruction + .user_base_token + .expect("user_base_token is not set"), + + user_quote_token: self + .instruction + .user_quote_token + .expect("user_quote_token is not set"), + + base_vault: self.instruction.base_vault.expect("base_vault is not set"), + + quote_vault: self + .instruction + .quote_vault + .expect("quote_vault is not set"), + + base_token_mint: self + .instruction + .base_token_mint + .expect("base_token_mint is not set"), + + quote_token_mint: self + .instruction + .quote_token_mint + .expect("quote_token_mint is not set"), + + base_token_program: self + .instruction + .base_token_program + .expect("base_token_program is not set"), + + quote_token_program: self + .instruction + .quote_token_program + .expect("quote_token_program is not set"), + + event_authority: self + .instruction + .event_authority + .expect("event_authority is not set"), + + program: self.instruction.program.expect("program is not set"), + __args: args, + }; + instruction.invoke_signed_with_remaining_accounts( + signers_seeds, + &self.instruction.__remaining_accounts, + ) + } +} + +#[derive(Clone, Debug)] +struct BuyExactOutCpiBuilderInstruction<'a, 'b> { + __program: &'b solana_account_info::AccountInfo<'a>, + payer: Option<&'b solana_account_info::AccountInfo<'a>>, + authority: Option<&'b solana_account_info::AccountInfo<'a>>, + global_config: Option<&'b solana_account_info::AccountInfo<'a>>, + platform_config: Option<&'b solana_account_info::AccountInfo<'a>>, + pool_state: Option<&'b solana_account_info::AccountInfo<'a>>, + user_base_token: Option<&'b solana_account_info::AccountInfo<'a>>, + user_quote_token: Option<&'b solana_account_info::AccountInfo<'a>>, + base_vault: Option<&'b solana_account_info::AccountInfo<'a>>, + quote_vault: Option<&'b solana_account_info::AccountInfo<'a>>, + base_token_mint: Option<&'b solana_account_info::AccountInfo<'a>>, + quote_token_mint: Option<&'b solana_account_info::AccountInfo<'a>>, + base_token_program: Option<&'b solana_account_info::AccountInfo<'a>>, + quote_token_program: Option<&'b solana_account_info::AccountInfo<'a>>, + event_authority: Option<&'b solana_account_info::AccountInfo<'a>>, + program: Option<&'b solana_account_info::AccountInfo<'a>>, + amount_out: Option, + maximum_amount_in: Option, + share_fee_rate: Option, + /// Additional instruction accounts `(AccountInfo, is_writable, is_signer)`. + __remaining_accounts: Vec<(&'b solana_account_info::AccountInfo<'a>, bool, bool)>, +} diff --git a/e2e/raydium-launchpad/src/generated/instructions/claim_platform_fee.rs b/e2e/raydium-launchpad/src/generated/instructions/claim_platform_fee.rs new file mode 100644 index 0000000..869de29 --- /dev/null +++ b/e2e/raydium-launchpad/src/generated/instructions/claim_platform_fee.rs @@ -0,0 +1,672 @@ +//! This code was AUTOGENERATED using the codama library. +//! Please DO NOT EDIT THIS FILE, instead use visitors +//! to add features, then rerun codama to update it. +//! +//! +//! + +use borsh::BorshDeserialize; +use borsh::BorshSerialize; + +pub const CLAIM_PLATFORM_FEE_DISCRIMINATOR: [u8; 8] = [156, 39, 208, 135, 76, 237, 61, 72]; + +/// Accounts. +#[derive(Debug)] +pub struct ClaimPlatformFee { + /// Only the wallet stored in platform_config can collect platform fees + pub platform_fee_wallet: solana_address::Address, + /// PDA that acts as the authority for pool vault and mint operations + /// Generated using AUTH_SEED + pub authority: solana_address::Address, + /// Account that stores the pool's state and parameters + /// PDA generated using POOL_SEED and both token mints + pub pool_state: solana_address::Address, + /// The platform config account + pub platform_config: solana_address::Address, + + pub quote_vault: solana_address::Address, + /// The address that receives the collected quote token fees + pub recipient_token_account: solana_address::Address, + /// The mint of quote token vault + pub quote_mint: solana_address::Address, + /// SPL program for input token transfers + pub token_program: solana_address::Address, + /// Required for account creation + pub system_program: solana_address::Address, + /// Required for associated token program + pub associated_token_program: solana_address::Address, +} + +impl ClaimPlatformFee { + pub fn instruction(&self) -> solana_instruction::Instruction { + self.instruction_with_remaining_accounts(&[]) + } + #[allow(clippy::arithmetic_side_effects)] + #[allow(clippy::vec_init_then_push)] + pub fn instruction_with_remaining_accounts( + &self, + remaining_accounts: &[solana_instruction::AccountMeta], + ) -> solana_instruction::Instruction { + let mut accounts = Vec::with_capacity(10 + remaining_accounts.len()); + accounts.push(solana_instruction::AccountMeta::new( + self.platform_fee_wallet, + true, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.authority, + false, + )); + accounts.push(solana_instruction::AccountMeta::new(self.pool_state, false)); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.platform_config, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + self.quote_vault, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + self.recipient_token_account, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.quote_mint, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.token_program, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.system_program, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.associated_token_program, + false, + )); + accounts.extend_from_slice(remaining_accounts); + let data = ClaimPlatformFeeInstructionData::new().try_to_vec().unwrap(); + + solana_instruction::Instruction { + program_id: crate::RAYDIUM_LAUNCHPAD_ID, + accounts, + data, + } + } +} + +#[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] +pub struct ClaimPlatformFeeInstructionData { + discriminator: [u8; 8], +} + +impl ClaimPlatformFeeInstructionData { + pub fn new() -> Self { + Self { + discriminator: [156, 39, 208, 135, 76, 237, 61, 72], + } + } + + pub(crate) fn try_to_vec(&self) -> Result, std::io::Error> { + borsh::to_vec(self) + } +} + +impl Default for ClaimPlatformFeeInstructionData { + fn default() -> Self { + Self::new() + } +} + +/// Instruction builder for `ClaimPlatformFee`. +/// +/// ### Accounts: +/// +/// 0. `[writable, signer]` platform_fee_wallet +/// 1. `[]` authority +/// 2. `[writable]` pool_state +/// 3. `[]` platform_config +/// 4. `[writable]` quote_vault +/// 5. `[writable]` recipient_token_account +/// 6. `[]` quote_mint +/// 7. `[optional]` token_program (default to `TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA`) +/// 8. `[optional]` system_program (default to `11111111111111111111111111111111`) +/// 9. `[optional]` associated_token_program (default to `ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL`) +#[derive(Clone, Debug, Default)] +pub struct ClaimPlatformFeeBuilder { + platform_fee_wallet: Option, + authority: Option, + pool_state: Option, + platform_config: Option, + quote_vault: Option, + recipient_token_account: Option, + quote_mint: Option, + token_program: Option, + system_program: Option, + associated_token_program: Option, + __remaining_accounts: Vec, +} + +impl ClaimPlatformFeeBuilder { + pub fn new() -> Self { + Self::default() + } + /// Only the wallet stored in platform_config can collect platform fees + #[inline(always)] + pub fn platform_fee_wallet( + &mut self, + platform_fee_wallet: solana_address::Address, + ) -> &mut Self { + self.platform_fee_wallet = Some(platform_fee_wallet); + self + } + /// PDA that acts as the authority for pool vault and mint operations + /// Generated using AUTH_SEED + #[inline(always)] + pub fn authority(&mut self, authority: solana_address::Address) -> &mut Self { + self.authority = Some(authority); + self + } + /// Account that stores the pool's state and parameters + /// PDA generated using POOL_SEED and both token mints + #[inline(always)] + pub fn pool_state(&mut self, pool_state: solana_address::Address) -> &mut Self { + self.pool_state = Some(pool_state); + self + } + /// The platform config account + #[inline(always)] + pub fn platform_config(&mut self, platform_config: solana_address::Address) -> &mut Self { + self.platform_config = Some(platform_config); + self + } + #[inline(always)] + pub fn quote_vault(&mut self, quote_vault: solana_address::Address) -> &mut Self { + self.quote_vault = Some(quote_vault); + self + } + /// The address that receives the collected quote token fees + #[inline(always)] + pub fn recipient_token_account( + &mut self, + recipient_token_account: solana_address::Address, + ) -> &mut Self { + self.recipient_token_account = Some(recipient_token_account); + self + } + /// The mint of quote token vault + #[inline(always)] + pub fn quote_mint(&mut self, quote_mint: solana_address::Address) -> &mut Self { + self.quote_mint = Some(quote_mint); + self + } + /// `[optional account, default to 'TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA']` + /// SPL program for input token transfers + #[inline(always)] + pub fn token_program(&mut self, token_program: solana_address::Address) -> &mut Self { + self.token_program = Some(token_program); + self + } + /// `[optional account, default to '11111111111111111111111111111111']` + /// Required for account creation + #[inline(always)] + pub fn system_program(&mut self, system_program: solana_address::Address) -> &mut Self { + self.system_program = Some(system_program); + self + } + /// `[optional account, default to 'ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL']` + /// Required for associated token program + #[inline(always)] + pub fn associated_token_program( + &mut self, + associated_token_program: solana_address::Address, + ) -> &mut Self { + self.associated_token_program = Some(associated_token_program); + self + } + /// Add an additional account to the instruction. + #[inline(always)] + pub fn add_remaining_account(&mut self, account: solana_instruction::AccountMeta) -> &mut Self { + self.__remaining_accounts.push(account); + self + } + /// Add additional accounts to the instruction. + #[inline(always)] + pub fn add_remaining_accounts( + &mut self, + accounts: &[solana_instruction::AccountMeta], + ) -> &mut Self { + self.__remaining_accounts.extend_from_slice(accounts); + self + } + #[allow(clippy::clone_on_copy)] + pub fn instruction(&self) -> solana_instruction::Instruction { + let accounts = ClaimPlatformFee { + platform_fee_wallet: self + .platform_fee_wallet + .expect("platform_fee_wallet is not set"), + authority: self.authority.expect("authority is not set"), + pool_state: self.pool_state.expect("pool_state is not set"), + platform_config: self.platform_config.expect("platform_config is not set"), + quote_vault: self.quote_vault.expect("quote_vault is not set"), + recipient_token_account: self + .recipient_token_account + .expect("recipient_token_account is not set"), + quote_mint: self.quote_mint.expect("quote_mint is not set"), + token_program: self.token_program.unwrap_or(solana_address::address!( + "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA" + )), + system_program: self + .system_program + .unwrap_or(solana_address::address!("11111111111111111111111111111111")), + associated_token_program: self.associated_token_program.unwrap_or( + solana_address::address!("ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL"), + ), + }; + + accounts.instruction_with_remaining_accounts(&self.__remaining_accounts) + } +} + +/// `claim_platform_fee` CPI accounts. +pub struct ClaimPlatformFeeCpiAccounts<'a, 'b> { + /// Only the wallet stored in platform_config can collect platform fees + pub platform_fee_wallet: &'b solana_account_info::AccountInfo<'a>, + /// PDA that acts as the authority for pool vault and mint operations + /// Generated using AUTH_SEED + pub authority: &'b solana_account_info::AccountInfo<'a>, + /// Account that stores the pool's state and parameters + /// PDA generated using POOL_SEED and both token mints + pub pool_state: &'b solana_account_info::AccountInfo<'a>, + /// The platform config account + pub platform_config: &'b solana_account_info::AccountInfo<'a>, + + pub quote_vault: &'b solana_account_info::AccountInfo<'a>, + /// The address that receives the collected quote token fees + pub recipient_token_account: &'b solana_account_info::AccountInfo<'a>, + /// The mint of quote token vault + pub quote_mint: &'b solana_account_info::AccountInfo<'a>, + /// SPL program for input token transfers + pub token_program: &'b solana_account_info::AccountInfo<'a>, + /// Required for account creation + pub system_program: &'b solana_account_info::AccountInfo<'a>, + /// Required for associated token program + pub associated_token_program: &'b solana_account_info::AccountInfo<'a>, +} + +/// `claim_platform_fee` CPI instruction. +pub struct ClaimPlatformFeeCpi<'a, 'b> { + /// The program to invoke. + pub __program: &'b solana_account_info::AccountInfo<'a>, + /// Only the wallet stored in platform_config can collect platform fees + pub platform_fee_wallet: &'b solana_account_info::AccountInfo<'a>, + /// PDA that acts as the authority for pool vault and mint operations + /// Generated using AUTH_SEED + pub authority: &'b solana_account_info::AccountInfo<'a>, + /// Account that stores the pool's state and parameters + /// PDA generated using POOL_SEED and both token mints + pub pool_state: &'b solana_account_info::AccountInfo<'a>, + /// The platform config account + pub platform_config: &'b solana_account_info::AccountInfo<'a>, + + pub quote_vault: &'b solana_account_info::AccountInfo<'a>, + /// The address that receives the collected quote token fees + pub recipient_token_account: &'b solana_account_info::AccountInfo<'a>, + /// The mint of quote token vault + pub quote_mint: &'b solana_account_info::AccountInfo<'a>, + /// SPL program for input token transfers + pub token_program: &'b solana_account_info::AccountInfo<'a>, + /// Required for account creation + pub system_program: &'b solana_account_info::AccountInfo<'a>, + /// Required for associated token program + pub associated_token_program: &'b solana_account_info::AccountInfo<'a>, +} + +impl<'a, 'b> ClaimPlatformFeeCpi<'a, 'b> { + pub fn new( + program: &'b solana_account_info::AccountInfo<'a>, + accounts: ClaimPlatformFeeCpiAccounts<'a, 'b>, + ) -> Self { + Self { + __program: program, + platform_fee_wallet: accounts.platform_fee_wallet, + authority: accounts.authority, + pool_state: accounts.pool_state, + platform_config: accounts.platform_config, + quote_vault: accounts.quote_vault, + recipient_token_account: accounts.recipient_token_account, + quote_mint: accounts.quote_mint, + token_program: accounts.token_program, + system_program: accounts.system_program, + associated_token_program: accounts.associated_token_program, + } + } + #[inline(always)] + pub fn invoke(&self) -> solana_program_error::ProgramResult { + self.invoke_signed_with_remaining_accounts(&[], &[]) + } + #[inline(always)] + pub fn invoke_with_remaining_accounts( + &self, + remaining_accounts: &[(&'b solana_account_info::AccountInfo<'a>, bool, bool)], + ) -> solana_program_error::ProgramResult { + self.invoke_signed_with_remaining_accounts(&[], remaining_accounts) + } + #[inline(always)] + pub fn invoke_signed(&self, signers_seeds: &[&[&[u8]]]) -> solana_program_error::ProgramResult { + self.invoke_signed_with_remaining_accounts(signers_seeds, &[]) + } + #[allow(clippy::arithmetic_side_effects)] + #[allow(clippy::clone_on_copy)] + #[allow(clippy::vec_init_then_push)] + pub fn invoke_signed_with_remaining_accounts( + &self, + signers_seeds: &[&[&[u8]]], + remaining_accounts: &[(&'b solana_account_info::AccountInfo<'a>, bool, bool)], + ) -> solana_program_error::ProgramResult { + let mut accounts = Vec::with_capacity(10 + remaining_accounts.len()); + accounts.push(solana_instruction::AccountMeta::new( + *self.platform_fee_wallet.key, + true, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.authority.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + *self.pool_state.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.platform_config.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + *self.quote_vault.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + *self.recipient_token_account.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.quote_mint.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.token_program.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.system_program.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.associated_token_program.key, + false, + )); + remaining_accounts.iter().for_each(|remaining_account| { + accounts.push(solana_instruction::AccountMeta { + pubkey: *remaining_account.0.key, + is_signer: remaining_account.1, + is_writable: remaining_account.2, + }) + }); + let data = ClaimPlatformFeeInstructionData::new().try_to_vec().unwrap(); + + let instruction = solana_instruction::Instruction { + program_id: crate::RAYDIUM_LAUNCHPAD_ID, + accounts, + data, + }; + let mut account_infos = Vec::with_capacity(11 + remaining_accounts.len()); + account_infos.push(self.__program.clone()); + account_infos.push(self.platform_fee_wallet.clone()); + account_infos.push(self.authority.clone()); + account_infos.push(self.pool_state.clone()); + account_infos.push(self.platform_config.clone()); + account_infos.push(self.quote_vault.clone()); + account_infos.push(self.recipient_token_account.clone()); + account_infos.push(self.quote_mint.clone()); + account_infos.push(self.token_program.clone()); + account_infos.push(self.system_program.clone()); + account_infos.push(self.associated_token_program.clone()); + remaining_accounts + .iter() + .for_each(|remaining_account| account_infos.push(remaining_account.0.clone())); + + if signers_seeds.is_empty() { + solana_cpi::invoke(&instruction, &account_infos) + } else { + solana_cpi::invoke_signed(&instruction, &account_infos, signers_seeds) + } + } +} + +/// Instruction builder for `ClaimPlatformFee` via CPI. +/// +/// ### Accounts: +/// +/// 0. `[writable, signer]` platform_fee_wallet +/// 1. `[]` authority +/// 2. `[writable]` pool_state +/// 3. `[]` platform_config +/// 4. `[writable]` quote_vault +/// 5. `[writable]` recipient_token_account +/// 6. `[]` quote_mint +/// 7. `[]` token_program +/// 8. `[]` system_program +/// 9. `[]` associated_token_program +#[derive(Clone, Debug)] +pub struct ClaimPlatformFeeCpiBuilder<'a, 'b> { + instruction: Box>, +} + +impl<'a, 'b> ClaimPlatformFeeCpiBuilder<'a, 'b> { + pub fn new(program: &'b solana_account_info::AccountInfo<'a>) -> Self { + let instruction = Box::new(ClaimPlatformFeeCpiBuilderInstruction { + __program: program, + platform_fee_wallet: None, + authority: None, + pool_state: None, + platform_config: None, + quote_vault: None, + recipient_token_account: None, + quote_mint: None, + token_program: None, + system_program: None, + associated_token_program: None, + __remaining_accounts: Vec::new(), + }); + Self { instruction } + } + /// Only the wallet stored in platform_config can collect platform fees + #[inline(always)] + pub fn platform_fee_wallet( + &mut self, + platform_fee_wallet: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.platform_fee_wallet = Some(platform_fee_wallet); + self + } + /// PDA that acts as the authority for pool vault and mint operations + /// Generated using AUTH_SEED + #[inline(always)] + pub fn authority(&mut self, authority: &'b solana_account_info::AccountInfo<'a>) -> &mut Self { + self.instruction.authority = Some(authority); + self + } + /// Account that stores the pool's state and parameters + /// PDA generated using POOL_SEED and both token mints + #[inline(always)] + pub fn pool_state( + &mut self, + pool_state: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.pool_state = Some(pool_state); + self + } + /// The platform config account + #[inline(always)] + pub fn platform_config( + &mut self, + platform_config: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.platform_config = Some(platform_config); + self + } + #[inline(always)] + pub fn quote_vault( + &mut self, + quote_vault: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.quote_vault = Some(quote_vault); + self + } + /// The address that receives the collected quote token fees + #[inline(always)] + pub fn recipient_token_account( + &mut self, + recipient_token_account: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.recipient_token_account = Some(recipient_token_account); + self + } + /// The mint of quote token vault + #[inline(always)] + pub fn quote_mint( + &mut self, + quote_mint: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.quote_mint = Some(quote_mint); + self + } + /// SPL program for input token transfers + #[inline(always)] + pub fn token_program( + &mut self, + token_program: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.token_program = Some(token_program); + self + } + /// Required for account creation + #[inline(always)] + pub fn system_program( + &mut self, + system_program: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.system_program = Some(system_program); + self + } + /// Required for associated token program + #[inline(always)] + pub fn associated_token_program( + &mut self, + associated_token_program: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.associated_token_program = Some(associated_token_program); + self + } + /// Add an additional account to the instruction. + #[inline(always)] + pub fn add_remaining_account( + &mut self, + account: &'b solana_account_info::AccountInfo<'a>, + is_writable: bool, + is_signer: bool, + ) -> &mut Self { + self.instruction + .__remaining_accounts + .push((account, is_writable, is_signer)); + self + } + /// Add additional accounts to the instruction. + /// + /// Each account is represented by a tuple of the `AccountInfo`, a `bool` indicating whether the account is writable or not, + /// and a `bool` indicating whether the account is a signer or not. + #[inline(always)] + pub fn add_remaining_accounts( + &mut self, + accounts: &[(&'b solana_account_info::AccountInfo<'a>, bool, bool)], + ) -> &mut Self { + self.instruction + .__remaining_accounts + .extend_from_slice(accounts); + self + } + #[inline(always)] + pub fn invoke(&self) -> solana_program_error::ProgramResult { + self.invoke_signed(&[]) + } + #[allow(clippy::clone_on_copy)] + #[allow(clippy::vec_init_then_push)] + pub fn invoke_signed(&self, signers_seeds: &[&[&[u8]]]) -> solana_program_error::ProgramResult { + let instruction = ClaimPlatformFeeCpi { + __program: self.instruction.__program, + + platform_fee_wallet: self + .instruction + .platform_fee_wallet + .expect("platform_fee_wallet is not set"), + + authority: self.instruction.authority.expect("authority is not set"), + + pool_state: self.instruction.pool_state.expect("pool_state is not set"), + + platform_config: self + .instruction + .platform_config + .expect("platform_config is not set"), + + quote_vault: self + .instruction + .quote_vault + .expect("quote_vault is not set"), + + recipient_token_account: self + .instruction + .recipient_token_account + .expect("recipient_token_account is not set"), + + quote_mint: self.instruction.quote_mint.expect("quote_mint is not set"), + + token_program: self + .instruction + .token_program + .expect("token_program is not set"), + + system_program: self + .instruction + .system_program + .expect("system_program is not set"), + + associated_token_program: self + .instruction + .associated_token_program + .expect("associated_token_program is not set"), + }; + instruction.invoke_signed_with_remaining_accounts( + signers_seeds, + &self.instruction.__remaining_accounts, + ) + } +} + +#[derive(Clone, Debug)] +struct ClaimPlatformFeeCpiBuilderInstruction<'a, 'b> { + __program: &'b solana_account_info::AccountInfo<'a>, + platform_fee_wallet: Option<&'b solana_account_info::AccountInfo<'a>>, + authority: Option<&'b solana_account_info::AccountInfo<'a>>, + pool_state: Option<&'b solana_account_info::AccountInfo<'a>>, + platform_config: Option<&'b solana_account_info::AccountInfo<'a>>, + quote_vault: Option<&'b solana_account_info::AccountInfo<'a>>, + recipient_token_account: Option<&'b solana_account_info::AccountInfo<'a>>, + quote_mint: Option<&'b solana_account_info::AccountInfo<'a>>, + token_program: Option<&'b solana_account_info::AccountInfo<'a>>, + system_program: Option<&'b solana_account_info::AccountInfo<'a>>, + associated_token_program: Option<&'b solana_account_info::AccountInfo<'a>>, + /// Additional instruction accounts `(AccountInfo, is_writable, is_signer)`. + __remaining_accounts: Vec<(&'b solana_account_info::AccountInfo<'a>, bool, bool)>, +} diff --git a/e2e/raydium-launchpad/src/generated/instructions/claim_vested_token.rs b/e2e/raydium-launchpad/src/generated/instructions/claim_vested_token.rs new file mode 100644 index 0000000..a4c1571 --- /dev/null +++ b/e2e/raydium-launchpad/src/generated/instructions/claim_vested_token.rs @@ -0,0 +1,671 @@ +//! This code was AUTOGENERATED using the codama library. +//! Please DO NOT EDIT THIS FILE, instead use visitors +//! to add features, then rerun codama to update it. +//! +//! +//! + +use borsh::BorshDeserialize; +use borsh::BorshSerialize; + +pub const CLAIM_VESTED_TOKEN_DISCRIMINATOR: [u8; 8] = [49, 33, 104, 30, 189, 157, 79, 35]; + +/// Accounts. +#[derive(Debug)] +pub struct ClaimVestedToken { + /// The beneficiary of the vesting account + pub beneficiary: solana_address::Address, + /// PDA that acts as the authority for pool vault and mint operations + /// Generated using AUTH_SEED + pub authority: solana_address::Address, + /// Account that stores the pool's state and parameters + /// PDA generated using POOL_SEED and both token mints + pub pool_state: solana_address::Address, + /// The vesting record account + pub vesting_record: solana_address::Address, + /// The pool's vault for base tokens + /// Will be debited to send tokens to the user + pub base_vault: solana_address::Address, + + pub user_base_token: solana_address::Address, + /// The mint for the base token (token being sold) + /// Created in this instruction with specified decimals + pub base_token_mint: solana_address::Address, + /// SPL Token program for the base token + /// Must be the standard Token program + pub base_token_program: solana_address::Address, + /// Required for account creation + pub system_program: solana_address::Address, + /// Required for associated token program + pub associated_token_program: solana_address::Address, +} + +impl ClaimVestedToken { + pub fn instruction(&self) -> solana_instruction::Instruction { + self.instruction_with_remaining_accounts(&[]) + } + #[allow(clippy::arithmetic_side_effects)] + #[allow(clippy::vec_init_then_push)] + pub fn instruction_with_remaining_accounts( + &self, + remaining_accounts: &[solana_instruction::AccountMeta], + ) -> solana_instruction::Instruction { + let mut accounts = Vec::with_capacity(10 + remaining_accounts.len()); + accounts.push(solana_instruction::AccountMeta::new(self.beneficiary, true)); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.authority, + false, + )); + accounts.push(solana_instruction::AccountMeta::new(self.pool_state, false)); + accounts.push(solana_instruction::AccountMeta::new( + self.vesting_record, + false, + )); + accounts.push(solana_instruction::AccountMeta::new(self.base_vault, false)); + accounts.push(solana_instruction::AccountMeta::new( + self.user_base_token, + true, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.base_token_mint, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.base_token_program, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.system_program, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.associated_token_program, + false, + )); + accounts.extend_from_slice(remaining_accounts); + let data = ClaimVestedTokenInstructionData::new().try_to_vec().unwrap(); + + solana_instruction::Instruction { + program_id: crate::RAYDIUM_LAUNCHPAD_ID, + accounts, + data, + } + } +} + +#[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] +pub struct ClaimVestedTokenInstructionData { + discriminator: [u8; 8], +} + +impl ClaimVestedTokenInstructionData { + pub fn new() -> Self { + Self { + discriminator: [49, 33, 104, 30, 189, 157, 79, 35], + } + } + + pub(crate) fn try_to_vec(&self) -> Result, std::io::Error> { + borsh::to_vec(self) + } +} + +impl Default for ClaimVestedTokenInstructionData { + fn default() -> Self { + Self::new() + } +} + +/// Instruction builder for `ClaimVestedToken`. +/// +/// ### Accounts: +/// +/// 0. `[writable, signer]` beneficiary +/// 1. `[]` authority +/// 2. `[writable]` pool_state +/// 3. `[writable]` vesting_record +/// 4. `[writable]` base_vault +/// 5. `[writable, signer]` user_base_token +/// 6. `[]` base_token_mint +/// 7. `[optional]` base_token_program (default to `TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA`) +/// 8. `[optional]` system_program (default to `11111111111111111111111111111111`) +/// 9. `[optional]` associated_token_program (default to `ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL`) +#[derive(Clone, Debug, Default)] +pub struct ClaimVestedTokenBuilder { + beneficiary: Option, + authority: Option, + pool_state: Option, + vesting_record: Option, + base_vault: Option, + user_base_token: Option, + base_token_mint: Option, + base_token_program: Option, + system_program: Option, + associated_token_program: Option, + __remaining_accounts: Vec, +} + +impl ClaimVestedTokenBuilder { + pub fn new() -> Self { + Self::default() + } + /// The beneficiary of the vesting account + #[inline(always)] + pub fn beneficiary(&mut self, beneficiary: solana_address::Address) -> &mut Self { + self.beneficiary = Some(beneficiary); + self + } + /// PDA that acts as the authority for pool vault and mint operations + /// Generated using AUTH_SEED + #[inline(always)] + pub fn authority(&mut self, authority: solana_address::Address) -> &mut Self { + self.authority = Some(authority); + self + } + /// Account that stores the pool's state and parameters + /// PDA generated using POOL_SEED and both token mints + #[inline(always)] + pub fn pool_state(&mut self, pool_state: solana_address::Address) -> &mut Self { + self.pool_state = Some(pool_state); + self + } + /// The vesting record account + #[inline(always)] + pub fn vesting_record(&mut self, vesting_record: solana_address::Address) -> &mut Self { + self.vesting_record = Some(vesting_record); + self + } + /// The pool's vault for base tokens + /// Will be debited to send tokens to the user + #[inline(always)] + pub fn base_vault(&mut self, base_vault: solana_address::Address) -> &mut Self { + self.base_vault = Some(base_vault); + self + } + #[inline(always)] + pub fn user_base_token(&mut self, user_base_token: solana_address::Address) -> &mut Self { + self.user_base_token = Some(user_base_token); + self + } + /// The mint for the base token (token being sold) + /// Created in this instruction with specified decimals + #[inline(always)] + pub fn base_token_mint(&mut self, base_token_mint: solana_address::Address) -> &mut Self { + self.base_token_mint = Some(base_token_mint); + self + } + /// `[optional account, default to 'TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA']` + /// SPL Token program for the base token + /// Must be the standard Token program + #[inline(always)] + pub fn base_token_program(&mut self, base_token_program: solana_address::Address) -> &mut Self { + self.base_token_program = Some(base_token_program); + self + } + /// `[optional account, default to '11111111111111111111111111111111']` + /// Required for account creation + #[inline(always)] + pub fn system_program(&mut self, system_program: solana_address::Address) -> &mut Self { + self.system_program = Some(system_program); + self + } + /// `[optional account, default to 'ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL']` + /// Required for associated token program + #[inline(always)] + pub fn associated_token_program( + &mut self, + associated_token_program: solana_address::Address, + ) -> &mut Self { + self.associated_token_program = Some(associated_token_program); + self + } + /// Add an additional account to the instruction. + #[inline(always)] + pub fn add_remaining_account(&mut self, account: solana_instruction::AccountMeta) -> &mut Self { + self.__remaining_accounts.push(account); + self + } + /// Add additional accounts to the instruction. + #[inline(always)] + pub fn add_remaining_accounts( + &mut self, + accounts: &[solana_instruction::AccountMeta], + ) -> &mut Self { + self.__remaining_accounts.extend_from_slice(accounts); + self + } + #[allow(clippy::clone_on_copy)] + pub fn instruction(&self) -> solana_instruction::Instruction { + let accounts = ClaimVestedToken { + beneficiary: self.beneficiary.expect("beneficiary is not set"), + authority: self.authority.expect("authority is not set"), + pool_state: self.pool_state.expect("pool_state is not set"), + vesting_record: self.vesting_record.expect("vesting_record is not set"), + base_vault: self.base_vault.expect("base_vault is not set"), + user_base_token: self.user_base_token.expect("user_base_token is not set"), + base_token_mint: self.base_token_mint.expect("base_token_mint is not set"), + base_token_program: self.base_token_program.unwrap_or(solana_address::address!( + "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA" + )), + system_program: self + .system_program + .unwrap_or(solana_address::address!("11111111111111111111111111111111")), + associated_token_program: self.associated_token_program.unwrap_or( + solana_address::address!("ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL"), + ), + }; + + accounts.instruction_with_remaining_accounts(&self.__remaining_accounts) + } +} + +/// `claim_vested_token` CPI accounts. +pub struct ClaimVestedTokenCpiAccounts<'a, 'b> { + /// The beneficiary of the vesting account + pub beneficiary: &'b solana_account_info::AccountInfo<'a>, + /// PDA that acts as the authority for pool vault and mint operations + /// Generated using AUTH_SEED + pub authority: &'b solana_account_info::AccountInfo<'a>, + /// Account that stores the pool's state and parameters + /// PDA generated using POOL_SEED and both token mints + pub pool_state: &'b solana_account_info::AccountInfo<'a>, + /// The vesting record account + pub vesting_record: &'b solana_account_info::AccountInfo<'a>, + /// The pool's vault for base tokens + /// Will be debited to send tokens to the user + pub base_vault: &'b solana_account_info::AccountInfo<'a>, + + pub user_base_token: &'b solana_account_info::AccountInfo<'a>, + /// The mint for the base token (token being sold) + /// Created in this instruction with specified decimals + pub base_token_mint: &'b solana_account_info::AccountInfo<'a>, + /// SPL Token program for the base token + /// Must be the standard Token program + pub base_token_program: &'b solana_account_info::AccountInfo<'a>, + /// Required for account creation + pub system_program: &'b solana_account_info::AccountInfo<'a>, + /// Required for associated token program + pub associated_token_program: &'b solana_account_info::AccountInfo<'a>, +} + +/// `claim_vested_token` CPI instruction. +pub struct ClaimVestedTokenCpi<'a, 'b> { + /// The program to invoke. + pub __program: &'b solana_account_info::AccountInfo<'a>, + /// The beneficiary of the vesting account + pub beneficiary: &'b solana_account_info::AccountInfo<'a>, + /// PDA that acts as the authority for pool vault and mint operations + /// Generated using AUTH_SEED + pub authority: &'b solana_account_info::AccountInfo<'a>, + /// Account that stores the pool's state and parameters + /// PDA generated using POOL_SEED and both token mints + pub pool_state: &'b solana_account_info::AccountInfo<'a>, + /// The vesting record account + pub vesting_record: &'b solana_account_info::AccountInfo<'a>, + /// The pool's vault for base tokens + /// Will be debited to send tokens to the user + pub base_vault: &'b solana_account_info::AccountInfo<'a>, + + pub user_base_token: &'b solana_account_info::AccountInfo<'a>, + /// The mint for the base token (token being sold) + /// Created in this instruction with specified decimals + pub base_token_mint: &'b solana_account_info::AccountInfo<'a>, + /// SPL Token program for the base token + /// Must be the standard Token program + pub base_token_program: &'b solana_account_info::AccountInfo<'a>, + /// Required for account creation + pub system_program: &'b solana_account_info::AccountInfo<'a>, + /// Required for associated token program + pub associated_token_program: &'b solana_account_info::AccountInfo<'a>, +} + +impl<'a, 'b> ClaimVestedTokenCpi<'a, 'b> { + pub fn new( + program: &'b solana_account_info::AccountInfo<'a>, + accounts: ClaimVestedTokenCpiAccounts<'a, 'b>, + ) -> Self { + Self { + __program: program, + beneficiary: accounts.beneficiary, + authority: accounts.authority, + pool_state: accounts.pool_state, + vesting_record: accounts.vesting_record, + base_vault: accounts.base_vault, + user_base_token: accounts.user_base_token, + base_token_mint: accounts.base_token_mint, + base_token_program: accounts.base_token_program, + system_program: accounts.system_program, + associated_token_program: accounts.associated_token_program, + } + } + #[inline(always)] + pub fn invoke(&self) -> solana_program_error::ProgramResult { + self.invoke_signed_with_remaining_accounts(&[], &[]) + } + #[inline(always)] + pub fn invoke_with_remaining_accounts( + &self, + remaining_accounts: &[(&'b solana_account_info::AccountInfo<'a>, bool, bool)], + ) -> solana_program_error::ProgramResult { + self.invoke_signed_with_remaining_accounts(&[], remaining_accounts) + } + #[inline(always)] + pub fn invoke_signed(&self, signers_seeds: &[&[&[u8]]]) -> solana_program_error::ProgramResult { + self.invoke_signed_with_remaining_accounts(signers_seeds, &[]) + } + #[allow(clippy::arithmetic_side_effects)] + #[allow(clippy::clone_on_copy)] + #[allow(clippy::vec_init_then_push)] + pub fn invoke_signed_with_remaining_accounts( + &self, + signers_seeds: &[&[&[u8]]], + remaining_accounts: &[(&'b solana_account_info::AccountInfo<'a>, bool, bool)], + ) -> solana_program_error::ProgramResult { + let mut accounts = Vec::with_capacity(10 + remaining_accounts.len()); + accounts.push(solana_instruction::AccountMeta::new( + *self.beneficiary.key, + true, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.authority.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + *self.pool_state.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + *self.vesting_record.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + *self.base_vault.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + *self.user_base_token.key, + true, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.base_token_mint.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.base_token_program.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.system_program.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.associated_token_program.key, + false, + )); + remaining_accounts.iter().for_each(|remaining_account| { + accounts.push(solana_instruction::AccountMeta { + pubkey: *remaining_account.0.key, + is_signer: remaining_account.1, + is_writable: remaining_account.2, + }) + }); + let data = ClaimVestedTokenInstructionData::new().try_to_vec().unwrap(); + + let instruction = solana_instruction::Instruction { + program_id: crate::RAYDIUM_LAUNCHPAD_ID, + accounts, + data, + }; + let mut account_infos = Vec::with_capacity(11 + remaining_accounts.len()); + account_infos.push(self.__program.clone()); + account_infos.push(self.beneficiary.clone()); + account_infos.push(self.authority.clone()); + account_infos.push(self.pool_state.clone()); + account_infos.push(self.vesting_record.clone()); + account_infos.push(self.base_vault.clone()); + account_infos.push(self.user_base_token.clone()); + account_infos.push(self.base_token_mint.clone()); + account_infos.push(self.base_token_program.clone()); + account_infos.push(self.system_program.clone()); + account_infos.push(self.associated_token_program.clone()); + remaining_accounts + .iter() + .for_each(|remaining_account| account_infos.push(remaining_account.0.clone())); + + if signers_seeds.is_empty() { + solana_cpi::invoke(&instruction, &account_infos) + } else { + solana_cpi::invoke_signed(&instruction, &account_infos, signers_seeds) + } + } +} + +/// Instruction builder for `ClaimVestedToken` via CPI. +/// +/// ### Accounts: +/// +/// 0. `[writable, signer]` beneficiary +/// 1. `[]` authority +/// 2. `[writable]` pool_state +/// 3. `[writable]` vesting_record +/// 4. `[writable]` base_vault +/// 5. `[writable, signer]` user_base_token +/// 6. `[]` base_token_mint +/// 7. `[]` base_token_program +/// 8. `[]` system_program +/// 9. `[]` associated_token_program +#[derive(Clone, Debug)] +pub struct ClaimVestedTokenCpiBuilder<'a, 'b> { + instruction: Box>, +} + +impl<'a, 'b> ClaimVestedTokenCpiBuilder<'a, 'b> { + pub fn new(program: &'b solana_account_info::AccountInfo<'a>) -> Self { + let instruction = Box::new(ClaimVestedTokenCpiBuilderInstruction { + __program: program, + beneficiary: None, + authority: None, + pool_state: None, + vesting_record: None, + base_vault: None, + user_base_token: None, + base_token_mint: None, + base_token_program: None, + system_program: None, + associated_token_program: None, + __remaining_accounts: Vec::new(), + }); + Self { instruction } + } + /// The beneficiary of the vesting account + #[inline(always)] + pub fn beneficiary( + &mut self, + beneficiary: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.beneficiary = Some(beneficiary); + self + } + /// PDA that acts as the authority for pool vault and mint operations + /// Generated using AUTH_SEED + #[inline(always)] + pub fn authority(&mut self, authority: &'b solana_account_info::AccountInfo<'a>) -> &mut Self { + self.instruction.authority = Some(authority); + self + } + /// Account that stores the pool's state and parameters + /// PDA generated using POOL_SEED and both token mints + #[inline(always)] + pub fn pool_state( + &mut self, + pool_state: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.pool_state = Some(pool_state); + self + } + /// The vesting record account + #[inline(always)] + pub fn vesting_record( + &mut self, + vesting_record: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.vesting_record = Some(vesting_record); + self + } + /// The pool's vault for base tokens + /// Will be debited to send tokens to the user + #[inline(always)] + pub fn base_vault( + &mut self, + base_vault: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.base_vault = Some(base_vault); + self + } + #[inline(always)] + pub fn user_base_token( + &mut self, + user_base_token: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.user_base_token = Some(user_base_token); + self + } + /// The mint for the base token (token being sold) + /// Created in this instruction with specified decimals + #[inline(always)] + pub fn base_token_mint( + &mut self, + base_token_mint: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.base_token_mint = Some(base_token_mint); + self + } + /// SPL Token program for the base token + /// Must be the standard Token program + #[inline(always)] + pub fn base_token_program( + &mut self, + base_token_program: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.base_token_program = Some(base_token_program); + self + } + /// Required for account creation + #[inline(always)] + pub fn system_program( + &mut self, + system_program: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.system_program = Some(system_program); + self + } + /// Required for associated token program + #[inline(always)] + pub fn associated_token_program( + &mut self, + associated_token_program: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.associated_token_program = Some(associated_token_program); + self + } + /// Add an additional account to the instruction. + #[inline(always)] + pub fn add_remaining_account( + &mut self, + account: &'b solana_account_info::AccountInfo<'a>, + is_writable: bool, + is_signer: bool, + ) -> &mut Self { + self.instruction + .__remaining_accounts + .push((account, is_writable, is_signer)); + self + } + /// Add additional accounts to the instruction. + /// + /// Each account is represented by a tuple of the `AccountInfo`, a `bool` indicating whether the account is writable or not, + /// and a `bool` indicating whether the account is a signer or not. + #[inline(always)] + pub fn add_remaining_accounts( + &mut self, + accounts: &[(&'b solana_account_info::AccountInfo<'a>, bool, bool)], + ) -> &mut Self { + self.instruction + .__remaining_accounts + .extend_from_slice(accounts); + self + } + #[inline(always)] + pub fn invoke(&self) -> solana_program_error::ProgramResult { + self.invoke_signed(&[]) + } + #[allow(clippy::clone_on_copy)] + #[allow(clippy::vec_init_then_push)] + pub fn invoke_signed(&self, signers_seeds: &[&[&[u8]]]) -> solana_program_error::ProgramResult { + let instruction = ClaimVestedTokenCpi { + __program: self.instruction.__program, + + beneficiary: self + .instruction + .beneficiary + .expect("beneficiary is not set"), + + authority: self.instruction.authority.expect("authority is not set"), + + pool_state: self.instruction.pool_state.expect("pool_state is not set"), + + vesting_record: self + .instruction + .vesting_record + .expect("vesting_record is not set"), + + base_vault: self.instruction.base_vault.expect("base_vault is not set"), + + user_base_token: self + .instruction + .user_base_token + .expect("user_base_token is not set"), + + base_token_mint: self + .instruction + .base_token_mint + .expect("base_token_mint is not set"), + + base_token_program: self + .instruction + .base_token_program + .expect("base_token_program is not set"), + + system_program: self + .instruction + .system_program + .expect("system_program is not set"), + + associated_token_program: self + .instruction + .associated_token_program + .expect("associated_token_program is not set"), + }; + instruction.invoke_signed_with_remaining_accounts( + signers_seeds, + &self.instruction.__remaining_accounts, + ) + } +} + +#[derive(Clone, Debug)] +struct ClaimVestedTokenCpiBuilderInstruction<'a, 'b> { + __program: &'b solana_account_info::AccountInfo<'a>, + beneficiary: Option<&'b solana_account_info::AccountInfo<'a>>, + authority: Option<&'b solana_account_info::AccountInfo<'a>>, + pool_state: Option<&'b solana_account_info::AccountInfo<'a>>, + vesting_record: Option<&'b solana_account_info::AccountInfo<'a>>, + base_vault: Option<&'b solana_account_info::AccountInfo<'a>>, + user_base_token: Option<&'b solana_account_info::AccountInfo<'a>>, + base_token_mint: Option<&'b solana_account_info::AccountInfo<'a>>, + base_token_program: Option<&'b solana_account_info::AccountInfo<'a>>, + system_program: Option<&'b solana_account_info::AccountInfo<'a>>, + associated_token_program: Option<&'b solana_account_info::AccountInfo<'a>>, + /// Additional instruction accounts `(AccountInfo, is_writable, is_signer)`. + __remaining_accounts: Vec<(&'b solana_account_info::AccountInfo<'a>, bool, bool)>, +} diff --git a/e2e/raydium-launchpad/src/generated/instructions/collect_fee.rs b/e2e/raydium-launchpad/src/generated/instructions/collect_fee.rs new file mode 100644 index 0000000..86e9908 --- /dev/null +++ b/e2e/raydium-launchpad/src/generated/instructions/collect_fee.rs @@ -0,0 +1,557 @@ +//! This code was AUTOGENERATED using the codama library. +//! Please DO NOT EDIT THIS FILE, instead use visitors +//! to add features, then rerun codama to update it. +//! +//! +//! + +use borsh::BorshDeserialize; +use borsh::BorshSerialize; + +pub const COLLECT_FEE_DISCRIMINATOR: [u8; 8] = [60, 173, 247, 103, 4, 93, 130, 48]; + +/// Accounts. +#[derive(Debug)] +pub struct CollectFee { + /// Only protocol_fee_owner saved in global_config can collect protocol fee now + pub owner: solana_address::Address, + + pub authority: solana_address::Address, + /// Pool state stores accumulated protocol fee amount + pub pool_state: solana_address::Address, + /// Global config account stores owner + pub global_config: solana_address::Address, + /// The address that holds pool tokens for quote token + pub quote_vault: solana_address::Address, + /// The mint of quote token vault + pub quote_mint: solana_address::Address, + /// The address that receives the collected quote token fees + pub recipient_token_account: solana_address::Address, + /// SPL program for input token transfers + pub token_program: solana_address::Address, +} + +impl CollectFee { + pub fn instruction(&self) -> solana_instruction::Instruction { + self.instruction_with_remaining_accounts(&[]) + } + #[allow(clippy::arithmetic_side_effects)] + #[allow(clippy::vec_init_then_push)] + pub fn instruction_with_remaining_accounts( + &self, + remaining_accounts: &[solana_instruction::AccountMeta], + ) -> solana_instruction::Instruction { + let mut accounts = Vec::with_capacity(8 + remaining_accounts.len()); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.owner, true, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.authority, + false, + )); + accounts.push(solana_instruction::AccountMeta::new(self.pool_state, false)); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.global_config, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + self.quote_vault, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.quote_mint, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + self.recipient_token_account, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.token_program, + false, + )); + accounts.extend_from_slice(remaining_accounts); + let data = CollectFeeInstructionData::new().try_to_vec().unwrap(); + + solana_instruction::Instruction { + program_id: crate::RAYDIUM_LAUNCHPAD_ID, + accounts, + data, + } + } +} + +#[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] +pub struct CollectFeeInstructionData { + discriminator: [u8; 8], +} + +impl CollectFeeInstructionData { + pub fn new() -> Self { + Self { + discriminator: [60, 173, 247, 103, 4, 93, 130, 48], + } + } + + pub(crate) fn try_to_vec(&self) -> Result, std::io::Error> { + borsh::to_vec(self) + } +} + +impl Default for CollectFeeInstructionData { + fn default() -> Self { + Self::new() + } +} + +/// Instruction builder for `CollectFee`. +/// +/// ### Accounts: +/// +/// 0. `[signer]` owner +/// 1. `[]` authority +/// 2. `[writable]` pool_state +/// 3. `[]` global_config +/// 4. `[writable]` quote_vault +/// 5. `[]` quote_mint +/// 6. `[writable]` recipient_token_account +/// 7. `[optional]` token_program (default to `TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA`) +#[derive(Clone, Debug, Default)] +pub struct CollectFeeBuilder { + owner: Option, + authority: Option, + pool_state: Option, + global_config: Option, + quote_vault: Option, + quote_mint: Option, + recipient_token_account: Option, + token_program: Option, + __remaining_accounts: Vec, +} + +impl CollectFeeBuilder { + pub fn new() -> Self { + Self::default() + } + /// Only protocol_fee_owner saved in global_config can collect protocol fee now + #[inline(always)] + pub fn owner(&mut self, owner: solana_address::Address) -> &mut Self { + self.owner = Some(owner); + self + } + #[inline(always)] + pub fn authority(&mut self, authority: solana_address::Address) -> &mut Self { + self.authority = Some(authority); + self + } + /// Pool state stores accumulated protocol fee amount + #[inline(always)] + pub fn pool_state(&mut self, pool_state: solana_address::Address) -> &mut Self { + self.pool_state = Some(pool_state); + self + } + /// Global config account stores owner + #[inline(always)] + pub fn global_config(&mut self, global_config: solana_address::Address) -> &mut Self { + self.global_config = Some(global_config); + self + } + /// The address that holds pool tokens for quote token + #[inline(always)] + pub fn quote_vault(&mut self, quote_vault: solana_address::Address) -> &mut Self { + self.quote_vault = Some(quote_vault); + self + } + /// The mint of quote token vault + #[inline(always)] + pub fn quote_mint(&mut self, quote_mint: solana_address::Address) -> &mut Self { + self.quote_mint = Some(quote_mint); + self + } + /// The address that receives the collected quote token fees + #[inline(always)] + pub fn recipient_token_account( + &mut self, + recipient_token_account: solana_address::Address, + ) -> &mut Self { + self.recipient_token_account = Some(recipient_token_account); + self + } + /// `[optional account, default to 'TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA']` + /// SPL program for input token transfers + #[inline(always)] + pub fn token_program(&mut self, token_program: solana_address::Address) -> &mut Self { + self.token_program = Some(token_program); + self + } + /// Add an additional account to the instruction. + #[inline(always)] + pub fn add_remaining_account(&mut self, account: solana_instruction::AccountMeta) -> &mut Self { + self.__remaining_accounts.push(account); + self + } + /// Add additional accounts to the instruction. + #[inline(always)] + pub fn add_remaining_accounts( + &mut self, + accounts: &[solana_instruction::AccountMeta], + ) -> &mut Self { + self.__remaining_accounts.extend_from_slice(accounts); + self + } + #[allow(clippy::clone_on_copy)] + pub fn instruction(&self) -> solana_instruction::Instruction { + let accounts = CollectFee { + owner: self.owner.expect("owner is not set"), + authority: self.authority.expect("authority is not set"), + pool_state: self.pool_state.expect("pool_state is not set"), + global_config: self.global_config.expect("global_config is not set"), + quote_vault: self.quote_vault.expect("quote_vault is not set"), + quote_mint: self.quote_mint.expect("quote_mint is not set"), + recipient_token_account: self + .recipient_token_account + .expect("recipient_token_account is not set"), + token_program: self.token_program.unwrap_or(solana_address::address!( + "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA" + )), + }; + + accounts.instruction_with_remaining_accounts(&self.__remaining_accounts) + } +} + +/// `collect_fee` CPI accounts. +pub struct CollectFeeCpiAccounts<'a, 'b> { + /// Only protocol_fee_owner saved in global_config can collect protocol fee now + pub owner: &'b solana_account_info::AccountInfo<'a>, + + pub authority: &'b solana_account_info::AccountInfo<'a>, + /// Pool state stores accumulated protocol fee amount + pub pool_state: &'b solana_account_info::AccountInfo<'a>, + /// Global config account stores owner + pub global_config: &'b solana_account_info::AccountInfo<'a>, + /// The address that holds pool tokens for quote token + pub quote_vault: &'b solana_account_info::AccountInfo<'a>, + /// The mint of quote token vault + pub quote_mint: &'b solana_account_info::AccountInfo<'a>, + /// The address that receives the collected quote token fees + pub recipient_token_account: &'b solana_account_info::AccountInfo<'a>, + /// SPL program for input token transfers + pub token_program: &'b solana_account_info::AccountInfo<'a>, +} + +/// `collect_fee` CPI instruction. +pub struct CollectFeeCpi<'a, 'b> { + /// The program to invoke. + pub __program: &'b solana_account_info::AccountInfo<'a>, + /// Only protocol_fee_owner saved in global_config can collect protocol fee now + pub owner: &'b solana_account_info::AccountInfo<'a>, + + pub authority: &'b solana_account_info::AccountInfo<'a>, + /// Pool state stores accumulated protocol fee amount + pub pool_state: &'b solana_account_info::AccountInfo<'a>, + /// Global config account stores owner + pub global_config: &'b solana_account_info::AccountInfo<'a>, + /// The address that holds pool tokens for quote token + pub quote_vault: &'b solana_account_info::AccountInfo<'a>, + /// The mint of quote token vault + pub quote_mint: &'b solana_account_info::AccountInfo<'a>, + /// The address that receives the collected quote token fees + pub recipient_token_account: &'b solana_account_info::AccountInfo<'a>, + /// SPL program for input token transfers + pub token_program: &'b solana_account_info::AccountInfo<'a>, +} + +impl<'a, 'b> CollectFeeCpi<'a, 'b> { + pub fn new( + program: &'b solana_account_info::AccountInfo<'a>, + accounts: CollectFeeCpiAccounts<'a, 'b>, + ) -> Self { + Self { + __program: program, + owner: accounts.owner, + authority: accounts.authority, + pool_state: accounts.pool_state, + global_config: accounts.global_config, + quote_vault: accounts.quote_vault, + quote_mint: accounts.quote_mint, + recipient_token_account: accounts.recipient_token_account, + token_program: accounts.token_program, + } + } + #[inline(always)] + pub fn invoke(&self) -> solana_program_error::ProgramResult { + self.invoke_signed_with_remaining_accounts(&[], &[]) + } + #[inline(always)] + pub fn invoke_with_remaining_accounts( + &self, + remaining_accounts: &[(&'b solana_account_info::AccountInfo<'a>, bool, bool)], + ) -> solana_program_error::ProgramResult { + self.invoke_signed_with_remaining_accounts(&[], remaining_accounts) + } + #[inline(always)] + pub fn invoke_signed(&self, signers_seeds: &[&[&[u8]]]) -> solana_program_error::ProgramResult { + self.invoke_signed_with_remaining_accounts(signers_seeds, &[]) + } + #[allow(clippy::arithmetic_side_effects)] + #[allow(clippy::clone_on_copy)] + #[allow(clippy::vec_init_then_push)] + pub fn invoke_signed_with_remaining_accounts( + &self, + signers_seeds: &[&[&[u8]]], + remaining_accounts: &[(&'b solana_account_info::AccountInfo<'a>, bool, bool)], + ) -> solana_program_error::ProgramResult { + let mut accounts = Vec::with_capacity(8 + remaining_accounts.len()); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.owner.key, + true, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.authority.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + *self.pool_state.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.global_config.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + *self.quote_vault.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.quote_mint.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + *self.recipient_token_account.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.token_program.key, + false, + )); + remaining_accounts.iter().for_each(|remaining_account| { + accounts.push(solana_instruction::AccountMeta { + pubkey: *remaining_account.0.key, + is_signer: remaining_account.1, + is_writable: remaining_account.2, + }) + }); + let data = CollectFeeInstructionData::new().try_to_vec().unwrap(); + + let instruction = solana_instruction::Instruction { + program_id: crate::RAYDIUM_LAUNCHPAD_ID, + accounts, + data, + }; + let mut account_infos = Vec::with_capacity(9 + remaining_accounts.len()); + account_infos.push(self.__program.clone()); + account_infos.push(self.owner.clone()); + account_infos.push(self.authority.clone()); + account_infos.push(self.pool_state.clone()); + account_infos.push(self.global_config.clone()); + account_infos.push(self.quote_vault.clone()); + account_infos.push(self.quote_mint.clone()); + account_infos.push(self.recipient_token_account.clone()); + account_infos.push(self.token_program.clone()); + remaining_accounts + .iter() + .for_each(|remaining_account| account_infos.push(remaining_account.0.clone())); + + if signers_seeds.is_empty() { + solana_cpi::invoke(&instruction, &account_infos) + } else { + solana_cpi::invoke_signed(&instruction, &account_infos, signers_seeds) + } + } +} + +/// Instruction builder for `CollectFee` via CPI. +/// +/// ### Accounts: +/// +/// 0. `[signer]` owner +/// 1. `[]` authority +/// 2. `[writable]` pool_state +/// 3. `[]` global_config +/// 4. `[writable]` quote_vault +/// 5. `[]` quote_mint +/// 6. `[writable]` recipient_token_account +/// 7. `[]` token_program +#[derive(Clone, Debug)] +pub struct CollectFeeCpiBuilder<'a, 'b> { + instruction: Box>, +} + +impl<'a, 'b> CollectFeeCpiBuilder<'a, 'b> { + pub fn new(program: &'b solana_account_info::AccountInfo<'a>) -> Self { + let instruction = Box::new(CollectFeeCpiBuilderInstruction { + __program: program, + owner: None, + authority: None, + pool_state: None, + global_config: None, + quote_vault: None, + quote_mint: None, + recipient_token_account: None, + token_program: None, + __remaining_accounts: Vec::new(), + }); + Self { instruction } + } + /// Only protocol_fee_owner saved in global_config can collect protocol fee now + #[inline(always)] + pub fn owner(&mut self, owner: &'b solana_account_info::AccountInfo<'a>) -> &mut Self { + self.instruction.owner = Some(owner); + self + } + #[inline(always)] + pub fn authority(&mut self, authority: &'b solana_account_info::AccountInfo<'a>) -> &mut Self { + self.instruction.authority = Some(authority); + self + } + /// Pool state stores accumulated protocol fee amount + #[inline(always)] + pub fn pool_state( + &mut self, + pool_state: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.pool_state = Some(pool_state); + self + } + /// Global config account stores owner + #[inline(always)] + pub fn global_config( + &mut self, + global_config: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.global_config = Some(global_config); + self + } + /// The address that holds pool tokens for quote token + #[inline(always)] + pub fn quote_vault( + &mut self, + quote_vault: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.quote_vault = Some(quote_vault); + self + } + /// The mint of quote token vault + #[inline(always)] + pub fn quote_mint( + &mut self, + quote_mint: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.quote_mint = Some(quote_mint); + self + } + /// The address that receives the collected quote token fees + #[inline(always)] + pub fn recipient_token_account( + &mut self, + recipient_token_account: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.recipient_token_account = Some(recipient_token_account); + self + } + /// SPL program for input token transfers + #[inline(always)] + pub fn token_program( + &mut self, + token_program: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.token_program = Some(token_program); + self + } + /// Add an additional account to the instruction. + #[inline(always)] + pub fn add_remaining_account( + &mut self, + account: &'b solana_account_info::AccountInfo<'a>, + is_writable: bool, + is_signer: bool, + ) -> &mut Self { + self.instruction + .__remaining_accounts + .push((account, is_writable, is_signer)); + self + } + /// Add additional accounts to the instruction. + /// + /// Each account is represented by a tuple of the `AccountInfo`, a `bool` indicating whether the account is writable or not, + /// and a `bool` indicating whether the account is a signer or not. + #[inline(always)] + pub fn add_remaining_accounts( + &mut self, + accounts: &[(&'b solana_account_info::AccountInfo<'a>, bool, bool)], + ) -> &mut Self { + self.instruction + .__remaining_accounts + .extend_from_slice(accounts); + self + } + #[inline(always)] + pub fn invoke(&self) -> solana_program_error::ProgramResult { + self.invoke_signed(&[]) + } + #[allow(clippy::clone_on_copy)] + #[allow(clippy::vec_init_then_push)] + pub fn invoke_signed(&self, signers_seeds: &[&[&[u8]]]) -> solana_program_error::ProgramResult { + let instruction = CollectFeeCpi { + __program: self.instruction.__program, + + owner: self.instruction.owner.expect("owner is not set"), + + authority: self.instruction.authority.expect("authority is not set"), + + pool_state: self.instruction.pool_state.expect("pool_state is not set"), + + global_config: self + .instruction + .global_config + .expect("global_config is not set"), + + quote_vault: self + .instruction + .quote_vault + .expect("quote_vault is not set"), + + quote_mint: self.instruction.quote_mint.expect("quote_mint is not set"), + + recipient_token_account: self + .instruction + .recipient_token_account + .expect("recipient_token_account is not set"), + + token_program: self + .instruction + .token_program + .expect("token_program is not set"), + }; + instruction.invoke_signed_with_remaining_accounts( + signers_seeds, + &self.instruction.__remaining_accounts, + ) + } +} + +#[derive(Clone, Debug)] +struct CollectFeeCpiBuilderInstruction<'a, 'b> { + __program: &'b solana_account_info::AccountInfo<'a>, + owner: Option<&'b solana_account_info::AccountInfo<'a>>, + authority: Option<&'b solana_account_info::AccountInfo<'a>>, + pool_state: Option<&'b solana_account_info::AccountInfo<'a>>, + global_config: Option<&'b solana_account_info::AccountInfo<'a>>, + quote_vault: Option<&'b solana_account_info::AccountInfo<'a>>, + quote_mint: Option<&'b solana_account_info::AccountInfo<'a>>, + recipient_token_account: Option<&'b solana_account_info::AccountInfo<'a>>, + token_program: Option<&'b solana_account_info::AccountInfo<'a>>, + /// Additional instruction accounts `(AccountInfo, is_writable, is_signer)`. + __remaining_accounts: Vec<(&'b solana_account_info::AccountInfo<'a>, bool, bool)>, +} diff --git a/e2e/raydium-launchpad/src/generated/instructions/collect_migrate_fee.rs b/e2e/raydium-launchpad/src/generated/instructions/collect_migrate_fee.rs new file mode 100644 index 0000000..6aa0544 --- /dev/null +++ b/e2e/raydium-launchpad/src/generated/instructions/collect_migrate_fee.rs @@ -0,0 +1,561 @@ +//! This code was AUTOGENERATED using the codama library. +//! Please DO NOT EDIT THIS FILE, instead use visitors +//! to add features, then rerun codama to update it. +//! +//! +//! + +use borsh::BorshDeserialize; +use borsh::BorshSerialize; + +pub const COLLECT_MIGRATE_FEE_DISCRIMINATOR: [u8; 8] = [255, 186, 150, 223, 235, 118, 201, 186]; + +/// Accounts. +#[derive(Debug)] +pub struct CollectMigrateFee { + /// Only migrate_fee_owner saved in global_config can collect migrate fee now + pub owner: solana_address::Address, + + pub authority: solana_address::Address, + /// Pool state stores accumulated protocol fee amount + pub pool_state: solana_address::Address, + /// Global config account stores owner + pub global_config: solana_address::Address, + /// The address that holds pool tokens for quote token + pub quote_vault: solana_address::Address, + /// The mint of quote token vault + pub quote_mint: solana_address::Address, + /// The address that receives the collected quote token fees + pub recipient_token_account: solana_address::Address, + /// SPL program for input token transfers + pub token_program: solana_address::Address, +} + +impl CollectMigrateFee { + pub fn instruction(&self) -> solana_instruction::Instruction { + self.instruction_with_remaining_accounts(&[]) + } + #[allow(clippy::arithmetic_side_effects)] + #[allow(clippy::vec_init_then_push)] + pub fn instruction_with_remaining_accounts( + &self, + remaining_accounts: &[solana_instruction::AccountMeta], + ) -> solana_instruction::Instruction { + let mut accounts = Vec::with_capacity(8 + remaining_accounts.len()); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.owner, true, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.authority, + false, + )); + accounts.push(solana_instruction::AccountMeta::new(self.pool_state, false)); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.global_config, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + self.quote_vault, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.quote_mint, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + self.recipient_token_account, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.token_program, + false, + )); + accounts.extend_from_slice(remaining_accounts); + let data = CollectMigrateFeeInstructionData::new() + .try_to_vec() + .unwrap(); + + solana_instruction::Instruction { + program_id: crate::RAYDIUM_LAUNCHPAD_ID, + accounts, + data, + } + } +} + +#[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] +pub struct CollectMigrateFeeInstructionData { + discriminator: [u8; 8], +} + +impl CollectMigrateFeeInstructionData { + pub fn new() -> Self { + Self { + discriminator: [255, 186, 150, 223, 235, 118, 201, 186], + } + } + + pub(crate) fn try_to_vec(&self) -> Result, std::io::Error> { + borsh::to_vec(self) + } +} + +impl Default for CollectMigrateFeeInstructionData { + fn default() -> Self { + Self::new() + } +} + +/// Instruction builder for `CollectMigrateFee`. +/// +/// ### Accounts: +/// +/// 0. `[signer]` owner +/// 1. `[]` authority +/// 2. `[writable]` pool_state +/// 3. `[]` global_config +/// 4. `[writable]` quote_vault +/// 5. `[]` quote_mint +/// 6. `[writable]` recipient_token_account +/// 7. `[optional]` token_program (default to `TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA`) +#[derive(Clone, Debug, Default)] +pub struct CollectMigrateFeeBuilder { + owner: Option, + authority: Option, + pool_state: Option, + global_config: Option, + quote_vault: Option, + quote_mint: Option, + recipient_token_account: Option, + token_program: Option, + __remaining_accounts: Vec, +} + +impl CollectMigrateFeeBuilder { + pub fn new() -> Self { + Self::default() + } + /// Only migrate_fee_owner saved in global_config can collect migrate fee now + #[inline(always)] + pub fn owner(&mut self, owner: solana_address::Address) -> &mut Self { + self.owner = Some(owner); + self + } + #[inline(always)] + pub fn authority(&mut self, authority: solana_address::Address) -> &mut Self { + self.authority = Some(authority); + self + } + /// Pool state stores accumulated protocol fee amount + #[inline(always)] + pub fn pool_state(&mut self, pool_state: solana_address::Address) -> &mut Self { + self.pool_state = Some(pool_state); + self + } + /// Global config account stores owner + #[inline(always)] + pub fn global_config(&mut self, global_config: solana_address::Address) -> &mut Self { + self.global_config = Some(global_config); + self + } + /// The address that holds pool tokens for quote token + #[inline(always)] + pub fn quote_vault(&mut self, quote_vault: solana_address::Address) -> &mut Self { + self.quote_vault = Some(quote_vault); + self + } + /// The mint of quote token vault + #[inline(always)] + pub fn quote_mint(&mut self, quote_mint: solana_address::Address) -> &mut Self { + self.quote_mint = Some(quote_mint); + self + } + /// The address that receives the collected quote token fees + #[inline(always)] + pub fn recipient_token_account( + &mut self, + recipient_token_account: solana_address::Address, + ) -> &mut Self { + self.recipient_token_account = Some(recipient_token_account); + self + } + /// `[optional account, default to 'TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA']` + /// SPL program for input token transfers + #[inline(always)] + pub fn token_program(&mut self, token_program: solana_address::Address) -> &mut Self { + self.token_program = Some(token_program); + self + } + /// Add an additional account to the instruction. + #[inline(always)] + pub fn add_remaining_account(&mut self, account: solana_instruction::AccountMeta) -> &mut Self { + self.__remaining_accounts.push(account); + self + } + /// Add additional accounts to the instruction. + #[inline(always)] + pub fn add_remaining_accounts( + &mut self, + accounts: &[solana_instruction::AccountMeta], + ) -> &mut Self { + self.__remaining_accounts.extend_from_slice(accounts); + self + } + #[allow(clippy::clone_on_copy)] + pub fn instruction(&self) -> solana_instruction::Instruction { + let accounts = CollectMigrateFee { + owner: self.owner.expect("owner is not set"), + authority: self.authority.expect("authority is not set"), + pool_state: self.pool_state.expect("pool_state is not set"), + global_config: self.global_config.expect("global_config is not set"), + quote_vault: self.quote_vault.expect("quote_vault is not set"), + quote_mint: self.quote_mint.expect("quote_mint is not set"), + recipient_token_account: self + .recipient_token_account + .expect("recipient_token_account is not set"), + token_program: self.token_program.unwrap_or(solana_address::address!( + "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA" + )), + }; + + accounts.instruction_with_remaining_accounts(&self.__remaining_accounts) + } +} + +/// `collect_migrate_fee` CPI accounts. +pub struct CollectMigrateFeeCpiAccounts<'a, 'b> { + /// Only migrate_fee_owner saved in global_config can collect migrate fee now + pub owner: &'b solana_account_info::AccountInfo<'a>, + + pub authority: &'b solana_account_info::AccountInfo<'a>, + /// Pool state stores accumulated protocol fee amount + pub pool_state: &'b solana_account_info::AccountInfo<'a>, + /// Global config account stores owner + pub global_config: &'b solana_account_info::AccountInfo<'a>, + /// The address that holds pool tokens for quote token + pub quote_vault: &'b solana_account_info::AccountInfo<'a>, + /// The mint of quote token vault + pub quote_mint: &'b solana_account_info::AccountInfo<'a>, + /// The address that receives the collected quote token fees + pub recipient_token_account: &'b solana_account_info::AccountInfo<'a>, + /// SPL program for input token transfers + pub token_program: &'b solana_account_info::AccountInfo<'a>, +} + +/// `collect_migrate_fee` CPI instruction. +pub struct CollectMigrateFeeCpi<'a, 'b> { + /// The program to invoke. + pub __program: &'b solana_account_info::AccountInfo<'a>, + /// Only migrate_fee_owner saved in global_config can collect migrate fee now + pub owner: &'b solana_account_info::AccountInfo<'a>, + + pub authority: &'b solana_account_info::AccountInfo<'a>, + /// Pool state stores accumulated protocol fee amount + pub pool_state: &'b solana_account_info::AccountInfo<'a>, + /// Global config account stores owner + pub global_config: &'b solana_account_info::AccountInfo<'a>, + /// The address that holds pool tokens for quote token + pub quote_vault: &'b solana_account_info::AccountInfo<'a>, + /// The mint of quote token vault + pub quote_mint: &'b solana_account_info::AccountInfo<'a>, + /// The address that receives the collected quote token fees + pub recipient_token_account: &'b solana_account_info::AccountInfo<'a>, + /// SPL program for input token transfers + pub token_program: &'b solana_account_info::AccountInfo<'a>, +} + +impl<'a, 'b> CollectMigrateFeeCpi<'a, 'b> { + pub fn new( + program: &'b solana_account_info::AccountInfo<'a>, + accounts: CollectMigrateFeeCpiAccounts<'a, 'b>, + ) -> Self { + Self { + __program: program, + owner: accounts.owner, + authority: accounts.authority, + pool_state: accounts.pool_state, + global_config: accounts.global_config, + quote_vault: accounts.quote_vault, + quote_mint: accounts.quote_mint, + recipient_token_account: accounts.recipient_token_account, + token_program: accounts.token_program, + } + } + #[inline(always)] + pub fn invoke(&self) -> solana_program_error::ProgramResult { + self.invoke_signed_with_remaining_accounts(&[], &[]) + } + #[inline(always)] + pub fn invoke_with_remaining_accounts( + &self, + remaining_accounts: &[(&'b solana_account_info::AccountInfo<'a>, bool, bool)], + ) -> solana_program_error::ProgramResult { + self.invoke_signed_with_remaining_accounts(&[], remaining_accounts) + } + #[inline(always)] + pub fn invoke_signed(&self, signers_seeds: &[&[&[u8]]]) -> solana_program_error::ProgramResult { + self.invoke_signed_with_remaining_accounts(signers_seeds, &[]) + } + #[allow(clippy::arithmetic_side_effects)] + #[allow(clippy::clone_on_copy)] + #[allow(clippy::vec_init_then_push)] + pub fn invoke_signed_with_remaining_accounts( + &self, + signers_seeds: &[&[&[u8]]], + remaining_accounts: &[(&'b solana_account_info::AccountInfo<'a>, bool, bool)], + ) -> solana_program_error::ProgramResult { + let mut accounts = Vec::with_capacity(8 + remaining_accounts.len()); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.owner.key, + true, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.authority.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + *self.pool_state.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.global_config.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + *self.quote_vault.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.quote_mint.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + *self.recipient_token_account.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.token_program.key, + false, + )); + remaining_accounts.iter().for_each(|remaining_account| { + accounts.push(solana_instruction::AccountMeta { + pubkey: *remaining_account.0.key, + is_signer: remaining_account.1, + is_writable: remaining_account.2, + }) + }); + let data = CollectMigrateFeeInstructionData::new() + .try_to_vec() + .unwrap(); + + let instruction = solana_instruction::Instruction { + program_id: crate::RAYDIUM_LAUNCHPAD_ID, + accounts, + data, + }; + let mut account_infos = Vec::with_capacity(9 + remaining_accounts.len()); + account_infos.push(self.__program.clone()); + account_infos.push(self.owner.clone()); + account_infos.push(self.authority.clone()); + account_infos.push(self.pool_state.clone()); + account_infos.push(self.global_config.clone()); + account_infos.push(self.quote_vault.clone()); + account_infos.push(self.quote_mint.clone()); + account_infos.push(self.recipient_token_account.clone()); + account_infos.push(self.token_program.clone()); + remaining_accounts + .iter() + .for_each(|remaining_account| account_infos.push(remaining_account.0.clone())); + + if signers_seeds.is_empty() { + solana_cpi::invoke(&instruction, &account_infos) + } else { + solana_cpi::invoke_signed(&instruction, &account_infos, signers_seeds) + } + } +} + +/// Instruction builder for `CollectMigrateFee` via CPI. +/// +/// ### Accounts: +/// +/// 0. `[signer]` owner +/// 1. `[]` authority +/// 2. `[writable]` pool_state +/// 3. `[]` global_config +/// 4. `[writable]` quote_vault +/// 5. `[]` quote_mint +/// 6. `[writable]` recipient_token_account +/// 7. `[]` token_program +#[derive(Clone, Debug)] +pub struct CollectMigrateFeeCpiBuilder<'a, 'b> { + instruction: Box>, +} + +impl<'a, 'b> CollectMigrateFeeCpiBuilder<'a, 'b> { + pub fn new(program: &'b solana_account_info::AccountInfo<'a>) -> Self { + let instruction = Box::new(CollectMigrateFeeCpiBuilderInstruction { + __program: program, + owner: None, + authority: None, + pool_state: None, + global_config: None, + quote_vault: None, + quote_mint: None, + recipient_token_account: None, + token_program: None, + __remaining_accounts: Vec::new(), + }); + Self { instruction } + } + /// Only migrate_fee_owner saved in global_config can collect migrate fee now + #[inline(always)] + pub fn owner(&mut self, owner: &'b solana_account_info::AccountInfo<'a>) -> &mut Self { + self.instruction.owner = Some(owner); + self + } + #[inline(always)] + pub fn authority(&mut self, authority: &'b solana_account_info::AccountInfo<'a>) -> &mut Self { + self.instruction.authority = Some(authority); + self + } + /// Pool state stores accumulated protocol fee amount + #[inline(always)] + pub fn pool_state( + &mut self, + pool_state: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.pool_state = Some(pool_state); + self + } + /// Global config account stores owner + #[inline(always)] + pub fn global_config( + &mut self, + global_config: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.global_config = Some(global_config); + self + } + /// The address that holds pool tokens for quote token + #[inline(always)] + pub fn quote_vault( + &mut self, + quote_vault: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.quote_vault = Some(quote_vault); + self + } + /// The mint of quote token vault + #[inline(always)] + pub fn quote_mint( + &mut self, + quote_mint: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.quote_mint = Some(quote_mint); + self + } + /// The address that receives the collected quote token fees + #[inline(always)] + pub fn recipient_token_account( + &mut self, + recipient_token_account: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.recipient_token_account = Some(recipient_token_account); + self + } + /// SPL program for input token transfers + #[inline(always)] + pub fn token_program( + &mut self, + token_program: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.token_program = Some(token_program); + self + } + /// Add an additional account to the instruction. + #[inline(always)] + pub fn add_remaining_account( + &mut self, + account: &'b solana_account_info::AccountInfo<'a>, + is_writable: bool, + is_signer: bool, + ) -> &mut Self { + self.instruction + .__remaining_accounts + .push((account, is_writable, is_signer)); + self + } + /// Add additional accounts to the instruction. + /// + /// Each account is represented by a tuple of the `AccountInfo`, a `bool` indicating whether the account is writable or not, + /// and a `bool` indicating whether the account is a signer or not. + #[inline(always)] + pub fn add_remaining_accounts( + &mut self, + accounts: &[(&'b solana_account_info::AccountInfo<'a>, bool, bool)], + ) -> &mut Self { + self.instruction + .__remaining_accounts + .extend_from_slice(accounts); + self + } + #[inline(always)] + pub fn invoke(&self) -> solana_program_error::ProgramResult { + self.invoke_signed(&[]) + } + #[allow(clippy::clone_on_copy)] + #[allow(clippy::vec_init_then_push)] + pub fn invoke_signed(&self, signers_seeds: &[&[&[u8]]]) -> solana_program_error::ProgramResult { + let instruction = CollectMigrateFeeCpi { + __program: self.instruction.__program, + + owner: self.instruction.owner.expect("owner is not set"), + + authority: self.instruction.authority.expect("authority is not set"), + + pool_state: self.instruction.pool_state.expect("pool_state is not set"), + + global_config: self + .instruction + .global_config + .expect("global_config is not set"), + + quote_vault: self + .instruction + .quote_vault + .expect("quote_vault is not set"), + + quote_mint: self.instruction.quote_mint.expect("quote_mint is not set"), + + recipient_token_account: self + .instruction + .recipient_token_account + .expect("recipient_token_account is not set"), + + token_program: self + .instruction + .token_program + .expect("token_program is not set"), + }; + instruction.invoke_signed_with_remaining_accounts( + signers_seeds, + &self.instruction.__remaining_accounts, + ) + } +} + +#[derive(Clone, Debug)] +struct CollectMigrateFeeCpiBuilderInstruction<'a, 'b> { + __program: &'b solana_account_info::AccountInfo<'a>, + owner: Option<&'b solana_account_info::AccountInfo<'a>>, + authority: Option<&'b solana_account_info::AccountInfo<'a>>, + pool_state: Option<&'b solana_account_info::AccountInfo<'a>>, + global_config: Option<&'b solana_account_info::AccountInfo<'a>>, + quote_vault: Option<&'b solana_account_info::AccountInfo<'a>>, + quote_mint: Option<&'b solana_account_info::AccountInfo<'a>>, + recipient_token_account: Option<&'b solana_account_info::AccountInfo<'a>>, + token_program: Option<&'b solana_account_info::AccountInfo<'a>>, + /// Additional instruction accounts `(AccountInfo, is_writable, is_signer)`. + __remaining_accounts: Vec<(&'b solana_account_info::AccountInfo<'a>, bool, bool)>, +} diff --git a/e2e/raydium-launchpad/src/generated/instructions/create_config.rs b/e2e/raydium-launchpad/src/generated/instructions/create_config.rs new file mode 100644 index 0000000..f3c1149 --- /dev/null +++ b/e2e/raydium-launchpad/src/generated/instructions/create_config.rs @@ -0,0 +1,712 @@ +//! This code was AUTOGENERATED using the codama library. +//! Please DO NOT EDIT THIS FILE, instead use visitors +//! to add features, then rerun codama to update it. +//! +//! +//! + +use borsh::BorshDeserialize; +use borsh::BorshSerialize; + +pub const CREATE_CONFIG_DISCRIMINATOR: [u8; 8] = [201, 207, 243, 114, 75, 111, 47, 189]; + +/// Accounts. +#[derive(Debug)] +pub struct CreateConfig { + /// The protocol owner/admin account + /// Must match the predefined admin address + /// Has authority to create and modify protocol configurations + pub owner: solana_address::Address, + /// Global configuration account that stores protocol-wide settings + /// PDA generated using GLOBAL_CONFIG_SEED, quote token mint, and curve type + /// Stores fee rates and protocol parameters + pub global_config: solana_address::Address, + /// The mint address of the quote token (token used for buying) + /// This will be the standard token used for all pools with this config + pub quote_token_mint: solana_address::Address, + /// Account that will receive protocol fees + pub protocol_fee_owner: solana_address::Address, + /// Account that will receive migrate fees + pub migrate_fee_owner: solana_address::Address, + /// The control wallet address for migrating to amm + pub migrate_to_amm_wallet: solana_address::Address, + /// The control wallet address for migrating to cpswap + pub migrate_to_cpswap_wallet: solana_address::Address, + /// Required for account creation + pub system_program: solana_address::Address, +} + +impl CreateConfig { + pub fn instruction( + &self, + args: CreateConfigInstructionArgs, + ) -> solana_instruction::Instruction { + self.instruction_with_remaining_accounts(args, &[]) + } + #[allow(clippy::arithmetic_side_effects)] + #[allow(clippy::vec_init_then_push)] + pub fn instruction_with_remaining_accounts( + &self, + args: CreateConfigInstructionArgs, + remaining_accounts: &[solana_instruction::AccountMeta], + ) -> solana_instruction::Instruction { + let mut accounts = Vec::with_capacity(8 + remaining_accounts.len()); + accounts.push(solana_instruction::AccountMeta::new(self.owner, true)); + accounts.push(solana_instruction::AccountMeta::new( + self.global_config, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.quote_token_mint, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.protocol_fee_owner, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.migrate_fee_owner, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.migrate_to_amm_wallet, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.migrate_to_cpswap_wallet, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.system_program, + false, + )); + accounts.extend_from_slice(remaining_accounts); + let mut data = CreateConfigInstructionData::new().try_to_vec().unwrap(); + let mut args = args.try_to_vec().unwrap(); + data.append(&mut args); + + solana_instruction::Instruction { + program_id: crate::RAYDIUM_LAUNCHPAD_ID, + accounts, + data, + } + } +} + +#[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] +pub struct CreateConfigInstructionData { + discriminator: [u8; 8], +} + +impl CreateConfigInstructionData { + pub fn new() -> Self { + Self { + discriminator: [201, 207, 243, 114, 75, 111, 47, 189], + } + } + + pub(crate) fn try_to_vec(&self) -> Result, std::io::Error> { + borsh::to_vec(self) + } +} + +impl Default for CreateConfigInstructionData { + fn default() -> Self { + Self::new() + } +} + +#[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] +pub struct CreateConfigInstructionArgs { + pub curve_type: u8, + pub index: u16, + pub migrate_fee: u64, + pub trade_fee_rate: u64, +} + +impl CreateConfigInstructionArgs { + pub(crate) fn try_to_vec(&self) -> Result, std::io::Error> { + borsh::to_vec(self) + } +} + +/// Instruction builder for `CreateConfig`. +/// +/// ### Accounts: +/// +/// 0. `[writable, signer, optional]` owner (default to `GThUX1Atko4tqhN2NaiTazWSeFWMuiUvfFnyJyUghFMJ`) +/// 1. `[writable]` global_config +/// 2. `[]` quote_token_mint +/// 3. `[]` protocol_fee_owner +/// 4. `[]` migrate_fee_owner +/// 5. `[]` migrate_to_amm_wallet +/// 6. `[]` migrate_to_cpswap_wallet +/// 7. `[optional]` system_program (default to `11111111111111111111111111111111`) +#[derive(Clone, Debug, Default)] +pub struct CreateConfigBuilder { + owner: Option, + global_config: Option, + quote_token_mint: Option, + protocol_fee_owner: Option, + migrate_fee_owner: Option, + migrate_to_amm_wallet: Option, + migrate_to_cpswap_wallet: Option, + system_program: Option, + curve_type: Option, + index: Option, + migrate_fee: Option, + trade_fee_rate: Option, + __remaining_accounts: Vec, +} + +impl CreateConfigBuilder { + pub fn new() -> Self { + Self::default() + } + /// `[optional account, default to 'GThUX1Atko4tqhN2NaiTazWSeFWMuiUvfFnyJyUghFMJ']` + /// The protocol owner/admin account + /// Must match the predefined admin address + /// Has authority to create and modify protocol configurations + #[inline(always)] + pub fn owner(&mut self, owner: solana_address::Address) -> &mut Self { + self.owner = Some(owner); + self + } + /// Global configuration account that stores protocol-wide settings + /// PDA generated using GLOBAL_CONFIG_SEED, quote token mint, and curve type + /// Stores fee rates and protocol parameters + #[inline(always)] + pub fn global_config(&mut self, global_config: solana_address::Address) -> &mut Self { + self.global_config = Some(global_config); + self + } + /// The mint address of the quote token (token used for buying) + /// This will be the standard token used for all pools with this config + #[inline(always)] + pub fn quote_token_mint(&mut self, quote_token_mint: solana_address::Address) -> &mut Self { + self.quote_token_mint = Some(quote_token_mint); + self + } + /// Account that will receive protocol fees + #[inline(always)] + pub fn protocol_fee_owner(&mut self, protocol_fee_owner: solana_address::Address) -> &mut Self { + self.protocol_fee_owner = Some(protocol_fee_owner); + self + } + /// Account that will receive migrate fees + #[inline(always)] + pub fn migrate_fee_owner(&mut self, migrate_fee_owner: solana_address::Address) -> &mut Self { + self.migrate_fee_owner = Some(migrate_fee_owner); + self + } + /// The control wallet address for migrating to amm + #[inline(always)] + pub fn migrate_to_amm_wallet( + &mut self, + migrate_to_amm_wallet: solana_address::Address, + ) -> &mut Self { + self.migrate_to_amm_wallet = Some(migrate_to_amm_wallet); + self + } + /// The control wallet address for migrating to cpswap + #[inline(always)] + pub fn migrate_to_cpswap_wallet( + &mut self, + migrate_to_cpswap_wallet: solana_address::Address, + ) -> &mut Self { + self.migrate_to_cpswap_wallet = Some(migrate_to_cpswap_wallet); + self + } + /// `[optional account, default to '11111111111111111111111111111111']` + /// Required for account creation + #[inline(always)] + pub fn system_program(&mut self, system_program: solana_address::Address) -> &mut Self { + self.system_program = Some(system_program); + self + } + #[inline(always)] + pub fn curve_type(&mut self, curve_type: u8) -> &mut Self { + self.curve_type = Some(curve_type); + self + } + #[inline(always)] + pub fn index(&mut self, index: u16) -> &mut Self { + self.index = Some(index); + self + } + #[inline(always)] + pub fn migrate_fee(&mut self, migrate_fee: u64) -> &mut Self { + self.migrate_fee = Some(migrate_fee); + self + } + #[inline(always)] + pub fn trade_fee_rate(&mut self, trade_fee_rate: u64) -> &mut Self { + self.trade_fee_rate = Some(trade_fee_rate); + self + } + /// Add an additional account to the instruction. + #[inline(always)] + pub fn add_remaining_account(&mut self, account: solana_instruction::AccountMeta) -> &mut Self { + self.__remaining_accounts.push(account); + self + } + /// Add additional accounts to the instruction. + #[inline(always)] + pub fn add_remaining_accounts( + &mut self, + accounts: &[solana_instruction::AccountMeta], + ) -> &mut Self { + self.__remaining_accounts.extend_from_slice(accounts); + self + } + #[allow(clippy::clone_on_copy)] + pub fn instruction(&self) -> solana_instruction::Instruction { + let accounts = CreateConfig { + owner: self.owner.unwrap_or(solana_address::address!( + "GThUX1Atko4tqhN2NaiTazWSeFWMuiUvfFnyJyUghFMJ" + )), + global_config: self.global_config.expect("global_config is not set"), + quote_token_mint: self.quote_token_mint.expect("quote_token_mint is not set"), + protocol_fee_owner: self + .protocol_fee_owner + .expect("protocol_fee_owner is not set"), + migrate_fee_owner: self + .migrate_fee_owner + .expect("migrate_fee_owner is not set"), + migrate_to_amm_wallet: self + .migrate_to_amm_wallet + .expect("migrate_to_amm_wallet is not set"), + migrate_to_cpswap_wallet: self + .migrate_to_cpswap_wallet + .expect("migrate_to_cpswap_wallet is not set"), + system_program: self + .system_program + .unwrap_or(solana_address::address!("11111111111111111111111111111111")), + }; + let args = CreateConfigInstructionArgs { + curve_type: self.curve_type.clone().expect("curve_type is not set"), + index: self.index.clone().expect("index is not set"), + migrate_fee: self.migrate_fee.clone().expect("migrate_fee is not set"), + trade_fee_rate: self + .trade_fee_rate + .clone() + .expect("trade_fee_rate is not set"), + }; + + accounts.instruction_with_remaining_accounts(args, &self.__remaining_accounts) + } +} + +/// `create_config` CPI accounts. +pub struct CreateConfigCpiAccounts<'a, 'b> { + /// The protocol owner/admin account + /// Must match the predefined admin address + /// Has authority to create and modify protocol configurations + pub owner: &'b solana_account_info::AccountInfo<'a>, + /// Global configuration account that stores protocol-wide settings + /// PDA generated using GLOBAL_CONFIG_SEED, quote token mint, and curve type + /// Stores fee rates and protocol parameters + pub global_config: &'b solana_account_info::AccountInfo<'a>, + /// The mint address of the quote token (token used for buying) + /// This will be the standard token used for all pools with this config + pub quote_token_mint: &'b solana_account_info::AccountInfo<'a>, + /// Account that will receive protocol fees + pub protocol_fee_owner: &'b solana_account_info::AccountInfo<'a>, + /// Account that will receive migrate fees + pub migrate_fee_owner: &'b solana_account_info::AccountInfo<'a>, + /// The control wallet address for migrating to amm + pub migrate_to_amm_wallet: &'b solana_account_info::AccountInfo<'a>, + /// The control wallet address for migrating to cpswap + pub migrate_to_cpswap_wallet: &'b solana_account_info::AccountInfo<'a>, + /// Required for account creation + pub system_program: &'b solana_account_info::AccountInfo<'a>, +} + +/// `create_config` CPI instruction. +pub struct CreateConfigCpi<'a, 'b> { + /// The program to invoke. + pub __program: &'b solana_account_info::AccountInfo<'a>, + /// The protocol owner/admin account + /// Must match the predefined admin address + /// Has authority to create and modify protocol configurations + pub owner: &'b solana_account_info::AccountInfo<'a>, + /// Global configuration account that stores protocol-wide settings + /// PDA generated using GLOBAL_CONFIG_SEED, quote token mint, and curve type + /// Stores fee rates and protocol parameters + pub global_config: &'b solana_account_info::AccountInfo<'a>, + /// The mint address of the quote token (token used for buying) + /// This will be the standard token used for all pools with this config + pub quote_token_mint: &'b solana_account_info::AccountInfo<'a>, + /// Account that will receive protocol fees + pub protocol_fee_owner: &'b solana_account_info::AccountInfo<'a>, + /// Account that will receive migrate fees + pub migrate_fee_owner: &'b solana_account_info::AccountInfo<'a>, + /// The control wallet address for migrating to amm + pub migrate_to_amm_wallet: &'b solana_account_info::AccountInfo<'a>, + /// The control wallet address for migrating to cpswap + pub migrate_to_cpswap_wallet: &'b solana_account_info::AccountInfo<'a>, + /// Required for account creation + pub system_program: &'b solana_account_info::AccountInfo<'a>, + /// The arguments for the instruction. + pub __args: CreateConfigInstructionArgs, +} + +impl<'a, 'b> CreateConfigCpi<'a, 'b> { + pub fn new( + program: &'b solana_account_info::AccountInfo<'a>, + accounts: CreateConfigCpiAccounts<'a, 'b>, + args: CreateConfigInstructionArgs, + ) -> Self { + Self { + __program: program, + owner: accounts.owner, + global_config: accounts.global_config, + quote_token_mint: accounts.quote_token_mint, + protocol_fee_owner: accounts.protocol_fee_owner, + migrate_fee_owner: accounts.migrate_fee_owner, + migrate_to_amm_wallet: accounts.migrate_to_amm_wallet, + migrate_to_cpswap_wallet: accounts.migrate_to_cpswap_wallet, + system_program: accounts.system_program, + __args: args, + } + } + #[inline(always)] + pub fn invoke(&self) -> solana_program_error::ProgramResult { + self.invoke_signed_with_remaining_accounts(&[], &[]) + } + #[inline(always)] + pub fn invoke_with_remaining_accounts( + &self, + remaining_accounts: &[(&'b solana_account_info::AccountInfo<'a>, bool, bool)], + ) -> solana_program_error::ProgramResult { + self.invoke_signed_with_remaining_accounts(&[], remaining_accounts) + } + #[inline(always)] + pub fn invoke_signed(&self, signers_seeds: &[&[&[u8]]]) -> solana_program_error::ProgramResult { + self.invoke_signed_with_remaining_accounts(signers_seeds, &[]) + } + #[allow(clippy::arithmetic_side_effects)] + #[allow(clippy::clone_on_copy)] + #[allow(clippy::vec_init_then_push)] + pub fn invoke_signed_with_remaining_accounts( + &self, + signers_seeds: &[&[&[u8]]], + remaining_accounts: &[(&'b solana_account_info::AccountInfo<'a>, bool, bool)], + ) -> solana_program_error::ProgramResult { + let mut accounts = Vec::with_capacity(8 + remaining_accounts.len()); + accounts.push(solana_instruction::AccountMeta::new(*self.owner.key, true)); + accounts.push(solana_instruction::AccountMeta::new( + *self.global_config.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.quote_token_mint.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.protocol_fee_owner.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.migrate_fee_owner.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.migrate_to_amm_wallet.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.migrate_to_cpswap_wallet.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.system_program.key, + false, + )); + remaining_accounts.iter().for_each(|remaining_account| { + accounts.push(solana_instruction::AccountMeta { + pubkey: *remaining_account.0.key, + is_signer: remaining_account.1, + is_writable: remaining_account.2, + }) + }); + let mut data = CreateConfigInstructionData::new().try_to_vec().unwrap(); + let mut args = self.__args.try_to_vec().unwrap(); + data.append(&mut args); + + let instruction = solana_instruction::Instruction { + program_id: crate::RAYDIUM_LAUNCHPAD_ID, + accounts, + data, + }; + let mut account_infos = Vec::with_capacity(9 + remaining_accounts.len()); + account_infos.push(self.__program.clone()); + account_infos.push(self.owner.clone()); + account_infos.push(self.global_config.clone()); + account_infos.push(self.quote_token_mint.clone()); + account_infos.push(self.protocol_fee_owner.clone()); + account_infos.push(self.migrate_fee_owner.clone()); + account_infos.push(self.migrate_to_amm_wallet.clone()); + account_infos.push(self.migrate_to_cpswap_wallet.clone()); + account_infos.push(self.system_program.clone()); + remaining_accounts + .iter() + .for_each(|remaining_account| account_infos.push(remaining_account.0.clone())); + + if signers_seeds.is_empty() { + solana_cpi::invoke(&instruction, &account_infos) + } else { + solana_cpi::invoke_signed(&instruction, &account_infos, signers_seeds) + } + } +} + +/// Instruction builder for `CreateConfig` via CPI. +/// +/// ### Accounts: +/// +/// 0. `[writable, signer]` owner +/// 1. `[writable]` global_config +/// 2. `[]` quote_token_mint +/// 3. `[]` protocol_fee_owner +/// 4. `[]` migrate_fee_owner +/// 5. `[]` migrate_to_amm_wallet +/// 6. `[]` migrate_to_cpswap_wallet +/// 7. `[]` system_program +#[derive(Clone, Debug)] +pub struct CreateConfigCpiBuilder<'a, 'b> { + instruction: Box>, +} + +impl<'a, 'b> CreateConfigCpiBuilder<'a, 'b> { + pub fn new(program: &'b solana_account_info::AccountInfo<'a>) -> Self { + let instruction = Box::new(CreateConfigCpiBuilderInstruction { + __program: program, + owner: None, + global_config: None, + quote_token_mint: None, + protocol_fee_owner: None, + migrate_fee_owner: None, + migrate_to_amm_wallet: None, + migrate_to_cpswap_wallet: None, + system_program: None, + curve_type: None, + index: None, + migrate_fee: None, + trade_fee_rate: None, + __remaining_accounts: Vec::new(), + }); + Self { instruction } + } + /// The protocol owner/admin account + /// Must match the predefined admin address + /// Has authority to create and modify protocol configurations + #[inline(always)] + pub fn owner(&mut self, owner: &'b solana_account_info::AccountInfo<'a>) -> &mut Self { + self.instruction.owner = Some(owner); + self + } + /// Global configuration account that stores protocol-wide settings + /// PDA generated using GLOBAL_CONFIG_SEED, quote token mint, and curve type + /// Stores fee rates and protocol parameters + #[inline(always)] + pub fn global_config( + &mut self, + global_config: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.global_config = Some(global_config); + self + } + /// The mint address of the quote token (token used for buying) + /// This will be the standard token used for all pools with this config + #[inline(always)] + pub fn quote_token_mint( + &mut self, + quote_token_mint: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.quote_token_mint = Some(quote_token_mint); + self + } + /// Account that will receive protocol fees + #[inline(always)] + pub fn protocol_fee_owner( + &mut self, + protocol_fee_owner: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.protocol_fee_owner = Some(protocol_fee_owner); + self + } + /// Account that will receive migrate fees + #[inline(always)] + pub fn migrate_fee_owner( + &mut self, + migrate_fee_owner: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.migrate_fee_owner = Some(migrate_fee_owner); + self + } + /// The control wallet address for migrating to amm + #[inline(always)] + pub fn migrate_to_amm_wallet( + &mut self, + migrate_to_amm_wallet: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.migrate_to_amm_wallet = Some(migrate_to_amm_wallet); + self + } + /// The control wallet address for migrating to cpswap + #[inline(always)] + pub fn migrate_to_cpswap_wallet( + &mut self, + migrate_to_cpswap_wallet: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.migrate_to_cpswap_wallet = Some(migrate_to_cpswap_wallet); + self + } + /// Required for account creation + #[inline(always)] + pub fn system_program( + &mut self, + system_program: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.system_program = Some(system_program); + self + } + #[inline(always)] + pub fn curve_type(&mut self, curve_type: u8) -> &mut Self { + self.instruction.curve_type = Some(curve_type); + self + } + #[inline(always)] + pub fn index(&mut self, index: u16) -> &mut Self { + self.instruction.index = Some(index); + self + } + #[inline(always)] + pub fn migrate_fee(&mut self, migrate_fee: u64) -> &mut Self { + self.instruction.migrate_fee = Some(migrate_fee); + self + } + #[inline(always)] + pub fn trade_fee_rate(&mut self, trade_fee_rate: u64) -> &mut Self { + self.instruction.trade_fee_rate = Some(trade_fee_rate); + self + } + /// Add an additional account to the instruction. + #[inline(always)] + pub fn add_remaining_account( + &mut self, + account: &'b solana_account_info::AccountInfo<'a>, + is_writable: bool, + is_signer: bool, + ) -> &mut Self { + self.instruction + .__remaining_accounts + .push((account, is_writable, is_signer)); + self + } + /// Add additional accounts to the instruction. + /// + /// Each account is represented by a tuple of the `AccountInfo`, a `bool` indicating whether the account is writable or not, + /// and a `bool` indicating whether the account is a signer or not. + #[inline(always)] + pub fn add_remaining_accounts( + &mut self, + accounts: &[(&'b solana_account_info::AccountInfo<'a>, bool, bool)], + ) -> &mut Self { + self.instruction + .__remaining_accounts + .extend_from_slice(accounts); + self + } + #[inline(always)] + pub fn invoke(&self) -> solana_program_error::ProgramResult { + self.invoke_signed(&[]) + } + #[allow(clippy::clone_on_copy)] + #[allow(clippy::vec_init_then_push)] + pub fn invoke_signed(&self, signers_seeds: &[&[&[u8]]]) -> solana_program_error::ProgramResult { + let args = CreateConfigInstructionArgs { + curve_type: self + .instruction + .curve_type + .clone() + .expect("curve_type is not set"), + index: self.instruction.index.clone().expect("index is not set"), + migrate_fee: self + .instruction + .migrate_fee + .clone() + .expect("migrate_fee is not set"), + trade_fee_rate: self + .instruction + .trade_fee_rate + .clone() + .expect("trade_fee_rate is not set"), + }; + let instruction = CreateConfigCpi { + __program: self.instruction.__program, + + owner: self.instruction.owner.expect("owner is not set"), + + global_config: self + .instruction + .global_config + .expect("global_config is not set"), + + quote_token_mint: self + .instruction + .quote_token_mint + .expect("quote_token_mint is not set"), + + protocol_fee_owner: self + .instruction + .protocol_fee_owner + .expect("protocol_fee_owner is not set"), + + migrate_fee_owner: self + .instruction + .migrate_fee_owner + .expect("migrate_fee_owner is not set"), + + migrate_to_amm_wallet: self + .instruction + .migrate_to_amm_wallet + .expect("migrate_to_amm_wallet is not set"), + + migrate_to_cpswap_wallet: self + .instruction + .migrate_to_cpswap_wallet + .expect("migrate_to_cpswap_wallet is not set"), + + system_program: self + .instruction + .system_program + .expect("system_program is not set"), + __args: args, + }; + instruction.invoke_signed_with_remaining_accounts( + signers_seeds, + &self.instruction.__remaining_accounts, + ) + } +} + +#[derive(Clone, Debug)] +struct CreateConfigCpiBuilderInstruction<'a, 'b> { + __program: &'b solana_account_info::AccountInfo<'a>, + owner: Option<&'b solana_account_info::AccountInfo<'a>>, + global_config: Option<&'b solana_account_info::AccountInfo<'a>>, + quote_token_mint: Option<&'b solana_account_info::AccountInfo<'a>>, + protocol_fee_owner: Option<&'b solana_account_info::AccountInfo<'a>>, + migrate_fee_owner: Option<&'b solana_account_info::AccountInfo<'a>>, + migrate_to_amm_wallet: Option<&'b solana_account_info::AccountInfo<'a>>, + migrate_to_cpswap_wallet: Option<&'b solana_account_info::AccountInfo<'a>>, + system_program: Option<&'b solana_account_info::AccountInfo<'a>>, + curve_type: Option, + index: Option, + migrate_fee: Option, + trade_fee_rate: Option, + /// Additional instruction accounts `(AccountInfo, is_writable, is_signer)`. + __remaining_accounts: Vec<(&'b solana_account_info::AccountInfo<'a>, bool, bool)>, +} diff --git a/e2e/raydium-launchpad/src/generated/instructions/create_platform_config.rs b/e2e/raydium-launchpad/src/generated/instructions/create_platform_config.rs new file mode 100644 index 0000000..cc4b333 --- /dev/null +++ b/e2e/raydium-launchpad/src/generated/instructions/create_platform_config.rs @@ -0,0 +1,579 @@ +//! This code was AUTOGENERATED using the codama library. +//! Please DO NOT EDIT THIS FILE, instead use visitors +//! to add features, then rerun codama to update it. +//! +//! +//! + +use crate::generated::types::MigrateNftInfo; +use borsh::BorshDeserialize; +use borsh::BorshSerialize; + +pub const CREATE_PLATFORM_CONFIG_DISCRIMINATOR: [u8; 8] = [176, 90, 196, 175, 253, 113, 220, 20]; + +/// Accounts. +#[derive(Debug)] +pub struct CreatePlatformConfig { + /// The account paying for the initialization costs + pub platform_admin: solana_address::Address, + + pub platform_fee_wallet: solana_address::Address, + + pub platform_nft_wallet: solana_address::Address, + /// The platform config account + pub platform_config: solana_address::Address, + /// Required for account creation + pub system_program: solana_address::Address, +} + +impl CreatePlatformConfig { + pub fn instruction( + &self, + args: CreatePlatformConfigInstructionArgs, + ) -> solana_instruction::Instruction { + self.instruction_with_remaining_accounts(args, &[]) + } + #[allow(clippy::arithmetic_side_effects)] + #[allow(clippy::vec_init_then_push)] + pub fn instruction_with_remaining_accounts( + &self, + args: CreatePlatformConfigInstructionArgs, + remaining_accounts: &[solana_instruction::AccountMeta], + ) -> solana_instruction::Instruction { + let mut accounts = Vec::with_capacity(5 + remaining_accounts.len()); + accounts.push(solana_instruction::AccountMeta::new( + self.platform_admin, + true, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.platform_fee_wallet, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.platform_nft_wallet, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + self.platform_config, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.system_program, + false, + )); + accounts.extend_from_slice(remaining_accounts); + let mut data = CreatePlatformConfigInstructionData::new() + .try_to_vec() + .unwrap(); + let mut args = args.try_to_vec().unwrap(); + data.append(&mut args); + + solana_instruction::Instruction { + program_id: crate::RAYDIUM_LAUNCHPAD_ID, + accounts, + data, + } + } +} + +#[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] +pub struct CreatePlatformConfigInstructionData { + discriminator: [u8; 8], +} + +impl CreatePlatformConfigInstructionData { + pub fn new() -> Self { + Self { + discriminator: [176, 90, 196, 175, 253, 113, 220, 20], + } + } + + pub(crate) fn try_to_vec(&self) -> Result, std::io::Error> { + borsh::to_vec(self) + } +} + +impl Default for CreatePlatformConfigInstructionData { + fn default() -> Self { + Self::new() + } +} + +#[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] +pub struct CreatePlatformConfigInstructionArgs { + pub migrate_nft_info: MigrateNftInfo, + pub fee_rate: u64, + pub name: String, + pub web: String, + pub img: String, +} + +impl CreatePlatformConfigInstructionArgs { + pub(crate) fn try_to_vec(&self) -> Result, std::io::Error> { + borsh::to_vec(self) + } +} + +/// Instruction builder for `CreatePlatformConfig`. +/// +/// ### Accounts: +/// +/// 0. `[writable, signer]` platform_admin +/// 1. `[]` platform_fee_wallet +/// 2. `[]` platform_nft_wallet +/// 3. `[writable]` platform_config +/// 4. `[optional]` system_program (default to `11111111111111111111111111111111`) +#[derive(Clone, Debug, Default)] +pub struct CreatePlatformConfigBuilder { + platform_admin: Option, + platform_fee_wallet: Option, + platform_nft_wallet: Option, + platform_config: Option, + system_program: Option, + migrate_nft_info: Option, + fee_rate: Option, + name: Option, + web: Option, + img: Option, + __remaining_accounts: Vec, +} + +impl CreatePlatformConfigBuilder { + pub fn new() -> Self { + Self::default() + } + /// The account paying for the initialization costs + #[inline(always)] + pub fn platform_admin(&mut self, platform_admin: solana_address::Address) -> &mut Self { + self.platform_admin = Some(platform_admin); + self + } + #[inline(always)] + pub fn platform_fee_wallet( + &mut self, + platform_fee_wallet: solana_address::Address, + ) -> &mut Self { + self.platform_fee_wallet = Some(platform_fee_wallet); + self + } + #[inline(always)] + pub fn platform_nft_wallet( + &mut self, + platform_nft_wallet: solana_address::Address, + ) -> &mut Self { + self.platform_nft_wallet = Some(platform_nft_wallet); + self + } + /// The platform config account + #[inline(always)] + pub fn platform_config(&mut self, platform_config: solana_address::Address) -> &mut Self { + self.platform_config = Some(platform_config); + self + } + /// `[optional account, default to '11111111111111111111111111111111']` + /// Required for account creation + #[inline(always)] + pub fn system_program(&mut self, system_program: solana_address::Address) -> &mut Self { + self.system_program = Some(system_program); + self + } + #[inline(always)] + pub fn migrate_nft_info(&mut self, migrate_nft_info: MigrateNftInfo) -> &mut Self { + self.migrate_nft_info = Some(migrate_nft_info); + self + } + #[inline(always)] + pub fn fee_rate(&mut self, fee_rate: u64) -> &mut Self { + self.fee_rate = Some(fee_rate); + self + } + #[inline(always)] + pub fn name(&mut self, name: String) -> &mut Self { + self.name = Some(name); + self + } + #[inline(always)] + pub fn web(&mut self, web: String) -> &mut Self { + self.web = Some(web); + self + } + #[inline(always)] + pub fn img(&mut self, img: String) -> &mut Self { + self.img = Some(img); + self + } + /// Add an additional account to the instruction. + #[inline(always)] + pub fn add_remaining_account(&mut self, account: solana_instruction::AccountMeta) -> &mut Self { + self.__remaining_accounts.push(account); + self + } + /// Add additional accounts to the instruction. + #[inline(always)] + pub fn add_remaining_accounts( + &mut self, + accounts: &[solana_instruction::AccountMeta], + ) -> &mut Self { + self.__remaining_accounts.extend_from_slice(accounts); + self + } + #[allow(clippy::clone_on_copy)] + pub fn instruction(&self) -> solana_instruction::Instruction { + let accounts = CreatePlatformConfig { + platform_admin: self.platform_admin.expect("platform_admin is not set"), + platform_fee_wallet: self + .platform_fee_wallet + .expect("platform_fee_wallet is not set"), + platform_nft_wallet: self + .platform_nft_wallet + .expect("platform_nft_wallet is not set"), + platform_config: self.platform_config.expect("platform_config is not set"), + system_program: self + .system_program + .unwrap_or(solana_address::address!("11111111111111111111111111111111")), + }; + let args = CreatePlatformConfigInstructionArgs { + migrate_nft_info: self + .migrate_nft_info + .clone() + .expect("migrate_nft_info is not set"), + fee_rate: self.fee_rate.clone().expect("fee_rate is not set"), + name: self.name.clone().expect("name is not set"), + web: self.web.clone().expect("web is not set"), + img: self.img.clone().expect("img is not set"), + }; + + accounts.instruction_with_remaining_accounts(args, &self.__remaining_accounts) + } +} + +/// `create_platform_config` CPI accounts. +pub struct CreatePlatformConfigCpiAccounts<'a, 'b> { + /// The account paying for the initialization costs + pub platform_admin: &'b solana_account_info::AccountInfo<'a>, + + pub platform_fee_wallet: &'b solana_account_info::AccountInfo<'a>, + + pub platform_nft_wallet: &'b solana_account_info::AccountInfo<'a>, + /// The platform config account + pub platform_config: &'b solana_account_info::AccountInfo<'a>, + /// Required for account creation + pub system_program: &'b solana_account_info::AccountInfo<'a>, +} + +/// `create_platform_config` CPI instruction. +pub struct CreatePlatformConfigCpi<'a, 'b> { + /// The program to invoke. + pub __program: &'b solana_account_info::AccountInfo<'a>, + /// The account paying for the initialization costs + pub platform_admin: &'b solana_account_info::AccountInfo<'a>, + + pub platform_fee_wallet: &'b solana_account_info::AccountInfo<'a>, + + pub platform_nft_wallet: &'b solana_account_info::AccountInfo<'a>, + /// The platform config account + pub platform_config: &'b solana_account_info::AccountInfo<'a>, + /// Required for account creation + pub system_program: &'b solana_account_info::AccountInfo<'a>, + /// The arguments for the instruction. + pub __args: CreatePlatformConfigInstructionArgs, +} + +impl<'a, 'b> CreatePlatformConfigCpi<'a, 'b> { + pub fn new( + program: &'b solana_account_info::AccountInfo<'a>, + accounts: CreatePlatformConfigCpiAccounts<'a, 'b>, + args: CreatePlatformConfigInstructionArgs, + ) -> Self { + Self { + __program: program, + platform_admin: accounts.platform_admin, + platform_fee_wallet: accounts.platform_fee_wallet, + platform_nft_wallet: accounts.platform_nft_wallet, + platform_config: accounts.platform_config, + system_program: accounts.system_program, + __args: args, + } + } + #[inline(always)] + pub fn invoke(&self) -> solana_program_error::ProgramResult { + self.invoke_signed_with_remaining_accounts(&[], &[]) + } + #[inline(always)] + pub fn invoke_with_remaining_accounts( + &self, + remaining_accounts: &[(&'b solana_account_info::AccountInfo<'a>, bool, bool)], + ) -> solana_program_error::ProgramResult { + self.invoke_signed_with_remaining_accounts(&[], remaining_accounts) + } + #[inline(always)] + pub fn invoke_signed(&self, signers_seeds: &[&[&[u8]]]) -> solana_program_error::ProgramResult { + self.invoke_signed_with_remaining_accounts(signers_seeds, &[]) + } + #[allow(clippy::arithmetic_side_effects)] + #[allow(clippy::clone_on_copy)] + #[allow(clippy::vec_init_then_push)] + pub fn invoke_signed_with_remaining_accounts( + &self, + signers_seeds: &[&[&[u8]]], + remaining_accounts: &[(&'b solana_account_info::AccountInfo<'a>, bool, bool)], + ) -> solana_program_error::ProgramResult { + let mut accounts = Vec::with_capacity(5 + remaining_accounts.len()); + accounts.push(solana_instruction::AccountMeta::new( + *self.platform_admin.key, + true, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.platform_fee_wallet.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.platform_nft_wallet.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + *self.platform_config.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.system_program.key, + false, + )); + remaining_accounts.iter().for_each(|remaining_account| { + accounts.push(solana_instruction::AccountMeta { + pubkey: *remaining_account.0.key, + is_signer: remaining_account.1, + is_writable: remaining_account.2, + }) + }); + let mut data = CreatePlatformConfigInstructionData::new() + .try_to_vec() + .unwrap(); + let mut args = self.__args.try_to_vec().unwrap(); + data.append(&mut args); + + let instruction = solana_instruction::Instruction { + program_id: crate::RAYDIUM_LAUNCHPAD_ID, + accounts, + data, + }; + let mut account_infos = Vec::with_capacity(6 + remaining_accounts.len()); + account_infos.push(self.__program.clone()); + account_infos.push(self.platform_admin.clone()); + account_infos.push(self.platform_fee_wallet.clone()); + account_infos.push(self.platform_nft_wallet.clone()); + account_infos.push(self.platform_config.clone()); + account_infos.push(self.system_program.clone()); + remaining_accounts + .iter() + .for_each(|remaining_account| account_infos.push(remaining_account.0.clone())); + + if signers_seeds.is_empty() { + solana_cpi::invoke(&instruction, &account_infos) + } else { + solana_cpi::invoke_signed(&instruction, &account_infos, signers_seeds) + } + } +} + +/// Instruction builder for `CreatePlatformConfig` via CPI. +/// +/// ### Accounts: +/// +/// 0. `[writable, signer]` platform_admin +/// 1. `[]` platform_fee_wallet +/// 2. `[]` platform_nft_wallet +/// 3. `[writable]` platform_config +/// 4. `[]` system_program +#[derive(Clone, Debug)] +pub struct CreatePlatformConfigCpiBuilder<'a, 'b> { + instruction: Box>, +} + +impl<'a, 'b> CreatePlatformConfigCpiBuilder<'a, 'b> { + pub fn new(program: &'b solana_account_info::AccountInfo<'a>) -> Self { + let instruction = Box::new(CreatePlatformConfigCpiBuilderInstruction { + __program: program, + platform_admin: None, + platform_fee_wallet: None, + platform_nft_wallet: None, + platform_config: None, + system_program: None, + migrate_nft_info: None, + fee_rate: None, + name: None, + web: None, + img: None, + __remaining_accounts: Vec::new(), + }); + Self { instruction } + } + /// The account paying for the initialization costs + #[inline(always)] + pub fn platform_admin( + &mut self, + platform_admin: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.platform_admin = Some(platform_admin); + self + } + #[inline(always)] + pub fn platform_fee_wallet( + &mut self, + platform_fee_wallet: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.platform_fee_wallet = Some(platform_fee_wallet); + self + } + #[inline(always)] + pub fn platform_nft_wallet( + &mut self, + platform_nft_wallet: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.platform_nft_wallet = Some(platform_nft_wallet); + self + } + /// The platform config account + #[inline(always)] + pub fn platform_config( + &mut self, + platform_config: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.platform_config = Some(platform_config); + self + } + /// Required for account creation + #[inline(always)] + pub fn system_program( + &mut self, + system_program: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.system_program = Some(system_program); + self + } + #[inline(always)] + pub fn migrate_nft_info(&mut self, migrate_nft_info: MigrateNftInfo) -> &mut Self { + self.instruction.migrate_nft_info = Some(migrate_nft_info); + self + } + #[inline(always)] + pub fn fee_rate(&mut self, fee_rate: u64) -> &mut Self { + self.instruction.fee_rate = Some(fee_rate); + self + } + #[inline(always)] + pub fn name(&mut self, name: String) -> &mut Self { + self.instruction.name = Some(name); + self + } + #[inline(always)] + pub fn web(&mut self, web: String) -> &mut Self { + self.instruction.web = Some(web); + self + } + #[inline(always)] + pub fn img(&mut self, img: String) -> &mut Self { + self.instruction.img = Some(img); + self + } + /// Add an additional account to the instruction. + #[inline(always)] + pub fn add_remaining_account( + &mut self, + account: &'b solana_account_info::AccountInfo<'a>, + is_writable: bool, + is_signer: bool, + ) -> &mut Self { + self.instruction + .__remaining_accounts + .push((account, is_writable, is_signer)); + self + } + /// Add additional accounts to the instruction. + /// + /// Each account is represented by a tuple of the `AccountInfo`, a `bool` indicating whether the account is writable or not, + /// and a `bool` indicating whether the account is a signer or not. + #[inline(always)] + pub fn add_remaining_accounts( + &mut self, + accounts: &[(&'b solana_account_info::AccountInfo<'a>, bool, bool)], + ) -> &mut Self { + self.instruction + .__remaining_accounts + .extend_from_slice(accounts); + self + } + #[inline(always)] + pub fn invoke(&self) -> solana_program_error::ProgramResult { + self.invoke_signed(&[]) + } + #[allow(clippy::clone_on_copy)] + #[allow(clippy::vec_init_then_push)] + pub fn invoke_signed(&self, signers_seeds: &[&[&[u8]]]) -> solana_program_error::ProgramResult { + let args = CreatePlatformConfigInstructionArgs { + migrate_nft_info: self + .instruction + .migrate_nft_info + .clone() + .expect("migrate_nft_info is not set"), + fee_rate: self + .instruction + .fee_rate + .clone() + .expect("fee_rate is not set"), + name: self.instruction.name.clone().expect("name is not set"), + web: self.instruction.web.clone().expect("web is not set"), + img: self.instruction.img.clone().expect("img is not set"), + }; + let instruction = CreatePlatformConfigCpi { + __program: self.instruction.__program, + + platform_admin: self + .instruction + .platform_admin + .expect("platform_admin is not set"), + + platform_fee_wallet: self + .instruction + .platform_fee_wallet + .expect("platform_fee_wallet is not set"), + + platform_nft_wallet: self + .instruction + .platform_nft_wallet + .expect("platform_nft_wallet is not set"), + + platform_config: self + .instruction + .platform_config + .expect("platform_config is not set"), + + system_program: self + .instruction + .system_program + .expect("system_program is not set"), + __args: args, + }; + instruction.invoke_signed_with_remaining_accounts( + signers_seeds, + &self.instruction.__remaining_accounts, + ) + } +} + +#[derive(Clone, Debug)] +struct CreatePlatformConfigCpiBuilderInstruction<'a, 'b> { + __program: &'b solana_account_info::AccountInfo<'a>, + platform_admin: Option<&'b solana_account_info::AccountInfo<'a>>, + platform_fee_wallet: Option<&'b solana_account_info::AccountInfo<'a>>, + platform_nft_wallet: Option<&'b solana_account_info::AccountInfo<'a>>, + platform_config: Option<&'b solana_account_info::AccountInfo<'a>>, + system_program: Option<&'b solana_account_info::AccountInfo<'a>>, + migrate_nft_info: Option, + fee_rate: Option, + name: Option, + web: Option, + img: Option, + /// Additional instruction accounts `(AccountInfo, is_writable, is_signer)`. + __remaining_accounts: Vec<(&'b solana_account_info::AccountInfo<'a>, bool, bool)>, +} diff --git a/e2e/raydium-launchpad/src/generated/instructions/create_vesting_account.rs b/e2e/raydium-launchpad/src/generated/instructions/create_vesting_account.rs new file mode 100644 index 0000000..963b553 --- /dev/null +++ b/e2e/raydium-launchpad/src/generated/instructions/create_vesting_account.rs @@ -0,0 +1,489 @@ +//! This code was AUTOGENERATED using the codama library. +//! Please DO NOT EDIT THIS FILE, instead use visitors +//! to add features, then rerun codama to update it. +//! +//! +//! + +use borsh::BorshDeserialize; +use borsh::BorshSerialize; + +pub const CREATE_VESTING_ACCOUNT_DISCRIMINATOR: [u8; 8] = [129, 178, 2, 13, 217, 172, 230, 218]; + +/// Accounts. +#[derive(Debug)] +pub struct CreateVestingAccount { + /// The account paying for the initialization costs + /// This can be any account with sufficient SOL to cover the transaction + pub creator: solana_address::Address, + + pub beneficiary: solana_address::Address, + /// The pool state account + pub pool_state: solana_address::Address, + /// The vesting record account + pub vesting_record: solana_address::Address, + /// Required for account creation + pub system_program: solana_address::Address, +} + +impl CreateVestingAccount { + pub fn instruction( + &self, + args: CreateVestingAccountInstructionArgs, + ) -> solana_instruction::Instruction { + self.instruction_with_remaining_accounts(args, &[]) + } + #[allow(clippy::arithmetic_side_effects)] + #[allow(clippy::vec_init_then_push)] + pub fn instruction_with_remaining_accounts( + &self, + args: CreateVestingAccountInstructionArgs, + remaining_accounts: &[solana_instruction::AccountMeta], + ) -> solana_instruction::Instruction { + let mut accounts = Vec::with_capacity(5 + remaining_accounts.len()); + accounts.push(solana_instruction::AccountMeta::new(self.creator, true)); + accounts.push(solana_instruction::AccountMeta::new( + self.beneficiary, + false, + )); + accounts.push(solana_instruction::AccountMeta::new(self.pool_state, false)); + accounts.push(solana_instruction::AccountMeta::new( + self.vesting_record, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.system_program, + false, + )); + accounts.extend_from_slice(remaining_accounts); + let mut data = CreateVestingAccountInstructionData::new() + .try_to_vec() + .unwrap(); + let mut args = args.try_to_vec().unwrap(); + data.append(&mut args); + + solana_instruction::Instruction { + program_id: crate::RAYDIUM_LAUNCHPAD_ID, + accounts, + data, + } + } +} + +#[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] +pub struct CreateVestingAccountInstructionData { + discriminator: [u8; 8], +} + +impl CreateVestingAccountInstructionData { + pub fn new() -> Self { + Self { + discriminator: [129, 178, 2, 13, 217, 172, 230, 218], + } + } + + pub(crate) fn try_to_vec(&self) -> Result, std::io::Error> { + borsh::to_vec(self) + } +} + +impl Default for CreateVestingAccountInstructionData { + fn default() -> Self { + Self::new() + } +} + +#[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] +pub struct CreateVestingAccountInstructionArgs { + pub share_amount: u64, +} + +impl CreateVestingAccountInstructionArgs { + pub(crate) fn try_to_vec(&self) -> Result, std::io::Error> { + borsh::to_vec(self) + } +} + +/// Instruction builder for `CreateVestingAccount`. +/// +/// ### Accounts: +/// +/// 0. `[writable, signer]` creator +/// 1. `[writable]` beneficiary +/// 2. `[writable]` pool_state +/// 3. `[writable]` vesting_record +/// 4. `[optional]` system_program (default to `11111111111111111111111111111111`) +#[derive(Clone, Debug, Default)] +pub struct CreateVestingAccountBuilder { + creator: Option, + beneficiary: Option, + pool_state: Option, + vesting_record: Option, + system_program: Option, + share_amount: Option, + __remaining_accounts: Vec, +} + +impl CreateVestingAccountBuilder { + pub fn new() -> Self { + Self::default() + } + /// The account paying for the initialization costs + /// This can be any account with sufficient SOL to cover the transaction + #[inline(always)] + pub fn creator(&mut self, creator: solana_address::Address) -> &mut Self { + self.creator = Some(creator); + self + } + #[inline(always)] + pub fn beneficiary(&mut self, beneficiary: solana_address::Address) -> &mut Self { + self.beneficiary = Some(beneficiary); + self + } + /// The pool state account + #[inline(always)] + pub fn pool_state(&mut self, pool_state: solana_address::Address) -> &mut Self { + self.pool_state = Some(pool_state); + self + } + /// The vesting record account + #[inline(always)] + pub fn vesting_record(&mut self, vesting_record: solana_address::Address) -> &mut Self { + self.vesting_record = Some(vesting_record); + self + } + /// `[optional account, default to '11111111111111111111111111111111']` + /// Required for account creation + #[inline(always)] + pub fn system_program(&mut self, system_program: solana_address::Address) -> &mut Self { + self.system_program = Some(system_program); + self + } + #[inline(always)] + pub fn share_amount(&mut self, share_amount: u64) -> &mut Self { + self.share_amount = Some(share_amount); + self + } + /// Add an additional account to the instruction. + #[inline(always)] + pub fn add_remaining_account(&mut self, account: solana_instruction::AccountMeta) -> &mut Self { + self.__remaining_accounts.push(account); + self + } + /// Add additional accounts to the instruction. + #[inline(always)] + pub fn add_remaining_accounts( + &mut self, + accounts: &[solana_instruction::AccountMeta], + ) -> &mut Self { + self.__remaining_accounts.extend_from_slice(accounts); + self + } + #[allow(clippy::clone_on_copy)] + pub fn instruction(&self) -> solana_instruction::Instruction { + let accounts = CreateVestingAccount { + creator: self.creator.expect("creator is not set"), + beneficiary: self.beneficiary.expect("beneficiary is not set"), + pool_state: self.pool_state.expect("pool_state is not set"), + vesting_record: self.vesting_record.expect("vesting_record is not set"), + system_program: self + .system_program + .unwrap_or(solana_address::address!("11111111111111111111111111111111")), + }; + let args = CreateVestingAccountInstructionArgs { + share_amount: self.share_amount.clone().expect("share_amount is not set"), + }; + + accounts.instruction_with_remaining_accounts(args, &self.__remaining_accounts) + } +} + +/// `create_vesting_account` CPI accounts. +pub struct CreateVestingAccountCpiAccounts<'a, 'b> { + /// The account paying for the initialization costs + /// This can be any account with sufficient SOL to cover the transaction + pub creator: &'b solana_account_info::AccountInfo<'a>, + + pub beneficiary: &'b solana_account_info::AccountInfo<'a>, + /// The pool state account + pub pool_state: &'b solana_account_info::AccountInfo<'a>, + /// The vesting record account + pub vesting_record: &'b solana_account_info::AccountInfo<'a>, + /// Required for account creation + pub system_program: &'b solana_account_info::AccountInfo<'a>, +} + +/// `create_vesting_account` CPI instruction. +pub struct CreateVestingAccountCpi<'a, 'b> { + /// The program to invoke. + pub __program: &'b solana_account_info::AccountInfo<'a>, + /// The account paying for the initialization costs + /// This can be any account with sufficient SOL to cover the transaction + pub creator: &'b solana_account_info::AccountInfo<'a>, + + pub beneficiary: &'b solana_account_info::AccountInfo<'a>, + /// The pool state account + pub pool_state: &'b solana_account_info::AccountInfo<'a>, + /// The vesting record account + pub vesting_record: &'b solana_account_info::AccountInfo<'a>, + /// Required for account creation + pub system_program: &'b solana_account_info::AccountInfo<'a>, + /// The arguments for the instruction. + pub __args: CreateVestingAccountInstructionArgs, +} + +impl<'a, 'b> CreateVestingAccountCpi<'a, 'b> { + pub fn new( + program: &'b solana_account_info::AccountInfo<'a>, + accounts: CreateVestingAccountCpiAccounts<'a, 'b>, + args: CreateVestingAccountInstructionArgs, + ) -> Self { + Self { + __program: program, + creator: accounts.creator, + beneficiary: accounts.beneficiary, + pool_state: accounts.pool_state, + vesting_record: accounts.vesting_record, + system_program: accounts.system_program, + __args: args, + } + } + #[inline(always)] + pub fn invoke(&self) -> solana_program_error::ProgramResult { + self.invoke_signed_with_remaining_accounts(&[], &[]) + } + #[inline(always)] + pub fn invoke_with_remaining_accounts( + &self, + remaining_accounts: &[(&'b solana_account_info::AccountInfo<'a>, bool, bool)], + ) -> solana_program_error::ProgramResult { + self.invoke_signed_with_remaining_accounts(&[], remaining_accounts) + } + #[inline(always)] + pub fn invoke_signed(&self, signers_seeds: &[&[&[u8]]]) -> solana_program_error::ProgramResult { + self.invoke_signed_with_remaining_accounts(signers_seeds, &[]) + } + #[allow(clippy::arithmetic_side_effects)] + #[allow(clippy::clone_on_copy)] + #[allow(clippy::vec_init_then_push)] + pub fn invoke_signed_with_remaining_accounts( + &self, + signers_seeds: &[&[&[u8]]], + remaining_accounts: &[(&'b solana_account_info::AccountInfo<'a>, bool, bool)], + ) -> solana_program_error::ProgramResult { + let mut accounts = Vec::with_capacity(5 + remaining_accounts.len()); + accounts.push(solana_instruction::AccountMeta::new( + *self.creator.key, + true, + )); + accounts.push(solana_instruction::AccountMeta::new( + *self.beneficiary.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + *self.pool_state.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + *self.vesting_record.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.system_program.key, + false, + )); + remaining_accounts.iter().for_each(|remaining_account| { + accounts.push(solana_instruction::AccountMeta { + pubkey: *remaining_account.0.key, + is_signer: remaining_account.1, + is_writable: remaining_account.2, + }) + }); + let mut data = CreateVestingAccountInstructionData::new() + .try_to_vec() + .unwrap(); + let mut args = self.__args.try_to_vec().unwrap(); + data.append(&mut args); + + let instruction = solana_instruction::Instruction { + program_id: crate::RAYDIUM_LAUNCHPAD_ID, + accounts, + data, + }; + let mut account_infos = Vec::with_capacity(6 + remaining_accounts.len()); + account_infos.push(self.__program.clone()); + account_infos.push(self.creator.clone()); + account_infos.push(self.beneficiary.clone()); + account_infos.push(self.pool_state.clone()); + account_infos.push(self.vesting_record.clone()); + account_infos.push(self.system_program.clone()); + remaining_accounts + .iter() + .for_each(|remaining_account| account_infos.push(remaining_account.0.clone())); + + if signers_seeds.is_empty() { + solana_cpi::invoke(&instruction, &account_infos) + } else { + solana_cpi::invoke_signed(&instruction, &account_infos, signers_seeds) + } + } +} + +/// Instruction builder for `CreateVestingAccount` via CPI. +/// +/// ### Accounts: +/// +/// 0. `[writable, signer]` creator +/// 1. `[writable]` beneficiary +/// 2. `[writable]` pool_state +/// 3. `[writable]` vesting_record +/// 4. `[]` system_program +#[derive(Clone, Debug)] +pub struct CreateVestingAccountCpiBuilder<'a, 'b> { + instruction: Box>, +} + +impl<'a, 'b> CreateVestingAccountCpiBuilder<'a, 'b> { + pub fn new(program: &'b solana_account_info::AccountInfo<'a>) -> Self { + let instruction = Box::new(CreateVestingAccountCpiBuilderInstruction { + __program: program, + creator: None, + beneficiary: None, + pool_state: None, + vesting_record: None, + system_program: None, + share_amount: None, + __remaining_accounts: Vec::new(), + }); + Self { instruction } + } + /// The account paying for the initialization costs + /// This can be any account with sufficient SOL to cover the transaction + #[inline(always)] + pub fn creator(&mut self, creator: &'b solana_account_info::AccountInfo<'a>) -> &mut Self { + self.instruction.creator = Some(creator); + self + } + #[inline(always)] + pub fn beneficiary( + &mut self, + beneficiary: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.beneficiary = Some(beneficiary); + self + } + /// The pool state account + #[inline(always)] + pub fn pool_state( + &mut self, + pool_state: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.pool_state = Some(pool_state); + self + } + /// The vesting record account + #[inline(always)] + pub fn vesting_record( + &mut self, + vesting_record: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.vesting_record = Some(vesting_record); + self + } + /// Required for account creation + #[inline(always)] + pub fn system_program( + &mut self, + system_program: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.system_program = Some(system_program); + self + } + #[inline(always)] + pub fn share_amount(&mut self, share_amount: u64) -> &mut Self { + self.instruction.share_amount = Some(share_amount); + self + } + /// Add an additional account to the instruction. + #[inline(always)] + pub fn add_remaining_account( + &mut self, + account: &'b solana_account_info::AccountInfo<'a>, + is_writable: bool, + is_signer: bool, + ) -> &mut Self { + self.instruction + .__remaining_accounts + .push((account, is_writable, is_signer)); + self + } + /// Add additional accounts to the instruction. + /// + /// Each account is represented by a tuple of the `AccountInfo`, a `bool` indicating whether the account is writable or not, + /// and a `bool` indicating whether the account is a signer or not. + #[inline(always)] + pub fn add_remaining_accounts( + &mut self, + accounts: &[(&'b solana_account_info::AccountInfo<'a>, bool, bool)], + ) -> &mut Self { + self.instruction + .__remaining_accounts + .extend_from_slice(accounts); + self + } + #[inline(always)] + pub fn invoke(&self) -> solana_program_error::ProgramResult { + self.invoke_signed(&[]) + } + #[allow(clippy::clone_on_copy)] + #[allow(clippy::vec_init_then_push)] + pub fn invoke_signed(&self, signers_seeds: &[&[&[u8]]]) -> solana_program_error::ProgramResult { + let args = CreateVestingAccountInstructionArgs { + share_amount: self + .instruction + .share_amount + .clone() + .expect("share_amount is not set"), + }; + let instruction = CreateVestingAccountCpi { + __program: self.instruction.__program, + + creator: self.instruction.creator.expect("creator is not set"), + + beneficiary: self + .instruction + .beneficiary + .expect("beneficiary is not set"), + + pool_state: self.instruction.pool_state.expect("pool_state is not set"), + + vesting_record: self + .instruction + .vesting_record + .expect("vesting_record is not set"), + + system_program: self + .instruction + .system_program + .expect("system_program is not set"), + __args: args, + }; + instruction.invoke_signed_with_remaining_accounts( + signers_seeds, + &self.instruction.__remaining_accounts, + ) + } +} + +#[derive(Clone, Debug)] +struct CreateVestingAccountCpiBuilderInstruction<'a, 'b> { + __program: &'b solana_account_info::AccountInfo<'a>, + creator: Option<&'b solana_account_info::AccountInfo<'a>>, + beneficiary: Option<&'b solana_account_info::AccountInfo<'a>>, + pool_state: Option<&'b solana_account_info::AccountInfo<'a>>, + vesting_record: Option<&'b solana_account_info::AccountInfo<'a>>, + system_program: Option<&'b solana_account_info::AccountInfo<'a>>, + share_amount: Option, + /// Additional instruction accounts `(AccountInfo, is_writable, is_signer)`. + __remaining_accounts: Vec<(&'b solana_account_info::AccountInfo<'a>, bool, bool)>, +} diff --git a/e2e/raydium-launchpad/src/generated/instructions/initialize.rs b/e2e/raydium-launchpad/src/generated/instructions/initialize.rs new file mode 100644 index 0000000..c404b02 --- /dev/null +++ b/e2e/raydium-launchpad/src/generated/instructions/initialize.rs @@ -0,0 +1,1104 @@ +//! This code was AUTOGENERATED using the codama library. +//! Please DO NOT EDIT THIS FILE, instead use visitors +//! to add features, then rerun codama to update it. +//! +//! +//! + +use crate::generated::types::CurveParams; +use crate::generated::types::MintParams; +use crate::generated::types::VestingParams; +use borsh::BorshDeserialize; +use borsh::BorshSerialize; + +pub const INITIALIZE_DISCRIMINATOR: [u8; 8] = [175, 175, 109, 31, 13, 152, 155, 237]; + +/// Accounts. +#[derive(Debug)] +pub struct Initialize { + /// The account paying for the initialization costs + /// This can be any account with sufficient SOL to cover the transaction + pub payer: solana_address::Address, + + pub creator: solana_address::Address, + /// Global configuration account containing protocol-wide settings + /// Includes settings like quote token mint and fee parameters + pub global_config: solana_address::Address, + /// Platform configuration account containing platform info + /// Includes settings like the fee_rate, name, web, img of the platform + pub platform_config: solana_address::Address, + /// PDA that acts as the authority for pool vault and mint operations + /// Generated using AUTH_SEED + pub authority: solana_address::Address, + /// Account that stores the pool's state and parameters + /// PDA generated using POOL_SEED and both token mints + pub pool_state: solana_address::Address, + /// The mint for the base token (token being sold) + /// Created in this instruction with specified decimals + pub base_mint: solana_address::Address, + /// The mint for the quote token (token used to buy) + /// Must match the quote_mint specified in global config + pub quote_mint: solana_address::Address, + /// Token account that holds the pool's base tokens + /// PDA generated using POOL_VAULT_SEED + pub base_vault: solana_address::Address, + /// Token account that holds the pool's quote tokens + /// PDA generated using POOL_VAULT_SEED + pub quote_vault: solana_address::Address, + /// Account to store the base token's metadata + /// Created using Metaplex metadata program + pub metadata_account: solana_address::Address, + /// SPL Token program for the base token + /// Must be the standard Token program + pub base_token_program: solana_address::Address, + /// SPL Token program for the quote token + pub quote_token_program: solana_address::Address, + /// Metaplex Token Metadata program + /// Used to create metadata for the base token + pub metadata_program: solana_address::Address, + /// Required for account creation + pub system_program: solana_address::Address, + /// Required for rent exempt calculations + pub rent_program: solana_address::Address, + + pub event_authority: solana_address::Address, + + pub program: solana_address::Address, +} + +impl Initialize { + pub fn instruction(&self, args: InitializeInstructionArgs) -> solana_instruction::Instruction { + self.instruction_with_remaining_accounts(args, &[]) + } + #[allow(clippy::arithmetic_side_effects)] + #[allow(clippy::vec_init_then_push)] + pub fn instruction_with_remaining_accounts( + &self, + args: InitializeInstructionArgs, + remaining_accounts: &[solana_instruction::AccountMeta], + ) -> solana_instruction::Instruction { + let mut accounts = Vec::with_capacity(18 + remaining_accounts.len()); + accounts.push(solana_instruction::AccountMeta::new(self.payer, true)); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.creator, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.global_config, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.platform_config, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.authority, + false, + )); + accounts.push(solana_instruction::AccountMeta::new(self.pool_state, false)); + accounts.push(solana_instruction::AccountMeta::new(self.base_mint, true)); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.quote_mint, + false, + )); + accounts.push(solana_instruction::AccountMeta::new(self.base_vault, false)); + accounts.push(solana_instruction::AccountMeta::new( + self.quote_vault, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + self.metadata_account, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.base_token_program, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.quote_token_program, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.metadata_program, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.system_program, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.rent_program, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.event_authority, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.program, + false, + )); + accounts.extend_from_slice(remaining_accounts); + let mut data = InitializeInstructionData::new().try_to_vec().unwrap(); + let mut args = args.try_to_vec().unwrap(); + data.append(&mut args); + + solana_instruction::Instruction { + program_id: crate::RAYDIUM_LAUNCHPAD_ID, + accounts, + data, + } + } +} + +#[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] +pub struct InitializeInstructionData { + discriminator: [u8; 8], +} + +impl InitializeInstructionData { + pub fn new() -> Self { + Self { + discriminator: [175, 175, 109, 31, 13, 152, 155, 237], + } + } + + pub(crate) fn try_to_vec(&self) -> Result, std::io::Error> { + borsh::to_vec(self) + } +} + +impl Default for InitializeInstructionData { + fn default() -> Self { + Self::new() + } +} + +#[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] +pub struct InitializeInstructionArgs { + pub base_mint_param: MintParams, + pub curve_param: CurveParams, + pub vesting_param: VestingParams, +} + +impl InitializeInstructionArgs { + pub(crate) fn try_to_vec(&self) -> Result, std::io::Error> { + borsh::to_vec(self) + } +} + +/// Instruction builder for `Initialize`. +/// +/// ### Accounts: +/// +/// 0. `[writable, signer]` payer +/// 1. `[]` creator +/// 2. `[]` global_config +/// 3. `[]` platform_config +/// 4. `[]` authority +/// 5. `[writable]` pool_state +/// 6. `[writable, signer]` base_mint +/// 7. `[]` quote_mint +/// 8. `[writable]` base_vault +/// 9. `[writable]` quote_vault +/// 10. `[writable]` metadata_account +/// 11. `[optional]` base_token_program (default to `TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA`) +/// 12. `[optional]` quote_token_program (default to `TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA`) +/// 13. `[optional]` metadata_program (default to `metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s`) +/// 14. `[optional]` system_program (default to `11111111111111111111111111111111`) +/// 15. `[optional]` rent_program (default to `SysvarRent111111111111111111111111111111111`) +/// 16. `[]` event_authority +/// 17. `[]` program +#[derive(Clone, Debug, Default)] +pub struct InitializeBuilder { + payer: Option, + creator: Option, + global_config: Option, + platform_config: Option, + authority: Option, + pool_state: Option, + base_mint: Option, + quote_mint: Option, + base_vault: Option, + quote_vault: Option, + metadata_account: Option, + base_token_program: Option, + quote_token_program: Option, + metadata_program: Option, + system_program: Option, + rent_program: Option, + event_authority: Option, + program: Option, + base_mint_param: Option, + curve_param: Option, + vesting_param: Option, + __remaining_accounts: Vec, +} + +impl InitializeBuilder { + pub fn new() -> Self { + Self::default() + } + /// The account paying for the initialization costs + /// This can be any account with sufficient SOL to cover the transaction + #[inline(always)] + pub fn payer(&mut self, payer: solana_address::Address) -> &mut Self { + self.payer = Some(payer); + self + } + #[inline(always)] + pub fn creator(&mut self, creator: solana_address::Address) -> &mut Self { + self.creator = Some(creator); + self + } + /// Global configuration account containing protocol-wide settings + /// Includes settings like quote token mint and fee parameters + #[inline(always)] + pub fn global_config(&mut self, global_config: solana_address::Address) -> &mut Self { + self.global_config = Some(global_config); + self + } + /// Platform configuration account containing platform info + /// Includes settings like the fee_rate, name, web, img of the platform + #[inline(always)] + pub fn platform_config(&mut self, platform_config: solana_address::Address) -> &mut Self { + self.platform_config = Some(platform_config); + self + } + /// PDA that acts as the authority for pool vault and mint operations + /// Generated using AUTH_SEED + #[inline(always)] + pub fn authority(&mut self, authority: solana_address::Address) -> &mut Self { + self.authority = Some(authority); + self + } + /// Account that stores the pool's state and parameters + /// PDA generated using POOL_SEED and both token mints + #[inline(always)] + pub fn pool_state(&mut self, pool_state: solana_address::Address) -> &mut Self { + self.pool_state = Some(pool_state); + self + } + /// The mint for the base token (token being sold) + /// Created in this instruction with specified decimals + #[inline(always)] + pub fn base_mint(&mut self, base_mint: solana_address::Address) -> &mut Self { + self.base_mint = Some(base_mint); + self + } + /// The mint for the quote token (token used to buy) + /// Must match the quote_mint specified in global config + #[inline(always)] + pub fn quote_mint(&mut self, quote_mint: solana_address::Address) -> &mut Self { + self.quote_mint = Some(quote_mint); + self + } + /// Token account that holds the pool's base tokens + /// PDA generated using POOL_VAULT_SEED + #[inline(always)] + pub fn base_vault(&mut self, base_vault: solana_address::Address) -> &mut Self { + self.base_vault = Some(base_vault); + self + } + /// Token account that holds the pool's quote tokens + /// PDA generated using POOL_VAULT_SEED + #[inline(always)] + pub fn quote_vault(&mut self, quote_vault: solana_address::Address) -> &mut Self { + self.quote_vault = Some(quote_vault); + self + } + /// Account to store the base token's metadata + /// Created using Metaplex metadata program + #[inline(always)] + pub fn metadata_account(&mut self, metadata_account: solana_address::Address) -> &mut Self { + self.metadata_account = Some(metadata_account); + self + } + /// `[optional account, default to 'TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA']` + /// SPL Token program for the base token + /// Must be the standard Token program + #[inline(always)] + pub fn base_token_program(&mut self, base_token_program: solana_address::Address) -> &mut Self { + self.base_token_program = Some(base_token_program); + self + } + /// `[optional account, default to 'TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA']` + /// SPL Token program for the quote token + #[inline(always)] + pub fn quote_token_program( + &mut self, + quote_token_program: solana_address::Address, + ) -> &mut Self { + self.quote_token_program = Some(quote_token_program); + self + } + /// `[optional account, default to 'metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s']` + /// Metaplex Token Metadata program + /// Used to create metadata for the base token + #[inline(always)] + pub fn metadata_program(&mut self, metadata_program: solana_address::Address) -> &mut Self { + self.metadata_program = Some(metadata_program); + self + } + /// `[optional account, default to '11111111111111111111111111111111']` + /// Required for account creation + #[inline(always)] + pub fn system_program(&mut self, system_program: solana_address::Address) -> &mut Self { + self.system_program = Some(system_program); + self + } + /// `[optional account, default to 'SysvarRent111111111111111111111111111111111']` + /// Required for rent exempt calculations + #[inline(always)] + pub fn rent_program(&mut self, rent_program: solana_address::Address) -> &mut Self { + self.rent_program = Some(rent_program); + self + } + #[inline(always)] + pub fn event_authority(&mut self, event_authority: solana_address::Address) -> &mut Self { + self.event_authority = Some(event_authority); + self + } + #[inline(always)] + pub fn program(&mut self, program: solana_address::Address) -> &mut Self { + self.program = Some(program); + self + } + #[inline(always)] + pub fn base_mint_param(&mut self, base_mint_param: MintParams) -> &mut Self { + self.base_mint_param = Some(base_mint_param); + self + } + #[inline(always)] + pub fn curve_param(&mut self, curve_param: CurveParams) -> &mut Self { + self.curve_param = Some(curve_param); + self + } + #[inline(always)] + pub fn vesting_param(&mut self, vesting_param: VestingParams) -> &mut Self { + self.vesting_param = Some(vesting_param); + self + } + /// Add an additional account to the instruction. + #[inline(always)] + pub fn add_remaining_account(&mut self, account: solana_instruction::AccountMeta) -> &mut Self { + self.__remaining_accounts.push(account); + self + } + /// Add additional accounts to the instruction. + #[inline(always)] + pub fn add_remaining_accounts( + &mut self, + accounts: &[solana_instruction::AccountMeta], + ) -> &mut Self { + self.__remaining_accounts.extend_from_slice(accounts); + self + } + #[allow(clippy::clone_on_copy)] + pub fn instruction(&self) -> solana_instruction::Instruction { + let accounts = Initialize { + payer: self.payer.expect("payer is not set"), + creator: self.creator.expect("creator is not set"), + global_config: self.global_config.expect("global_config is not set"), + platform_config: self.platform_config.expect("platform_config is not set"), + authority: self.authority.expect("authority is not set"), + pool_state: self.pool_state.expect("pool_state is not set"), + base_mint: self.base_mint.expect("base_mint is not set"), + quote_mint: self.quote_mint.expect("quote_mint is not set"), + base_vault: self.base_vault.expect("base_vault is not set"), + quote_vault: self.quote_vault.expect("quote_vault is not set"), + metadata_account: self.metadata_account.expect("metadata_account is not set"), + base_token_program: self.base_token_program.unwrap_or(solana_address::address!( + "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA" + )), + quote_token_program: self.quote_token_program.unwrap_or(solana_address::address!( + "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA" + )), + metadata_program: self.metadata_program.unwrap_or(solana_address::address!( + "metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s" + )), + system_program: self + .system_program + .unwrap_or(solana_address::address!("11111111111111111111111111111111")), + rent_program: self.rent_program.unwrap_or(solana_address::address!( + "SysvarRent111111111111111111111111111111111" + )), + event_authority: self.event_authority.expect("event_authority is not set"), + program: self.program.expect("program is not set"), + }; + let args = InitializeInstructionArgs { + base_mint_param: self + .base_mint_param + .clone() + .expect("base_mint_param is not set"), + curve_param: self.curve_param.clone().expect("curve_param is not set"), + vesting_param: self + .vesting_param + .clone() + .expect("vesting_param is not set"), + }; + + accounts.instruction_with_remaining_accounts(args, &self.__remaining_accounts) + } +} + +/// `initialize` CPI accounts. +pub struct InitializeCpiAccounts<'a, 'b> { + /// The account paying for the initialization costs + /// This can be any account with sufficient SOL to cover the transaction + pub payer: &'b solana_account_info::AccountInfo<'a>, + + pub creator: &'b solana_account_info::AccountInfo<'a>, + /// Global configuration account containing protocol-wide settings + /// Includes settings like quote token mint and fee parameters + pub global_config: &'b solana_account_info::AccountInfo<'a>, + /// Platform configuration account containing platform info + /// Includes settings like the fee_rate, name, web, img of the platform + pub platform_config: &'b solana_account_info::AccountInfo<'a>, + /// PDA that acts as the authority for pool vault and mint operations + /// Generated using AUTH_SEED + pub authority: &'b solana_account_info::AccountInfo<'a>, + /// Account that stores the pool's state and parameters + /// PDA generated using POOL_SEED and both token mints + pub pool_state: &'b solana_account_info::AccountInfo<'a>, + /// The mint for the base token (token being sold) + /// Created in this instruction with specified decimals + pub base_mint: &'b solana_account_info::AccountInfo<'a>, + /// The mint for the quote token (token used to buy) + /// Must match the quote_mint specified in global config + pub quote_mint: &'b solana_account_info::AccountInfo<'a>, + /// Token account that holds the pool's base tokens + /// PDA generated using POOL_VAULT_SEED + pub base_vault: &'b solana_account_info::AccountInfo<'a>, + /// Token account that holds the pool's quote tokens + /// PDA generated using POOL_VAULT_SEED + pub quote_vault: &'b solana_account_info::AccountInfo<'a>, + /// Account to store the base token's metadata + /// Created using Metaplex metadata program + pub metadata_account: &'b solana_account_info::AccountInfo<'a>, + /// SPL Token program for the base token + /// Must be the standard Token program + pub base_token_program: &'b solana_account_info::AccountInfo<'a>, + /// SPL Token program for the quote token + pub quote_token_program: &'b solana_account_info::AccountInfo<'a>, + /// Metaplex Token Metadata program + /// Used to create metadata for the base token + pub metadata_program: &'b solana_account_info::AccountInfo<'a>, + /// Required for account creation + pub system_program: &'b solana_account_info::AccountInfo<'a>, + /// Required for rent exempt calculations + pub rent_program: &'b solana_account_info::AccountInfo<'a>, + + pub event_authority: &'b solana_account_info::AccountInfo<'a>, + + pub program: &'b solana_account_info::AccountInfo<'a>, +} + +/// `initialize` CPI instruction. +pub struct InitializeCpi<'a, 'b> { + /// The program to invoke. + pub __program: &'b solana_account_info::AccountInfo<'a>, + /// The account paying for the initialization costs + /// This can be any account with sufficient SOL to cover the transaction + pub payer: &'b solana_account_info::AccountInfo<'a>, + + pub creator: &'b solana_account_info::AccountInfo<'a>, + /// Global configuration account containing protocol-wide settings + /// Includes settings like quote token mint and fee parameters + pub global_config: &'b solana_account_info::AccountInfo<'a>, + /// Platform configuration account containing platform info + /// Includes settings like the fee_rate, name, web, img of the platform + pub platform_config: &'b solana_account_info::AccountInfo<'a>, + /// PDA that acts as the authority for pool vault and mint operations + /// Generated using AUTH_SEED + pub authority: &'b solana_account_info::AccountInfo<'a>, + /// Account that stores the pool's state and parameters + /// PDA generated using POOL_SEED and both token mints + pub pool_state: &'b solana_account_info::AccountInfo<'a>, + /// The mint for the base token (token being sold) + /// Created in this instruction with specified decimals + pub base_mint: &'b solana_account_info::AccountInfo<'a>, + /// The mint for the quote token (token used to buy) + /// Must match the quote_mint specified in global config + pub quote_mint: &'b solana_account_info::AccountInfo<'a>, + /// Token account that holds the pool's base tokens + /// PDA generated using POOL_VAULT_SEED + pub base_vault: &'b solana_account_info::AccountInfo<'a>, + /// Token account that holds the pool's quote tokens + /// PDA generated using POOL_VAULT_SEED + pub quote_vault: &'b solana_account_info::AccountInfo<'a>, + /// Account to store the base token's metadata + /// Created using Metaplex metadata program + pub metadata_account: &'b solana_account_info::AccountInfo<'a>, + /// SPL Token program for the base token + /// Must be the standard Token program + pub base_token_program: &'b solana_account_info::AccountInfo<'a>, + /// SPL Token program for the quote token + pub quote_token_program: &'b solana_account_info::AccountInfo<'a>, + /// Metaplex Token Metadata program + /// Used to create metadata for the base token + pub metadata_program: &'b solana_account_info::AccountInfo<'a>, + /// Required for account creation + pub system_program: &'b solana_account_info::AccountInfo<'a>, + /// Required for rent exempt calculations + pub rent_program: &'b solana_account_info::AccountInfo<'a>, + + pub event_authority: &'b solana_account_info::AccountInfo<'a>, + + pub program: &'b solana_account_info::AccountInfo<'a>, + /// The arguments for the instruction. + pub __args: InitializeInstructionArgs, +} + +impl<'a, 'b> InitializeCpi<'a, 'b> { + pub fn new( + program: &'b solana_account_info::AccountInfo<'a>, + accounts: InitializeCpiAccounts<'a, 'b>, + args: InitializeInstructionArgs, + ) -> Self { + Self { + __program: program, + payer: accounts.payer, + creator: accounts.creator, + global_config: accounts.global_config, + platform_config: accounts.platform_config, + authority: accounts.authority, + pool_state: accounts.pool_state, + base_mint: accounts.base_mint, + quote_mint: accounts.quote_mint, + base_vault: accounts.base_vault, + quote_vault: accounts.quote_vault, + metadata_account: accounts.metadata_account, + base_token_program: accounts.base_token_program, + quote_token_program: accounts.quote_token_program, + metadata_program: accounts.metadata_program, + system_program: accounts.system_program, + rent_program: accounts.rent_program, + event_authority: accounts.event_authority, + program: accounts.program, + __args: args, + } + } + #[inline(always)] + pub fn invoke(&self) -> solana_program_error::ProgramResult { + self.invoke_signed_with_remaining_accounts(&[], &[]) + } + #[inline(always)] + pub fn invoke_with_remaining_accounts( + &self, + remaining_accounts: &[(&'b solana_account_info::AccountInfo<'a>, bool, bool)], + ) -> solana_program_error::ProgramResult { + self.invoke_signed_with_remaining_accounts(&[], remaining_accounts) + } + #[inline(always)] + pub fn invoke_signed(&self, signers_seeds: &[&[&[u8]]]) -> solana_program_error::ProgramResult { + self.invoke_signed_with_remaining_accounts(signers_seeds, &[]) + } + #[allow(clippy::arithmetic_side_effects)] + #[allow(clippy::clone_on_copy)] + #[allow(clippy::vec_init_then_push)] + pub fn invoke_signed_with_remaining_accounts( + &self, + signers_seeds: &[&[&[u8]]], + remaining_accounts: &[(&'b solana_account_info::AccountInfo<'a>, bool, bool)], + ) -> solana_program_error::ProgramResult { + let mut accounts = Vec::with_capacity(18 + remaining_accounts.len()); + accounts.push(solana_instruction::AccountMeta::new(*self.payer.key, true)); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.creator.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.global_config.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.platform_config.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.authority.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + *self.pool_state.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + *self.base_mint.key, + true, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.quote_mint.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + *self.base_vault.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + *self.quote_vault.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + *self.metadata_account.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.base_token_program.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.quote_token_program.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.metadata_program.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.system_program.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.rent_program.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.event_authority.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.program.key, + false, + )); + remaining_accounts.iter().for_each(|remaining_account| { + accounts.push(solana_instruction::AccountMeta { + pubkey: *remaining_account.0.key, + is_signer: remaining_account.1, + is_writable: remaining_account.2, + }) + }); + let mut data = InitializeInstructionData::new().try_to_vec().unwrap(); + let mut args = self.__args.try_to_vec().unwrap(); + data.append(&mut args); + + let instruction = solana_instruction::Instruction { + program_id: crate::RAYDIUM_LAUNCHPAD_ID, + accounts, + data, + }; + let mut account_infos = Vec::with_capacity(19 + remaining_accounts.len()); + account_infos.push(self.__program.clone()); + account_infos.push(self.payer.clone()); + account_infos.push(self.creator.clone()); + account_infos.push(self.global_config.clone()); + account_infos.push(self.platform_config.clone()); + account_infos.push(self.authority.clone()); + account_infos.push(self.pool_state.clone()); + account_infos.push(self.base_mint.clone()); + account_infos.push(self.quote_mint.clone()); + account_infos.push(self.base_vault.clone()); + account_infos.push(self.quote_vault.clone()); + account_infos.push(self.metadata_account.clone()); + account_infos.push(self.base_token_program.clone()); + account_infos.push(self.quote_token_program.clone()); + account_infos.push(self.metadata_program.clone()); + account_infos.push(self.system_program.clone()); + account_infos.push(self.rent_program.clone()); + account_infos.push(self.event_authority.clone()); + account_infos.push(self.program.clone()); + remaining_accounts + .iter() + .for_each(|remaining_account| account_infos.push(remaining_account.0.clone())); + + if signers_seeds.is_empty() { + solana_cpi::invoke(&instruction, &account_infos) + } else { + solana_cpi::invoke_signed(&instruction, &account_infos, signers_seeds) + } + } +} + +/// Instruction builder for `Initialize` via CPI. +/// +/// ### Accounts: +/// +/// 0. `[writable, signer]` payer +/// 1. `[]` creator +/// 2. `[]` global_config +/// 3. `[]` platform_config +/// 4. `[]` authority +/// 5. `[writable]` pool_state +/// 6. `[writable, signer]` base_mint +/// 7. `[]` quote_mint +/// 8. `[writable]` base_vault +/// 9. `[writable]` quote_vault +/// 10. `[writable]` metadata_account +/// 11. `[]` base_token_program +/// 12. `[]` quote_token_program +/// 13. `[]` metadata_program +/// 14. `[]` system_program +/// 15. `[]` rent_program +/// 16. `[]` event_authority +/// 17. `[]` program +#[derive(Clone, Debug)] +pub struct InitializeCpiBuilder<'a, 'b> { + instruction: Box>, +} + +impl<'a, 'b> InitializeCpiBuilder<'a, 'b> { + pub fn new(program: &'b solana_account_info::AccountInfo<'a>) -> Self { + let instruction = Box::new(InitializeCpiBuilderInstruction { + __program: program, + payer: None, + creator: None, + global_config: None, + platform_config: None, + authority: None, + pool_state: None, + base_mint: None, + quote_mint: None, + base_vault: None, + quote_vault: None, + metadata_account: None, + base_token_program: None, + quote_token_program: None, + metadata_program: None, + system_program: None, + rent_program: None, + event_authority: None, + program: None, + base_mint_param: None, + curve_param: None, + vesting_param: None, + __remaining_accounts: Vec::new(), + }); + Self { instruction } + } + /// The account paying for the initialization costs + /// This can be any account with sufficient SOL to cover the transaction + #[inline(always)] + pub fn payer(&mut self, payer: &'b solana_account_info::AccountInfo<'a>) -> &mut Self { + self.instruction.payer = Some(payer); + self + } + #[inline(always)] + pub fn creator(&mut self, creator: &'b solana_account_info::AccountInfo<'a>) -> &mut Self { + self.instruction.creator = Some(creator); + self + } + /// Global configuration account containing protocol-wide settings + /// Includes settings like quote token mint and fee parameters + #[inline(always)] + pub fn global_config( + &mut self, + global_config: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.global_config = Some(global_config); + self + } + /// Platform configuration account containing platform info + /// Includes settings like the fee_rate, name, web, img of the platform + #[inline(always)] + pub fn platform_config( + &mut self, + platform_config: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.platform_config = Some(platform_config); + self + } + /// PDA that acts as the authority for pool vault and mint operations + /// Generated using AUTH_SEED + #[inline(always)] + pub fn authority(&mut self, authority: &'b solana_account_info::AccountInfo<'a>) -> &mut Self { + self.instruction.authority = Some(authority); + self + } + /// Account that stores the pool's state and parameters + /// PDA generated using POOL_SEED and both token mints + #[inline(always)] + pub fn pool_state( + &mut self, + pool_state: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.pool_state = Some(pool_state); + self + } + /// The mint for the base token (token being sold) + /// Created in this instruction with specified decimals + #[inline(always)] + pub fn base_mint(&mut self, base_mint: &'b solana_account_info::AccountInfo<'a>) -> &mut Self { + self.instruction.base_mint = Some(base_mint); + self + } + /// The mint for the quote token (token used to buy) + /// Must match the quote_mint specified in global config + #[inline(always)] + pub fn quote_mint( + &mut self, + quote_mint: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.quote_mint = Some(quote_mint); + self + } + /// Token account that holds the pool's base tokens + /// PDA generated using POOL_VAULT_SEED + #[inline(always)] + pub fn base_vault( + &mut self, + base_vault: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.base_vault = Some(base_vault); + self + } + /// Token account that holds the pool's quote tokens + /// PDA generated using POOL_VAULT_SEED + #[inline(always)] + pub fn quote_vault( + &mut self, + quote_vault: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.quote_vault = Some(quote_vault); + self + } + /// Account to store the base token's metadata + /// Created using Metaplex metadata program + #[inline(always)] + pub fn metadata_account( + &mut self, + metadata_account: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.metadata_account = Some(metadata_account); + self + } + /// SPL Token program for the base token + /// Must be the standard Token program + #[inline(always)] + pub fn base_token_program( + &mut self, + base_token_program: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.base_token_program = Some(base_token_program); + self + } + /// SPL Token program for the quote token + #[inline(always)] + pub fn quote_token_program( + &mut self, + quote_token_program: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.quote_token_program = Some(quote_token_program); + self + } + /// Metaplex Token Metadata program + /// Used to create metadata for the base token + #[inline(always)] + pub fn metadata_program( + &mut self, + metadata_program: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.metadata_program = Some(metadata_program); + self + } + /// Required for account creation + #[inline(always)] + pub fn system_program( + &mut self, + system_program: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.system_program = Some(system_program); + self + } + /// Required for rent exempt calculations + #[inline(always)] + pub fn rent_program( + &mut self, + rent_program: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.rent_program = Some(rent_program); + self + } + #[inline(always)] + pub fn event_authority( + &mut self, + event_authority: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.event_authority = Some(event_authority); + self + } + #[inline(always)] + pub fn program(&mut self, program: &'b solana_account_info::AccountInfo<'a>) -> &mut Self { + self.instruction.program = Some(program); + self + } + #[inline(always)] + pub fn base_mint_param(&mut self, base_mint_param: MintParams) -> &mut Self { + self.instruction.base_mint_param = Some(base_mint_param); + self + } + #[inline(always)] + pub fn curve_param(&mut self, curve_param: CurveParams) -> &mut Self { + self.instruction.curve_param = Some(curve_param); + self + } + #[inline(always)] + pub fn vesting_param(&mut self, vesting_param: VestingParams) -> &mut Self { + self.instruction.vesting_param = Some(vesting_param); + self + } + /// Add an additional account to the instruction. + #[inline(always)] + pub fn add_remaining_account( + &mut self, + account: &'b solana_account_info::AccountInfo<'a>, + is_writable: bool, + is_signer: bool, + ) -> &mut Self { + self.instruction + .__remaining_accounts + .push((account, is_writable, is_signer)); + self + } + /// Add additional accounts to the instruction. + /// + /// Each account is represented by a tuple of the `AccountInfo`, a `bool` indicating whether the account is writable or not, + /// and a `bool` indicating whether the account is a signer or not. + #[inline(always)] + pub fn add_remaining_accounts( + &mut self, + accounts: &[(&'b solana_account_info::AccountInfo<'a>, bool, bool)], + ) -> &mut Self { + self.instruction + .__remaining_accounts + .extend_from_slice(accounts); + self + } + #[inline(always)] + pub fn invoke(&self) -> solana_program_error::ProgramResult { + self.invoke_signed(&[]) + } + #[allow(clippy::clone_on_copy)] + #[allow(clippy::vec_init_then_push)] + pub fn invoke_signed(&self, signers_seeds: &[&[&[u8]]]) -> solana_program_error::ProgramResult { + let args = InitializeInstructionArgs { + base_mint_param: self + .instruction + .base_mint_param + .clone() + .expect("base_mint_param is not set"), + curve_param: self + .instruction + .curve_param + .clone() + .expect("curve_param is not set"), + vesting_param: self + .instruction + .vesting_param + .clone() + .expect("vesting_param is not set"), + }; + let instruction = InitializeCpi { + __program: self.instruction.__program, + + payer: self.instruction.payer.expect("payer is not set"), + + creator: self.instruction.creator.expect("creator is not set"), + + global_config: self + .instruction + .global_config + .expect("global_config is not set"), + + platform_config: self + .instruction + .platform_config + .expect("platform_config is not set"), + + authority: self.instruction.authority.expect("authority is not set"), + + pool_state: self.instruction.pool_state.expect("pool_state is not set"), + + base_mint: self.instruction.base_mint.expect("base_mint is not set"), + + quote_mint: self.instruction.quote_mint.expect("quote_mint is not set"), + + base_vault: self.instruction.base_vault.expect("base_vault is not set"), + + quote_vault: self + .instruction + .quote_vault + .expect("quote_vault is not set"), + + metadata_account: self + .instruction + .metadata_account + .expect("metadata_account is not set"), + + base_token_program: self + .instruction + .base_token_program + .expect("base_token_program is not set"), + + quote_token_program: self + .instruction + .quote_token_program + .expect("quote_token_program is not set"), + + metadata_program: self + .instruction + .metadata_program + .expect("metadata_program is not set"), + + system_program: self + .instruction + .system_program + .expect("system_program is not set"), + + rent_program: self + .instruction + .rent_program + .expect("rent_program is not set"), + + event_authority: self + .instruction + .event_authority + .expect("event_authority is not set"), + + program: self.instruction.program.expect("program is not set"), + __args: args, + }; + instruction.invoke_signed_with_remaining_accounts( + signers_seeds, + &self.instruction.__remaining_accounts, + ) + } +} + +#[derive(Clone, Debug)] +struct InitializeCpiBuilderInstruction<'a, 'b> { + __program: &'b solana_account_info::AccountInfo<'a>, + payer: Option<&'b solana_account_info::AccountInfo<'a>>, + creator: Option<&'b solana_account_info::AccountInfo<'a>>, + global_config: Option<&'b solana_account_info::AccountInfo<'a>>, + platform_config: Option<&'b solana_account_info::AccountInfo<'a>>, + authority: Option<&'b solana_account_info::AccountInfo<'a>>, + pool_state: Option<&'b solana_account_info::AccountInfo<'a>>, + base_mint: Option<&'b solana_account_info::AccountInfo<'a>>, + quote_mint: Option<&'b solana_account_info::AccountInfo<'a>>, + base_vault: Option<&'b solana_account_info::AccountInfo<'a>>, + quote_vault: Option<&'b solana_account_info::AccountInfo<'a>>, + metadata_account: Option<&'b solana_account_info::AccountInfo<'a>>, + base_token_program: Option<&'b solana_account_info::AccountInfo<'a>>, + quote_token_program: Option<&'b solana_account_info::AccountInfo<'a>>, + metadata_program: Option<&'b solana_account_info::AccountInfo<'a>>, + system_program: Option<&'b solana_account_info::AccountInfo<'a>>, + rent_program: Option<&'b solana_account_info::AccountInfo<'a>>, + event_authority: Option<&'b solana_account_info::AccountInfo<'a>>, + program: Option<&'b solana_account_info::AccountInfo<'a>>, + base_mint_param: Option, + curve_param: Option, + vesting_param: Option, + /// Additional instruction accounts `(AccountInfo, is_writable, is_signer)`. + __remaining_accounts: Vec<(&'b solana_account_info::AccountInfo<'a>, bool, bool)>, +} diff --git a/e2e/raydium-launchpad/src/generated/instructions/migrate_to_amm.rs b/e2e/raydium-launchpad/src/generated/instructions/migrate_to_amm.rs new file mode 100644 index 0000000..4c6181b --- /dev/null +++ b/e2e/raydium-launchpad/src/generated/instructions/migrate_to_amm.rs @@ -0,0 +1,1631 @@ +//! This code was AUTOGENERATED using the codama library. +//! Please DO NOT EDIT THIS FILE, instead use visitors +//! to add features, then rerun codama to update it. +//! +//! +//! + +use borsh::BorshDeserialize; +use borsh::BorshSerialize; + +pub const MIGRATE_TO_AMM_DISCRIMINATOR: [u8; 8] = [207, 82, 192, 145, 254, 207, 145, 223]; + +/// Accounts. +#[derive(Debug)] +pub struct MigrateToAmm { + /// Only migrate_to_amm_wallet can migrate to cpswap pool + /// This signer must match the migrate_to_amm_wallet saved in global_config + pub payer: solana_address::Address, + /// The mint for the base token (token being sold) + pub base_mint: solana_address::Address, + /// The mint for the quote token (token used to buy) + pub quote_mint: solana_address::Address, + + pub openbook_program: solana_address::Address, + /// Account created and asigned to openbook_program but not been initialized + pub market: solana_address::Address, + /// Account created and asigned to openbook_program but not been initialized + pub request_queue: solana_address::Address, + /// Account created and asigned to openbook_program but not been initialized + pub event_queue: solana_address::Address, + /// Account created and asigned to openbook_program but not been initialized + pub bids: solana_address::Address, + /// Account created and asigned to openbook_program but not been initialized + pub asks: solana_address::Address, + + pub market_vault_signer: solana_address::Address, + /// Token account that holds the market's base tokens + pub market_base_vault: solana_address::Address, + /// Token account that holds the market's quote tokens + pub market_quote_vault: solana_address::Address, + + pub amm_program: solana_address::Address, + + pub amm_pool: solana_address::Address, + + pub amm_authority: solana_address::Address, + + pub amm_open_orders: solana_address::Address, + + pub amm_lp_mint: solana_address::Address, + + pub amm_base_vault: solana_address::Address, + + pub amm_quote_vault: solana_address::Address, + + pub amm_target_orders: solana_address::Address, + + pub amm_config: solana_address::Address, + + pub amm_create_fee_destination: solana_address::Address, + /// PDA that acts as the authority for pool vault operations + /// Generated using AUTH_SEED + pub authority: solana_address::Address, + /// Account that stores the pool's state and parameters + /// PDA generated using POOL_SEED and both token mints + pub pool_state: solana_address::Address, + /// Global config account stores owner + pub global_config: solana_address::Address, + /// The pool's vault for base tokens + /// Will be fully drained during migration + pub base_vault: solana_address::Address, + /// The pool's vault for quote tokens + /// Will be fully drained during migration + pub quote_vault: solana_address::Address, + + pub pool_lp_token: solana_address::Address, + /// SPL Token program for the base token + /// Must be the standard Token program + pub spl_token_program: solana_address::Address, + /// Program to create an ATA for receiving fee NFT + pub associated_token_program: solana_address::Address, + /// Required for account creation + pub system_program: solana_address::Address, + /// Required for rent exempt calculations + pub rent_program: solana_address::Address, +} + +impl MigrateToAmm { + pub fn instruction( + &self, + args: MigrateToAmmInstructionArgs, + ) -> solana_instruction::Instruction { + self.instruction_with_remaining_accounts(args, &[]) + } + #[allow(clippy::arithmetic_side_effects)] + #[allow(clippy::vec_init_then_push)] + pub fn instruction_with_remaining_accounts( + &self, + args: MigrateToAmmInstructionArgs, + remaining_accounts: &[solana_instruction::AccountMeta], + ) -> solana_instruction::Instruction { + let mut accounts = Vec::with_capacity(32 + remaining_accounts.len()); + accounts.push(solana_instruction::AccountMeta::new(self.payer, true)); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.base_mint, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.quote_mint, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.openbook_program, + false, + )); + accounts.push(solana_instruction::AccountMeta::new(self.market, false)); + accounts.push(solana_instruction::AccountMeta::new( + self.request_queue, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + self.event_queue, + false, + )); + accounts.push(solana_instruction::AccountMeta::new(self.bids, false)); + accounts.push(solana_instruction::AccountMeta::new(self.asks, false)); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.market_vault_signer, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + self.market_base_vault, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + self.market_quote_vault, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.amm_program, + false, + )); + accounts.push(solana_instruction::AccountMeta::new(self.amm_pool, false)); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.amm_authority, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + self.amm_open_orders, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + self.amm_lp_mint, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + self.amm_base_vault, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + self.amm_quote_vault, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + self.amm_target_orders, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.amm_config, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + self.amm_create_fee_destination, + false, + )); + accounts.push(solana_instruction::AccountMeta::new(self.authority, false)); + accounts.push(solana_instruction::AccountMeta::new(self.pool_state, false)); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.global_config, + false, + )); + accounts.push(solana_instruction::AccountMeta::new(self.base_vault, false)); + accounts.push(solana_instruction::AccountMeta::new( + self.quote_vault, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + self.pool_lp_token, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.spl_token_program, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.associated_token_program, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.system_program, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.rent_program, + false, + )); + accounts.extend_from_slice(remaining_accounts); + let mut data = MigrateToAmmInstructionData::new().try_to_vec().unwrap(); + let mut args = args.try_to_vec().unwrap(); + data.append(&mut args); + + solana_instruction::Instruction { + program_id: crate::RAYDIUM_LAUNCHPAD_ID, + accounts, + data, + } + } +} + +#[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] +pub struct MigrateToAmmInstructionData { + discriminator: [u8; 8], +} + +impl MigrateToAmmInstructionData { + pub fn new() -> Self { + Self { + discriminator: [207, 82, 192, 145, 254, 207, 145, 223], + } + } + + pub(crate) fn try_to_vec(&self) -> Result, std::io::Error> { + borsh::to_vec(self) + } +} + +impl Default for MigrateToAmmInstructionData { + fn default() -> Self { + Self::new() + } +} + +#[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] +pub struct MigrateToAmmInstructionArgs { + pub base_lot_size: u64, + pub quote_lot_size: u64, + pub market_vault_signer_nonce: u8, +} + +impl MigrateToAmmInstructionArgs { + pub(crate) fn try_to_vec(&self) -> Result, std::io::Error> { + borsh::to_vec(self) + } +} + +/// Instruction builder for `MigrateToAmm`. +/// +/// ### Accounts: +/// +/// 0. `[writable, signer]` payer +/// 1. `[]` base_mint +/// 2. `[]` quote_mint +/// 3. `[optional]` openbook_program (default to `srmqPvymJeFKQ4zGQed1GFppgkRHL9kaELCbyksJtPX`) +/// 4. `[writable]` market +/// 5. `[writable]` request_queue +/// 6. `[writable]` event_queue +/// 7. `[writable]` bids +/// 8. `[writable]` asks +/// 9. `[]` market_vault_signer +/// 10. `[writable]` market_base_vault +/// 11. `[writable]` market_quote_vault +/// 12. `[optional]` amm_program (default to `675kPX9MHTjS2zt1qfr1NYHuzeLXfQM9H24wFSUt1Mp8`) +/// 13. `[writable]` amm_pool +/// 14. `[]` amm_authority +/// 15. `[writable]` amm_open_orders +/// 16. `[writable]` amm_lp_mint +/// 17. `[writable]` amm_base_vault +/// 18. `[writable]` amm_quote_vault +/// 19. `[writable]` amm_target_orders +/// 20. `[]` amm_config +/// 21. `[writable]` amm_create_fee_destination +/// 22. `[writable]` authority +/// 23. `[writable]` pool_state +/// 24. `[]` global_config +/// 25. `[writable]` base_vault +/// 26. `[writable]` quote_vault +/// 27. `[writable]` pool_lp_token +/// 28. `[optional]` spl_token_program (default to `TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA`) +/// 29. `[optional]` associated_token_program (default to `ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL`) +/// 30. `[optional]` system_program (default to `11111111111111111111111111111111`) +/// 31. `[optional]` rent_program (default to `SysvarRent111111111111111111111111111111111`) +#[derive(Clone, Debug, Default)] +pub struct MigrateToAmmBuilder { + payer: Option, + base_mint: Option, + quote_mint: Option, + openbook_program: Option, + market: Option, + request_queue: Option, + event_queue: Option, + bids: Option, + asks: Option, + market_vault_signer: Option, + market_base_vault: Option, + market_quote_vault: Option, + amm_program: Option, + amm_pool: Option, + amm_authority: Option, + amm_open_orders: Option, + amm_lp_mint: Option, + amm_base_vault: Option, + amm_quote_vault: Option, + amm_target_orders: Option, + amm_config: Option, + amm_create_fee_destination: Option, + authority: Option, + pool_state: Option, + global_config: Option, + base_vault: Option, + quote_vault: Option, + pool_lp_token: Option, + spl_token_program: Option, + associated_token_program: Option, + system_program: Option, + rent_program: Option, + base_lot_size: Option, + quote_lot_size: Option, + market_vault_signer_nonce: Option, + __remaining_accounts: Vec, +} + +impl MigrateToAmmBuilder { + pub fn new() -> Self { + Self::default() + } + /// Only migrate_to_amm_wallet can migrate to cpswap pool + /// This signer must match the migrate_to_amm_wallet saved in global_config + #[inline(always)] + pub fn payer(&mut self, payer: solana_address::Address) -> &mut Self { + self.payer = Some(payer); + self + } + /// The mint for the base token (token being sold) + #[inline(always)] + pub fn base_mint(&mut self, base_mint: solana_address::Address) -> &mut Self { + self.base_mint = Some(base_mint); + self + } + /// The mint for the quote token (token used to buy) + #[inline(always)] + pub fn quote_mint(&mut self, quote_mint: solana_address::Address) -> &mut Self { + self.quote_mint = Some(quote_mint); + self + } + /// `[optional account, default to 'srmqPvymJeFKQ4zGQed1GFppgkRHL9kaELCbyksJtPX']` + #[inline(always)] + pub fn openbook_program(&mut self, openbook_program: solana_address::Address) -> &mut Self { + self.openbook_program = Some(openbook_program); + self + } + /// Account created and asigned to openbook_program but not been initialized + #[inline(always)] + pub fn market(&mut self, market: solana_address::Address) -> &mut Self { + self.market = Some(market); + self + } + /// Account created and asigned to openbook_program but not been initialized + #[inline(always)] + pub fn request_queue(&mut self, request_queue: solana_address::Address) -> &mut Self { + self.request_queue = Some(request_queue); + self + } + /// Account created and asigned to openbook_program but not been initialized + #[inline(always)] + pub fn event_queue(&mut self, event_queue: solana_address::Address) -> &mut Self { + self.event_queue = Some(event_queue); + self + } + /// Account created and asigned to openbook_program but not been initialized + #[inline(always)] + pub fn bids(&mut self, bids: solana_address::Address) -> &mut Self { + self.bids = Some(bids); + self + } + /// Account created and asigned to openbook_program but not been initialized + #[inline(always)] + pub fn asks(&mut self, asks: solana_address::Address) -> &mut Self { + self.asks = Some(asks); + self + } + #[inline(always)] + pub fn market_vault_signer( + &mut self, + market_vault_signer: solana_address::Address, + ) -> &mut Self { + self.market_vault_signer = Some(market_vault_signer); + self + } + /// Token account that holds the market's base tokens + #[inline(always)] + pub fn market_base_vault(&mut self, market_base_vault: solana_address::Address) -> &mut Self { + self.market_base_vault = Some(market_base_vault); + self + } + /// Token account that holds the market's quote tokens + #[inline(always)] + pub fn market_quote_vault(&mut self, market_quote_vault: solana_address::Address) -> &mut Self { + self.market_quote_vault = Some(market_quote_vault); + self + } + /// `[optional account, default to '675kPX9MHTjS2zt1qfr1NYHuzeLXfQM9H24wFSUt1Mp8']` + #[inline(always)] + pub fn amm_program(&mut self, amm_program: solana_address::Address) -> &mut Self { + self.amm_program = Some(amm_program); + self + } + #[inline(always)] + pub fn amm_pool(&mut self, amm_pool: solana_address::Address) -> &mut Self { + self.amm_pool = Some(amm_pool); + self + } + #[inline(always)] + pub fn amm_authority(&mut self, amm_authority: solana_address::Address) -> &mut Self { + self.amm_authority = Some(amm_authority); + self + } + #[inline(always)] + pub fn amm_open_orders(&mut self, amm_open_orders: solana_address::Address) -> &mut Self { + self.amm_open_orders = Some(amm_open_orders); + self + } + #[inline(always)] + pub fn amm_lp_mint(&mut self, amm_lp_mint: solana_address::Address) -> &mut Self { + self.amm_lp_mint = Some(amm_lp_mint); + self + } + #[inline(always)] + pub fn amm_base_vault(&mut self, amm_base_vault: solana_address::Address) -> &mut Self { + self.amm_base_vault = Some(amm_base_vault); + self + } + #[inline(always)] + pub fn amm_quote_vault(&mut self, amm_quote_vault: solana_address::Address) -> &mut Self { + self.amm_quote_vault = Some(amm_quote_vault); + self + } + #[inline(always)] + pub fn amm_target_orders(&mut self, amm_target_orders: solana_address::Address) -> &mut Self { + self.amm_target_orders = Some(amm_target_orders); + self + } + #[inline(always)] + pub fn amm_config(&mut self, amm_config: solana_address::Address) -> &mut Self { + self.amm_config = Some(amm_config); + self + } + #[inline(always)] + pub fn amm_create_fee_destination( + &mut self, + amm_create_fee_destination: solana_address::Address, + ) -> &mut Self { + self.amm_create_fee_destination = Some(amm_create_fee_destination); + self + } + /// PDA that acts as the authority for pool vault operations + /// Generated using AUTH_SEED + #[inline(always)] + pub fn authority(&mut self, authority: solana_address::Address) -> &mut Self { + self.authority = Some(authority); + self + } + /// Account that stores the pool's state and parameters + /// PDA generated using POOL_SEED and both token mints + #[inline(always)] + pub fn pool_state(&mut self, pool_state: solana_address::Address) -> &mut Self { + self.pool_state = Some(pool_state); + self + } + /// Global config account stores owner + #[inline(always)] + pub fn global_config(&mut self, global_config: solana_address::Address) -> &mut Self { + self.global_config = Some(global_config); + self + } + /// The pool's vault for base tokens + /// Will be fully drained during migration + #[inline(always)] + pub fn base_vault(&mut self, base_vault: solana_address::Address) -> &mut Self { + self.base_vault = Some(base_vault); + self + } + /// The pool's vault for quote tokens + /// Will be fully drained during migration + #[inline(always)] + pub fn quote_vault(&mut self, quote_vault: solana_address::Address) -> &mut Self { + self.quote_vault = Some(quote_vault); + self + } + #[inline(always)] + pub fn pool_lp_token(&mut self, pool_lp_token: solana_address::Address) -> &mut Self { + self.pool_lp_token = Some(pool_lp_token); + self + } + /// `[optional account, default to 'TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA']` + /// SPL Token program for the base token + /// Must be the standard Token program + #[inline(always)] + pub fn spl_token_program(&mut self, spl_token_program: solana_address::Address) -> &mut Self { + self.spl_token_program = Some(spl_token_program); + self + } + /// `[optional account, default to 'ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL']` + /// Program to create an ATA for receiving fee NFT + #[inline(always)] + pub fn associated_token_program( + &mut self, + associated_token_program: solana_address::Address, + ) -> &mut Self { + self.associated_token_program = Some(associated_token_program); + self + } + /// `[optional account, default to '11111111111111111111111111111111']` + /// Required for account creation + #[inline(always)] + pub fn system_program(&mut self, system_program: solana_address::Address) -> &mut Self { + self.system_program = Some(system_program); + self + } + /// `[optional account, default to 'SysvarRent111111111111111111111111111111111']` + /// Required for rent exempt calculations + #[inline(always)] + pub fn rent_program(&mut self, rent_program: solana_address::Address) -> &mut Self { + self.rent_program = Some(rent_program); + self + } + #[inline(always)] + pub fn base_lot_size(&mut self, base_lot_size: u64) -> &mut Self { + self.base_lot_size = Some(base_lot_size); + self + } + #[inline(always)] + pub fn quote_lot_size(&mut self, quote_lot_size: u64) -> &mut Self { + self.quote_lot_size = Some(quote_lot_size); + self + } + #[inline(always)] + pub fn market_vault_signer_nonce(&mut self, market_vault_signer_nonce: u8) -> &mut Self { + self.market_vault_signer_nonce = Some(market_vault_signer_nonce); + self + } + /// Add an additional account to the instruction. + #[inline(always)] + pub fn add_remaining_account(&mut self, account: solana_instruction::AccountMeta) -> &mut Self { + self.__remaining_accounts.push(account); + self + } + /// Add additional accounts to the instruction. + #[inline(always)] + pub fn add_remaining_accounts( + &mut self, + accounts: &[solana_instruction::AccountMeta], + ) -> &mut Self { + self.__remaining_accounts.extend_from_slice(accounts); + self + } + #[allow(clippy::clone_on_copy)] + pub fn instruction(&self) -> solana_instruction::Instruction { + let accounts = MigrateToAmm { + payer: self.payer.expect("payer is not set"), + base_mint: self.base_mint.expect("base_mint is not set"), + quote_mint: self.quote_mint.expect("quote_mint is not set"), + openbook_program: self.openbook_program.unwrap_or(solana_address::address!( + "srmqPvymJeFKQ4zGQed1GFppgkRHL9kaELCbyksJtPX" + )), + market: self.market.expect("market is not set"), + request_queue: self.request_queue.expect("request_queue is not set"), + event_queue: self.event_queue.expect("event_queue is not set"), + bids: self.bids.expect("bids is not set"), + asks: self.asks.expect("asks is not set"), + market_vault_signer: self + .market_vault_signer + .expect("market_vault_signer is not set"), + market_base_vault: self + .market_base_vault + .expect("market_base_vault is not set"), + market_quote_vault: self + .market_quote_vault + .expect("market_quote_vault is not set"), + amm_program: self.amm_program.unwrap_or(solana_address::address!( + "675kPX9MHTjS2zt1qfr1NYHuzeLXfQM9H24wFSUt1Mp8" + )), + amm_pool: self.amm_pool.expect("amm_pool is not set"), + amm_authority: self.amm_authority.expect("amm_authority is not set"), + amm_open_orders: self.amm_open_orders.expect("amm_open_orders is not set"), + amm_lp_mint: self.amm_lp_mint.expect("amm_lp_mint is not set"), + amm_base_vault: self.amm_base_vault.expect("amm_base_vault is not set"), + amm_quote_vault: self.amm_quote_vault.expect("amm_quote_vault is not set"), + amm_target_orders: self + .amm_target_orders + .expect("amm_target_orders is not set"), + amm_config: self.amm_config.expect("amm_config is not set"), + amm_create_fee_destination: self + .amm_create_fee_destination + .expect("amm_create_fee_destination is not set"), + authority: self.authority.expect("authority is not set"), + pool_state: self.pool_state.expect("pool_state is not set"), + global_config: self.global_config.expect("global_config is not set"), + base_vault: self.base_vault.expect("base_vault is not set"), + quote_vault: self.quote_vault.expect("quote_vault is not set"), + pool_lp_token: self.pool_lp_token.expect("pool_lp_token is not set"), + spl_token_program: self.spl_token_program.unwrap_or(solana_address::address!( + "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA" + )), + associated_token_program: self.associated_token_program.unwrap_or( + solana_address::address!("ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL"), + ), + system_program: self + .system_program + .unwrap_or(solana_address::address!("11111111111111111111111111111111")), + rent_program: self.rent_program.unwrap_or(solana_address::address!( + "SysvarRent111111111111111111111111111111111" + )), + }; + let args = MigrateToAmmInstructionArgs { + base_lot_size: self + .base_lot_size + .clone() + .expect("base_lot_size is not set"), + quote_lot_size: self + .quote_lot_size + .clone() + .expect("quote_lot_size is not set"), + market_vault_signer_nonce: self + .market_vault_signer_nonce + .clone() + .expect("market_vault_signer_nonce is not set"), + }; + + accounts.instruction_with_remaining_accounts(args, &self.__remaining_accounts) + } +} + +/// `migrate_to_amm` CPI accounts. +pub struct MigrateToAmmCpiAccounts<'a, 'b> { + /// Only migrate_to_amm_wallet can migrate to cpswap pool + /// This signer must match the migrate_to_amm_wallet saved in global_config + pub payer: &'b solana_account_info::AccountInfo<'a>, + /// The mint for the base token (token being sold) + pub base_mint: &'b solana_account_info::AccountInfo<'a>, + /// The mint for the quote token (token used to buy) + pub quote_mint: &'b solana_account_info::AccountInfo<'a>, + + pub openbook_program: &'b solana_account_info::AccountInfo<'a>, + /// Account created and asigned to openbook_program but not been initialized + pub market: &'b solana_account_info::AccountInfo<'a>, + /// Account created and asigned to openbook_program but not been initialized + pub request_queue: &'b solana_account_info::AccountInfo<'a>, + /// Account created and asigned to openbook_program but not been initialized + pub event_queue: &'b solana_account_info::AccountInfo<'a>, + /// Account created and asigned to openbook_program but not been initialized + pub bids: &'b solana_account_info::AccountInfo<'a>, + /// Account created and asigned to openbook_program but not been initialized + pub asks: &'b solana_account_info::AccountInfo<'a>, + + pub market_vault_signer: &'b solana_account_info::AccountInfo<'a>, + /// Token account that holds the market's base tokens + pub market_base_vault: &'b solana_account_info::AccountInfo<'a>, + /// Token account that holds the market's quote tokens + pub market_quote_vault: &'b solana_account_info::AccountInfo<'a>, + + pub amm_program: &'b solana_account_info::AccountInfo<'a>, + + pub amm_pool: &'b solana_account_info::AccountInfo<'a>, + + pub amm_authority: &'b solana_account_info::AccountInfo<'a>, + + pub amm_open_orders: &'b solana_account_info::AccountInfo<'a>, + + pub amm_lp_mint: &'b solana_account_info::AccountInfo<'a>, + + pub amm_base_vault: &'b solana_account_info::AccountInfo<'a>, + + pub amm_quote_vault: &'b solana_account_info::AccountInfo<'a>, + + pub amm_target_orders: &'b solana_account_info::AccountInfo<'a>, + + pub amm_config: &'b solana_account_info::AccountInfo<'a>, + + pub amm_create_fee_destination: &'b solana_account_info::AccountInfo<'a>, + /// PDA that acts as the authority for pool vault operations + /// Generated using AUTH_SEED + pub authority: &'b solana_account_info::AccountInfo<'a>, + /// Account that stores the pool's state and parameters + /// PDA generated using POOL_SEED and both token mints + pub pool_state: &'b solana_account_info::AccountInfo<'a>, + /// Global config account stores owner + pub global_config: &'b solana_account_info::AccountInfo<'a>, + /// The pool's vault for base tokens + /// Will be fully drained during migration + pub base_vault: &'b solana_account_info::AccountInfo<'a>, + /// The pool's vault for quote tokens + /// Will be fully drained during migration + pub quote_vault: &'b solana_account_info::AccountInfo<'a>, + + pub pool_lp_token: &'b solana_account_info::AccountInfo<'a>, + /// SPL Token program for the base token + /// Must be the standard Token program + pub spl_token_program: &'b solana_account_info::AccountInfo<'a>, + /// Program to create an ATA for receiving fee NFT + pub associated_token_program: &'b solana_account_info::AccountInfo<'a>, + /// Required for account creation + pub system_program: &'b solana_account_info::AccountInfo<'a>, + /// Required for rent exempt calculations + pub rent_program: &'b solana_account_info::AccountInfo<'a>, +} + +/// `migrate_to_amm` CPI instruction. +pub struct MigrateToAmmCpi<'a, 'b> { + /// The program to invoke. + pub __program: &'b solana_account_info::AccountInfo<'a>, + /// Only migrate_to_amm_wallet can migrate to cpswap pool + /// This signer must match the migrate_to_amm_wallet saved in global_config + pub payer: &'b solana_account_info::AccountInfo<'a>, + /// The mint for the base token (token being sold) + pub base_mint: &'b solana_account_info::AccountInfo<'a>, + /// The mint for the quote token (token used to buy) + pub quote_mint: &'b solana_account_info::AccountInfo<'a>, + + pub openbook_program: &'b solana_account_info::AccountInfo<'a>, + /// Account created and asigned to openbook_program but not been initialized + pub market: &'b solana_account_info::AccountInfo<'a>, + /// Account created and asigned to openbook_program but not been initialized + pub request_queue: &'b solana_account_info::AccountInfo<'a>, + /// Account created and asigned to openbook_program but not been initialized + pub event_queue: &'b solana_account_info::AccountInfo<'a>, + /// Account created and asigned to openbook_program but not been initialized + pub bids: &'b solana_account_info::AccountInfo<'a>, + /// Account created and asigned to openbook_program but not been initialized + pub asks: &'b solana_account_info::AccountInfo<'a>, + + pub market_vault_signer: &'b solana_account_info::AccountInfo<'a>, + /// Token account that holds the market's base tokens + pub market_base_vault: &'b solana_account_info::AccountInfo<'a>, + /// Token account that holds the market's quote tokens + pub market_quote_vault: &'b solana_account_info::AccountInfo<'a>, + + pub amm_program: &'b solana_account_info::AccountInfo<'a>, + + pub amm_pool: &'b solana_account_info::AccountInfo<'a>, + + pub amm_authority: &'b solana_account_info::AccountInfo<'a>, + + pub amm_open_orders: &'b solana_account_info::AccountInfo<'a>, + + pub amm_lp_mint: &'b solana_account_info::AccountInfo<'a>, + + pub amm_base_vault: &'b solana_account_info::AccountInfo<'a>, + + pub amm_quote_vault: &'b solana_account_info::AccountInfo<'a>, + + pub amm_target_orders: &'b solana_account_info::AccountInfo<'a>, + + pub amm_config: &'b solana_account_info::AccountInfo<'a>, + + pub amm_create_fee_destination: &'b solana_account_info::AccountInfo<'a>, + /// PDA that acts as the authority for pool vault operations + /// Generated using AUTH_SEED + pub authority: &'b solana_account_info::AccountInfo<'a>, + /// Account that stores the pool's state and parameters + /// PDA generated using POOL_SEED and both token mints + pub pool_state: &'b solana_account_info::AccountInfo<'a>, + /// Global config account stores owner + pub global_config: &'b solana_account_info::AccountInfo<'a>, + /// The pool's vault for base tokens + /// Will be fully drained during migration + pub base_vault: &'b solana_account_info::AccountInfo<'a>, + /// The pool's vault for quote tokens + /// Will be fully drained during migration + pub quote_vault: &'b solana_account_info::AccountInfo<'a>, + + pub pool_lp_token: &'b solana_account_info::AccountInfo<'a>, + /// SPL Token program for the base token + /// Must be the standard Token program + pub spl_token_program: &'b solana_account_info::AccountInfo<'a>, + /// Program to create an ATA for receiving fee NFT + pub associated_token_program: &'b solana_account_info::AccountInfo<'a>, + /// Required for account creation + pub system_program: &'b solana_account_info::AccountInfo<'a>, + /// Required for rent exempt calculations + pub rent_program: &'b solana_account_info::AccountInfo<'a>, + /// The arguments for the instruction. + pub __args: MigrateToAmmInstructionArgs, +} + +impl<'a, 'b> MigrateToAmmCpi<'a, 'b> { + pub fn new( + program: &'b solana_account_info::AccountInfo<'a>, + accounts: MigrateToAmmCpiAccounts<'a, 'b>, + args: MigrateToAmmInstructionArgs, + ) -> Self { + Self { + __program: program, + payer: accounts.payer, + base_mint: accounts.base_mint, + quote_mint: accounts.quote_mint, + openbook_program: accounts.openbook_program, + market: accounts.market, + request_queue: accounts.request_queue, + event_queue: accounts.event_queue, + bids: accounts.bids, + asks: accounts.asks, + market_vault_signer: accounts.market_vault_signer, + market_base_vault: accounts.market_base_vault, + market_quote_vault: accounts.market_quote_vault, + amm_program: accounts.amm_program, + amm_pool: accounts.amm_pool, + amm_authority: accounts.amm_authority, + amm_open_orders: accounts.amm_open_orders, + amm_lp_mint: accounts.amm_lp_mint, + amm_base_vault: accounts.amm_base_vault, + amm_quote_vault: accounts.amm_quote_vault, + amm_target_orders: accounts.amm_target_orders, + amm_config: accounts.amm_config, + amm_create_fee_destination: accounts.amm_create_fee_destination, + authority: accounts.authority, + pool_state: accounts.pool_state, + global_config: accounts.global_config, + base_vault: accounts.base_vault, + quote_vault: accounts.quote_vault, + pool_lp_token: accounts.pool_lp_token, + spl_token_program: accounts.spl_token_program, + associated_token_program: accounts.associated_token_program, + system_program: accounts.system_program, + rent_program: accounts.rent_program, + __args: args, + } + } + #[inline(always)] + pub fn invoke(&self) -> solana_program_error::ProgramResult { + self.invoke_signed_with_remaining_accounts(&[], &[]) + } + #[inline(always)] + pub fn invoke_with_remaining_accounts( + &self, + remaining_accounts: &[(&'b solana_account_info::AccountInfo<'a>, bool, bool)], + ) -> solana_program_error::ProgramResult { + self.invoke_signed_with_remaining_accounts(&[], remaining_accounts) + } + #[inline(always)] + pub fn invoke_signed(&self, signers_seeds: &[&[&[u8]]]) -> solana_program_error::ProgramResult { + self.invoke_signed_with_remaining_accounts(signers_seeds, &[]) + } + #[allow(clippy::arithmetic_side_effects)] + #[allow(clippy::clone_on_copy)] + #[allow(clippy::vec_init_then_push)] + pub fn invoke_signed_with_remaining_accounts( + &self, + signers_seeds: &[&[&[u8]]], + remaining_accounts: &[(&'b solana_account_info::AccountInfo<'a>, bool, bool)], + ) -> solana_program_error::ProgramResult { + let mut accounts = Vec::with_capacity(32 + remaining_accounts.len()); + accounts.push(solana_instruction::AccountMeta::new(*self.payer.key, true)); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.base_mint.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.quote_mint.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.openbook_program.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + *self.market.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + *self.request_queue.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + *self.event_queue.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new(*self.bids.key, false)); + accounts.push(solana_instruction::AccountMeta::new(*self.asks.key, false)); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.market_vault_signer.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + *self.market_base_vault.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + *self.market_quote_vault.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.amm_program.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + *self.amm_pool.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.amm_authority.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + *self.amm_open_orders.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + *self.amm_lp_mint.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + *self.amm_base_vault.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + *self.amm_quote_vault.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + *self.amm_target_orders.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.amm_config.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + *self.amm_create_fee_destination.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + *self.authority.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + *self.pool_state.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.global_config.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + *self.base_vault.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + *self.quote_vault.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + *self.pool_lp_token.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.spl_token_program.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.associated_token_program.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.system_program.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.rent_program.key, + false, + )); + remaining_accounts.iter().for_each(|remaining_account| { + accounts.push(solana_instruction::AccountMeta { + pubkey: *remaining_account.0.key, + is_signer: remaining_account.1, + is_writable: remaining_account.2, + }) + }); + let mut data = MigrateToAmmInstructionData::new().try_to_vec().unwrap(); + let mut args = self.__args.try_to_vec().unwrap(); + data.append(&mut args); + + let instruction = solana_instruction::Instruction { + program_id: crate::RAYDIUM_LAUNCHPAD_ID, + accounts, + data, + }; + let mut account_infos = Vec::with_capacity(33 + remaining_accounts.len()); + account_infos.push(self.__program.clone()); + account_infos.push(self.payer.clone()); + account_infos.push(self.base_mint.clone()); + account_infos.push(self.quote_mint.clone()); + account_infos.push(self.openbook_program.clone()); + account_infos.push(self.market.clone()); + account_infos.push(self.request_queue.clone()); + account_infos.push(self.event_queue.clone()); + account_infos.push(self.bids.clone()); + account_infos.push(self.asks.clone()); + account_infos.push(self.market_vault_signer.clone()); + account_infos.push(self.market_base_vault.clone()); + account_infos.push(self.market_quote_vault.clone()); + account_infos.push(self.amm_program.clone()); + account_infos.push(self.amm_pool.clone()); + account_infos.push(self.amm_authority.clone()); + account_infos.push(self.amm_open_orders.clone()); + account_infos.push(self.amm_lp_mint.clone()); + account_infos.push(self.amm_base_vault.clone()); + account_infos.push(self.amm_quote_vault.clone()); + account_infos.push(self.amm_target_orders.clone()); + account_infos.push(self.amm_config.clone()); + account_infos.push(self.amm_create_fee_destination.clone()); + account_infos.push(self.authority.clone()); + account_infos.push(self.pool_state.clone()); + account_infos.push(self.global_config.clone()); + account_infos.push(self.base_vault.clone()); + account_infos.push(self.quote_vault.clone()); + account_infos.push(self.pool_lp_token.clone()); + account_infos.push(self.spl_token_program.clone()); + account_infos.push(self.associated_token_program.clone()); + account_infos.push(self.system_program.clone()); + account_infos.push(self.rent_program.clone()); + remaining_accounts + .iter() + .for_each(|remaining_account| account_infos.push(remaining_account.0.clone())); + + if signers_seeds.is_empty() { + solana_cpi::invoke(&instruction, &account_infos) + } else { + solana_cpi::invoke_signed(&instruction, &account_infos, signers_seeds) + } + } +} + +/// Instruction builder for `MigrateToAmm` via CPI. +/// +/// ### Accounts: +/// +/// 0. `[writable, signer]` payer +/// 1. `[]` base_mint +/// 2. `[]` quote_mint +/// 3. `[]` openbook_program +/// 4. `[writable]` market +/// 5. `[writable]` request_queue +/// 6. `[writable]` event_queue +/// 7. `[writable]` bids +/// 8. `[writable]` asks +/// 9. `[]` market_vault_signer +/// 10. `[writable]` market_base_vault +/// 11. `[writable]` market_quote_vault +/// 12. `[]` amm_program +/// 13. `[writable]` amm_pool +/// 14. `[]` amm_authority +/// 15. `[writable]` amm_open_orders +/// 16. `[writable]` amm_lp_mint +/// 17. `[writable]` amm_base_vault +/// 18. `[writable]` amm_quote_vault +/// 19. `[writable]` amm_target_orders +/// 20. `[]` amm_config +/// 21. `[writable]` amm_create_fee_destination +/// 22. `[writable]` authority +/// 23. `[writable]` pool_state +/// 24. `[]` global_config +/// 25. `[writable]` base_vault +/// 26. `[writable]` quote_vault +/// 27. `[writable]` pool_lp_token +/// 28. `[]` spl_token_program +/// 29. `[]` associated_token_program +/// 30. `[]` system_program +/// 31. `[]` rent_program +#[derive(Clone, Debug)] +pub struct MigrateToAmmCpiBuilder<'a, 'b> { + instruction: Box>, +} + +impl<'a, 'b> MigrateToAmmCpiBuilder<'a, 'b> { + pub fn new(program: &'b solana_account_info::AccountInfo<'a>) -> Self { + let instruction = Box::new(MigrateToAmmCpiBuilderInstruction { + __program: program, + payer: None, + base_mint: None, + quote_mint: None, + openbook_program: None, + market: None, + request_queue: None, + event_queue: None, + bids: None, + asks: None, + market_vault_signer: None, + market_base_vault: None, + market_quote_vault: None, + amm_program: None, + amm_pool: None, + amm_authority: None, + amm_open_orders: None, + amm_lp_mint: None, + amm_base_vault: None, + amm_quote_vault: None, + amm_target_orders: None, + amm_config: None, + amm_create_fee_destination: None, + authority: None, + pool_state: None, + global_config: None, + base_vault: None, + quote_vault: None, + pool_lp_token: None, + spl_token_program: None, + associated_token_program: None, + system_program: None, + rent_program: None, + base_lot_size: None, + quote_lot_size: None, + market_vault_signer_nonce: None, + __remaining_accounts: Vec::new(), + }); + Self { instruction } + } + /// Only migrate_to_amm_wallet can migrate to cpswap pool + /// This signer must match the migrate_to_amm_wallet saved in global_config + #[inline(always)] + pub fn payer(&mut self, payer: &'b solana_account_info::AccountInfo<'a>) -> &mut Self { + self.instruction.payer = Some(payer); + self + } + /// The mint for the base token (token being sold) + #[inline(always)] + pub fn base_mint(&mut self, base_mint: &'b solana_account_info::AccountInfo<'a>) -> &mut Self { + self.instruction.base_mint = Some(base_mint); + self + } + /// The mint for the quote token (token used to buy) + #[inline(always)] + pub fn quote_mint( + &mut self, + quote_mint: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.quote_mint = Some(quote_mint); + self + } + #[inline(always)] + pub fn openbook_program( + &mut self, + openbook_program: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.openbook_program = Some(openbook_program); + self + } + /// Account created and asigned to openbook_program but not been initialized + #[inline(always)] + pub fn market(&mut self, market: &'b solana_account_info::AccountInfo<'a>) -> &mut Self { + self.instruction.market = Some(market); + self + } + /// Account created and asigned to openbook_program but not been initialized + #[inline(always)] + pub fn request_queue( + &mut self, + request_queue: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.request_queue = Some(request_queue); + self + } + /// Account created and asigned to openbook_program but not been initialized + #[inline(always)] + pub fn event_queue( + &mut self, + event_queue: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.event_queue = Some(event_queue); + self + } + /// Account created and asigned to openbook_program but not been initialized + #[inline(always)] + pub fn bids(&mut self, bids: &'b solana_account_info::AccountInfo<'a>) -> &mut Self { + self.instruction.bids = Some(bids); + self + } + /// Account created and asigned to openbook_program but not been initialized + #[inline(always)] + pub fn asks(&mut self, asks: &'b solana_account_info::AccountInfo<'a>) -> &mut Self { + self.instruction.asks = Some(asks); + self + } + #[inline(always)] + pub fn market_vault_signer( + &mut self, + market_vault_signer: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.market_vault_signer = Some(market_vault_signer); + self + } + /// Token account that holds the market's base tokens + #[inline(always)] + pub fn market_base_vault( + &mut self, + market_base_vault: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.market_base_vault = Some(market_base_vault); + self + } + /// Token account that holds the market's quote tokens + #[inline(always)] + pub fn market_quote_vault( + &mut self, + market_quote_vault: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.market_quote_vault = Some(market_quote_vault); + self + } + #[inline(always)] + pub fn amm_program( + &mut self, + amm_program: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.amm_program = Some(amm_program); + self + } + #[inline(always)] + pub fn amm_pool(&mut self, amm_pool: &'b solana_account_info::AccountInfo<'a>) -> &mut Self { + self.instruction.amm_pool = Some(amm_pool); + self + } + #[inline(always)] + pub fn amm_authority( + &mut self, + amm_authority: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.amm_authority = Some(amm_authority); + self + } + #[inline(always)] + pub fn amm_open_orders( + &mut self, + amm_open_orders: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.amm_open_orders = Some(amm_open_orders); + self + } + #[inline(always)] + pub fn amm_lp_mint( + &mut self, + amm_lp_mint: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.amm_lp_mint = Some(amm_lp_mint); + self + } + #[inline(always)] + pub fn amm_base_vault( + &mut self, + amm_base_vault: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.amm_base_vault = Some(amm_base_vault); + self + } + #[inline(always)] + pub fn amm_quote_vault( + &mut self, + amm_quote_vault: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.amm_quote_vault = Some(amm_quote_vault); + self + } + #[inline(always)] + pub fn amm_target_orders( + &mut self, + amm_target_orders: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.amm_target_orders = Some(amm_target_orders); + self + } + #[inline(always)] + pub fn amm_config( + &mut self, + amm_config: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.amm_config = Some(amm_config); + self + } + #[inline(always)] + pub fn amm_create_fee_destination( + &mut self, + amm_create_fee_destination: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.amm_create_fee_destination = Some(amm_create_fee_destination); + self + } + /// PDA that acts as the authority for pool vault operations + /// Generated using AUTH_SEED + #[inline(always)] + pub fn authority(&mut self, authority: &'b solana_account_info::AccountInfo<'a>) -> &mut Self { + self.instruction.authority = Some(authority); + self + } + /// Account that stores the pool's state and parameters + /// PDA generated using POOL_SEED and both token mints + #[inline(always)] + pub fn pool_state( + &mut self, + pool_state: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.pool_state = Some(pool_state); + self + } + /// Global config account stores owner + #[inline(always)] + pub fn global_config( + &mut self, + global_config: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.global_config = Some(global_config); + self + } + /// The pool's vault for base tokens + /// Will be fully drained during migration + #[inline(always)] + pub fn base_vault( + &mut self, + base_vault: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.base_vault = Some(base_vault); + self + } + /// The pool's vault for quote tokens + /// Will be fully drained during migration + #[inline(always)] + pub fn quote_vault( + &mut self, + quote_vault: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.quote_vault = Some(quote_vault); + self + } + #[inline(always)] + pub fn pool_lp_token( + &mut self, + pool_lp_token: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.pool_lp_token = Some(pool_lp_token); + self + } + /// SPL Token program for the base token + /// Must be the standard Token program + #[inline(always)] + pub fn spl_token_program( + &mut self, + spl_token_program: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.spl_token_program = Some(spl_token_program); + self + } + /// Program to create an ATA for receiving fee NFT + #[inline(always)] + pub fn associated_token_program( + &mut self, + associated_token_program: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.associated_token_program = Some(associated_token_program); + self + } + /// Required for account creation + #[inline(always)] + pub fn system_program( + &mut self, + system_program: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.system_program = Some(system_program); + self + } + /// Required for rent exempt calculations + #[inline(always)] + pub fn rent_program( + &mut self, + rent_program: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.rent_program = Some(rent_program); + self + } + #[inline(always)] + pub fn base_lot_size(&mut self, base_lot_size: u64) -> &mut Self { + self.instruction.base_lot_size = Some(base_lot_size); + self + } + #[inline(always)] + pub fn quote_lot_size(&mut self, quote_lot_size: u64) -> &mut Self { + self.instruction.quote_lot_size = Some(quote_lot_size); + self + } + #[inline(always)] + pub fn market_vault_signer_nonce(&mut self, market_vault_signer_nonce: u8) -> &mut Self { + self.instruction.market_vault_signer_nonce = Some(market_vault_signer_nonce); + self + } + /// Add an additional account to the instruction. + #[inline(always)] + pub fn add_remaining_account( + &mut self, + account: &'b solana_account_info::AccountInfo<'a>, + is_writable: bool, + is_signer: bool, + ) -> &mut Self { + self.instruction + .__remaining_accounts + .push((account, is_writable, is_signer)); + self + } + /// Add additional accounts to the instruction. + /// + /// Each account is represented by a tuple of the `AccountInfo`, a `bool` indicating whether the account is writable or not, + /// and a `bool` indicating whether the account is a signer or not. + #[inline(always)] + pub fn add_remaining_accounts( + &mut self, + accounts: &[(&'b solana_account_info::AccountInfo<'a>, bool, bool)], + ) -> &mut Self { + self.instruction + .__remaining_accounts + .extend_from_slice(accounts); + self + } + #[inline(always)] + pub fn invoke(&self) -> solana_program_error::ProgramResult { + self.invoke_signed(&[]) + } + #[allow(clippy::clone_on_copy)] + #[allow(clippy::vec_init_then_push)] + pub fn invoke_signed(&self, signers_seeds: &[&[&[u8]]]) -> solana_program_error::ProgramResult { + let args = MigrateToAmmInstructionArgs { + base_lot_size: self + .instruction + .base_lot_size + .clone() + .expect("base_lot_size is not set"), + quote_lot_size: self + .instruction + .quote_lot_size + .clone() + .expect("quote_lot_size is not set"), + market_vault_signer_nonce: self + .instruction + .market_vault_signer_nonce + .clone() + .expect("market_vault_signer_nonce is not set"), + }; + let instruction = MigrateToAmmCpi { + __program: self.instruction.__program, + + payer: self.instruction.payer.expect("payer is not set"), + + base_mint: self.instruction.base_mint.expect("base_mint is not set"), + + quote_mint: self.instruction.quote_mint.expect("quote_mint is not set"), + + openbook_program: self + .instruction + .openbook_program + .expect("openbook_program is not set"), + + market: self.instruction.market.expect("market is not set"), + + request_queue: self + .instruction + .request_queue + .expect("request_queue is not set"), + + event_queue: self + .instruction + .event_queue + .expect("event_queue is not set"), + + bids: self.instruction.bids.expect("bids is not set"), + + asks: self.instruction.asks.expect("asks is not set"), + + market_vault_signer: self + .instruction + .market_vault_signer + .expect("market_vault_signer is not set"), + + market_base_vault: self + .instruction + .market_base_vault + .expect("market_base_vault is not set"), + + market_quote_vault: self + .instruction + .market_quote_vault + .expect("market_quote_vault is not set"), + + amm_program: self + .instruction + .amm_program + .expect("amm_program is not set"), + + amm_pool: self.instruction.amm_pool.expect("amm_pool is not set"), + + amm_authority: self + .instruction + .amm_authority + .expect("amm_authority is not set"), + + amm_open_orders: self + .instruction + .amm_open_orders + .expect("amm_open_orders is not set"), + + amm_lp_mint: self + .instruction + .amm_lp_mint + .expect("amm_lp_mint is not set"), + + amm_base_vault: self + .instruction + .amm_base_vault + .expect("amm_base_vault is not set"), + + amm_quote_vault: self + .instruction + .amm_quote_vault + .expect("amm_quote_vault is not set"), + + amm_target_orders: self + .instruction + .amm_target_orders + .expect("amm_target_orders is not set"), + + amm_config: self.instruction.amm_config.expect("amm_config is not set"), + + amm_create_fee_destination: self + .instruction + .amm_create_fee_destination + .expect("amm_create_fee_destination is not set"), + + authority: self.instruction.authority.expect("authority is not set"), + + pool_state: self.instruction.pool_state.expect("pool_state is not set"), + + global_config: self + .instruction + .global_config + .expect("global_config is not set"), + + base_vault: self.instruction.base_vault.expect("base_vault is not set"), + + quote_vault: self + .instruction + .quote_vault + .expect("quote_vault is not set"), + + pool_lp_token: self + .instruction + .pool_lp_token + .expect("pool_lp_token is not set"), + + spl_token_program: self + .instruction + .spl_token_program + .expect("spl_token_program is not set"), + + associated_token_program: self + .instruction + .associated_token_program + .expect("associated_token_program is not set"), + + system_program: self + .instruction + .system_program + .expect("system_program is not set"), + + rent_program: self + .instruction + .rent_program + .expect("rent_program is not set"), + __args: args, + }; + instruction.invoke_signed_with_remaining_accounts( + signers_seeds, + &self.instruction.__remaining_accounts, + ) + } +} + +#[derive(Clone, Debug)] +struct MigrateToAmmCpiBuilderInstruction<'a, 'b> { + __program: &'b solana_account_info::AccountInfo<'a>, + payer: Option<&'b solana_account_info::AccountInfo<'a>>, + base_mint: Option<&'b solana_account_info::AccountInfo<'a>>, + quote_mint: Option<&'b solana_account_info::AccountInfo<'a>>, + openbook_program: Option<&'b solana_account_info::AccountInfo<'a>>, + market: Option<&'b solana_account_info::AccountInfo<'a>>, + request_queue: Option<&'b solana_account_info::AccountInfo<'a>>, + event_queue: Option<&'b solana_account_info::AccountInfo<'a>>, + bids: Option<&'b solana_account_info::AccountInfo<'a>>, + asks: Option<&'b solana_account_info::AccountInfo<'a>>, + market_vault_signer: Option<&'b solana_account_info::AccountInfo<'a>>, + market_base_vault: Option<&'b solana_account_info::AccountInfo<'a>>, + market_quote_vault: Option<&'b solana_account_info::AccountInfo<'a>>, + amm_program: Option<&'b solana_account_info::AccountInfo<'a>>, + amm_pool: Option<&'b solana_account_info::AccountInfo<'a>>, + amm_authority: Option<&'b solana_account_info::AccountInfo<'a>>, + amm_open_orders: Option<&'b solana_account_info::AccountInfo<'a>>, + amm_lp_mint: Option<&'b solana_account_info::AccountInfo<'a>>, + amm_base_vault: Option<&'b solana_account_info::AccountInfo<'a>>, + amm_quote_vault: Option<&'b solana_account_info::AccountInfo<'a>>, + amm_target_orders: Option<&'b solana_account_info::AccountInfo<'a>>, + amm_config: Option<&'b solana_account_info::AccountInfo<'a>>, + amm_create_fee_destination: Option<&'b solana_account_info::AccountInfo<'a>>, + authority: Option<&'b solana_account_info::AccountInfo<'a>>, + pool_state: Option<&'b solana_account_info::AccountInfo<'a>>, + global_config: Option<&'b solana_account_info::AccountInfo<'a>>, + base_vault: Option<&'b solana_account_info::AccountInfo<'a>>, + quote_vault: Option<&'b solana_account_info::AccountInfo<'a>>, + pool_lp_token: Option<&'b solana_account_info::AccountInfo<'a>>, + spl_token_program: Option<&'b solana_account_info::AccountInfo<'a>>, + associated_token_program: Option<&'b solana_account_info::AccountInfo<'a>>, + system_program: Option<&'b solana_account_info::AccountInfo<'a>>, + rent_program: Option<&'b solana_account_info::AccountInfo<'a>>, + base_lot_size: Option, + quote_lot_size: Option, + market_vault_signer_nonce: Option, + /// Additional instruction accounts `(AccountInfo, is_writable, is_signer)`. + __remaining_accounts: Vec<(&'b solana_account_info::AccountInfo<'a>, bool, bool)>, +} diff --git a/e2e/raydium-launchpad/src/generated/instructions/migrate_to_cpswap.rs b/e2e/raydium-launchpad/src/generated/instructions/migrate_to_cpswap.rs new file mode 100644 index 0000000..398ac27 --- /dev/null +++ b/e2e/raydium-launchpad/src/generated/instructions/migrate_to_cpswap.rs @@ -0,0 +1,1468 @@ +//! This code was AUTOGENERATED using the codama library. +//! Please DO NOT EDIT THIS FILE, instead use visitors +//! to add features, then rerun codama to update it. +//! +//! +//! + +use borsh::BorshDeserialize; +use borsh::BorshSerialize; + +pub const MIGRATE_TO_CPSWAP_DISCRIMINATOR: [u8; 8] = [136, 92, 200, 103, 28, 218, 144, 140]; + +/// Accounts. +#[derive(Debug)] +pub struct MigrateToCpswap { + /// Only migrate_to_cpswap_wallet can migrate to cpswap pool + /// This signer must match the migrate_to_cpswap_wallet saved in global_config + pub payer: solana_address::Address, + /// The mint for the base token (token being sold) + pub base_mint: solana_address::Address, + /// The mint for the quote token (token used to buy) + pub quote_mint: solana_address::Address, + /// Platform configuration account containing platform-wide settings + /// Used to read platform fee rate + pub platform_config: solana_address::Address, + + pub cpswap_program: solana_address::Address, + /// PDA account: + /// seeds = [ + /// b"pool", + /// cpswap_config.key().as_ref(), + /// token_0_mint.key().as_ref(), + /// token_1_mint.key().as_ref(), + /// ], + /// seeds::program = cpswap_program, + /// + /// Or random account: must be signed by cli + pub cpswap_pool: solana_address::Address, + + pub cpswap_authority: solana_address::Address, + + pub cpswap_lp_mint: solana_address::Address, + + pub cpswap_base_vault: solana_address::Address, + + pub cpswap_quote_vault: solana_address::Address, + + pub cpswap_config: solana_address::Address, + + pub cpswap_create_pool_fee: solana_address::Address, + + pub cpswap_observation: solana_address::Address, + + pub lock_program: solana_address::Address, + + pub lock_authority: solana_address::Address, + + pub lock_lp_vault: solana_address::Address, + /// PDA that acts as the authority for pool vault operations + /// Generated using AUTH_SEED + pub authority: solana_address::Address, + /// Account that stores the pool's state and parameters + /// PDA generated using POOL_SEED and both token mints + pub pool_state: solana_address::Address, + /// Global config account stores owner + pub global_config: solana_address::Address, + /// The pool's vault for base tokens + /// Will be fully drained during migration + pub base_vault: solana_address::Address, + /// The pool's vault for quote tokens + /// Will be fully drained during migration + pub quote_vault: solana_address::Address, + + pub pool_lp_token: solana_address::Address, + /// SPL Token program for the base token + /// Must be the standard Token program + pub base_token_program: solana_address::Address, + /// SPL Token program for the quote token + pub quote_token_program: solana_address::Address, + /// Program to create an ATA for receiving fee NFT + pub associated_token_program: solana_address::Address, + /// Required for account creation + pub system_program: solana_address::Address, + /// Required for rent exempt calculations + pub rent_program: solana_address::Address, + /// Program to create NFT metadata accunt + pub metadata_program: solana_address::Address, +} + +impl MigrateToCpswap { + pub fn instruction(&self) -> solana_instruction::Instruction { + self.instruction_with_remaining_accounts(&[]) + } + #[allow(clippy::arithmetic_side_effects)] + #[allow(clippy::vec_init_then_push)] + pub fn instruction_with_remaining_accounts( + &self, + remaining_accounts: &[solana_instruction::AccountMeta], + ) -> solana_instruction::Instruction { + let mut accounts = Vec::with_capacity(28 + remaining_accounts.len()); + accounts.push(solana_instruction::AccountMeta::new(self.payer, true)); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.base_mint, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.quote_mint, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.platform_config, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.cpswap_program, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + self.cpswap_pool, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.cpswap_authority, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + self.cpswap_lp_mint, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + self.cpswap_base_vault, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + self.cpswap_quote_vault, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.cpswap_config, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + self.cpswap_create_pool_fee, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + self.cpswap_observation, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.lock_program, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.lock_authority, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + self.lock_lp_vault, + false, + )); + accounts.push(solana_instruction::AccountMeta::new(self.authority, false)); + accounts.push(solana_instruction::AccountMeta::new(self.pool_state, false)); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.global_config, + false, + )); + accounts.push(solana_instruction::AccountMeta::new(self.base_vault, false)); + accounts.push(solana_instruction::AccountMeta::new( + self.quote_vault, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + self.pool_lp_token, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.base_token_program, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.quote_token_program, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.associated_token_program, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.system_program, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.rent_program, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.metadata_program, + false, + )); + accounts.extend_from_slice(remaining_accounts); + let data = MigrateToCpswapInstructionData::new().try_to_vec().unwrap(); + + solana_instruction::Instruction { + program_id: crate::RAYDIUM_LAUNCHPAD_ID, + accounts, + data, + } + } +} + +#[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] +pub struct MigrateToCpswapInstructionData { + discriminator: [u8; 8], +} + +impl MigrateToCpswapInstructionData { + pub fn new() -> Self { + Self { + discriminator: [136, 92, 200, 103, 28, 218, 144, 140], + } + } + + pub(crate) fn try_to_vec(&self) -> Result, std::io::Error> { + borsh::to_vec(self) + } +} + +impl Default for MigrateToCpswapInstructionData { + fn default() -> Self { + Self::new() + } +} + +/// Instruction builder for `MigrateToCpswap`. +/// +/// ### Accounts: +/// +/// 0. `[writable, signer]` payer +/// 1. `[]` base_mint +/// 2. `[]` quote_mint +/// 3. `[]` platform_config +/// 4. `[optional]` cpswap_program (default to `CPMMoo8L3F4NbTegBCKVNunggL7H1ZpdTHKxQB5qKP1C`) +/// 5. `[writable]` cpswap_pool +/// 6. `[]` cpswap_authority +/// 7. `[writable]` cpswap_lp_mint +/// 8. `[writable]` cpswap_base_vault +/// 9. `[writable]` cpswap_quote_vault +/// 10. `[]` cpswap_config +/// 11. `[writable]` cpswap_create_pool_fee +/// 12. `[writable]` cpswap_observation +/// 13. `[optional]` lock_program (default to `LockrWmn6K5twhz3y9w1dQERbmgSaRkfnTeTKbpofwE`) +/// 14. `[]` lock_authority +/// 15. `[writable]` lock_lp_vault +/// 16. `[writable]` authority +/// 17. `[writable]` pool_state +/// 18. `[]` global_config +/// 19. `[writable]` base_vault +/// 20. `[writable]` quote_vault +/// 21. `[writable]` pool_lp_token +/// 22. `[optional]` base_token_program (default to `TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA`) +/// 23. `[optional]` quote_token_program (default to `TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA`) +/// 24. `[optional]` associated_token_program (default to `ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL`) +/// 25. `[optional]` system_program (default to `11111111111111111111111111111111`) +/// 26. `[optional]` rent_program (default to `SysvarRent111111111111111111111111111111111`) +/// 27. `[optional]` metadata_program (default to `metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s`) +#[derive(Clone, Debug, Default)] +pub struct MigrateToCpswapBuilder { + payer: Option, + base_mint: Option, + quote_mint: Option, + platform_config: Option, + cpswap_program: Option, + cpswap_pool: Option, + cpswap_authority: Option, + cpswap_lp_mint: Option, + cpswap_base_vault: Option, + cpswap_quote_vault: Option, + cpswap_config: Option, + cpswap_create_pool_fee: Option, + cpswap_observation: Option, + lock_program: Option, + lock_authority: Option, + lock_lp_vault: Option, + authority: Option, + pool_state: Option, + global_config: Option, + base_vault: Option, + quote_vault: Option, + pool_lp_token: Option, + base_token_program: Option, + quote_token_program: Option, + associated_token_program: Option, + system_program: Option, + rent_program: Option, + metadata_program: Option, + __remaining_accounts: Vec, +} + +impl MigrateToCpswapBuilder { + pub fn new() -> Self { + Self::default() + } + /// Only migrate_to_cpswap_wallet can migrate to cpswap pool + /// This signer must match the migrate_to_cpswap_wallet saved in global_config + #[inline(always)] + pub fn payer(&mut self, payer: solana_address::Address) -> &mut Self { + self.payer = Some(payer); + self + } + /// The mint for the base token (token being sold) + #[inline(always)] + pub fn base_mint(&mut self, base_mint: solana_address::Address) -> &mut Self { + self.base_mint = Some(base_mint); + self + } + /// The mint for the quote token (token used to buy) + #[inline(always)] + pub fn quote_mint(&mut self, quote_mint: solana_address::Address) -> &mut Self { + self.quote_mint = Some(quote_mint); + self + } + /// Platform configuration account containing platform-wide settings + /// Used to read platform fee rate + #[inline(always)] + pub fn platform_config(&mut self, platform_config: solana_address::Address) -> &mut Self { + self.platform_config = Some(platform_config); + self + } + /// `[optional account, default to 'CPMMoo8L3F4NbTegBCKVNunggL7H1ZpdTHKxQB5qKP1C']` + #[inline(always)] + pub fn cpswap_program(&mut self, cpswap_program: solana_address::Address) -> &mut Self { + self.cpswap_program = Some(cpswap_program); + self + } + /// PDA account: + /// seeds = [ + /// b"pool", + /// cpswap_config.key().as_ref(), + /// token_0_mint.key().as_ref(), + /// token_1_mint.key().as_ref(), + /// ], + /// seeds::program = cpswap_program, + /// + /// Or random account: must be signed by cli + #[inline(always)] + pub fn cpswap_pool(&mut self, cpswap_pool: solana_address::Address) -> &mut Self { + self.cpswap_pool = Some(cpswap_pool); + self + } + #[inline(always)] + pub fn cpswap_authority(&mut self, cpswap_authority: solana_address::Address) -> &mut Self { + self.cpswap_authority = Some(cpswap_authority); + self + } + #[inline(always)] + pub fn cpswap_lp_mint(&mut self, cpswap_lp_mint: solana_address::Address) -> &mut Self { + self.cpswap_lp_mint = Some(cpswap_lp_mint); + self + } + #[inline(always)] + pub fn cpswap_base_vault(&mut self, cpswap_base_vault: solana_address::Address) -> &mut Self { + self.cpswap_base_vault = Some(cpswap_base_vault); + self + } + #[inline(always)] + pub fn cpswap_quote_vault(&mut self, cpswap_quote_vault: solana_address::Address) -> &mut Self { + self.cpswap_quote_vault = Some(cpswap_quote_vault); + self + } + #[inline(always)] + pub fn cpswap_config(&mut self, cpswap_config: solana_address::Address) -> &mut Self { + self.cpswap_config = Some(cpswap_config); + self + } + #[inline(always)] + pub fn cpswap_create_pool_fee( + &mut self, + cpswap_create_pool_fee: solana_address::Address, + ) -> &mut Self { + self.cpswap_create_pool_fee = Some(cpswap_create_pool_fee); + self + } + #[inline(always)] + pub fn cpswap_observation(&mut self, cpswap_observation: solana_address::Address) -> &mut Self { + self.cpswap_observation = Some(cpswap_observation); + self + } + /// `[optional account, default to 'LockrWmn6K5twhz3y9w1dQERbmgSaRkfnTeTKbpofwE']` + #[inline(always)] + pub fn lock_program(&mut self, lock_program: solana_address::Address) -> &mut Self { + self.lock_program = Some(lock_program); + self + } + #[inline(always)] + pub fn lock_authority(&mut self, lock_authority: solana_address::Address) -> &mut Self { + self.lock_authority = Some(lock_authority); + self + } + #[inline(always)] + pub fn lock_lp_vault(&mut self, lock_lp_vault: solana_address::Address) -> &mut Self { + self.lock_lp_vault = Some(lock_lp_vault); + self + } + /// PDA that acts as the authority for pool vault operations + /// Generated using AUTH_SEED + #[inline(always)] + pub fn authority(&mut self, authority: solana_address::Address) -> &mut Self { + self.authority = Some(authority); + self + } + /// Account that stores the pool's state and parameters + /// PDA generated using POOL_SEED and both token mints + #[inline(always)] + pub fn pool_state(&mut self, pool_state: solana_address::Address) -> &mut Self { + self.pool_state = Some(pool_state); + self + } + /// Global config account stores owner + #[inline(always)] + pub fn global_config(&mut self, global_config: solana_address::Address) -> &mut Self { + self.global_config = Some(global_config); + self + } + /// The pool's vault for base tokens + /// Will be fully drained during migration + #[inline(always)] + pub fn base_vault(&mut self, base_vault: solana_address::Address) -> &mut Self { + self.base_vault = Some(base_vault); + self + } + /// The pool's vault for quote tokens + /// Will be fully drained during migration + #[inline(always)] + pub fn quote_vault(&mut self, quote_vault: solana_address::Address) -> &mut Self { + self.quote_vault = Some(quote_vault); + self + } + #[inline(always)] + pub fn pool_lp_token(&mut self, pool_lp_token: solana_address::Address) -> &mut Self { + self.pool_lp_token = Some(pool_lp_token); + self + } + /// `[optional account, default to 'TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA']` + /// SPL Token program for the base token + /// Must be the standard Token program + #[inline(always)] + pub fn base_token_program(&mut self, base_token_program: solana_address::Address) -> &mut Self { + self.base_token_program = Some(base_token_program); + self + } + /// `[optional account, default to 'TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA']` + /// SPL Token program for the quote token + #[inline(always)] + pub fn quote_token_program( + &mut self, + quote_token_program: solana_address::Address, + ) -> &mut Self { + self.quote_token_program = Some(quote_token_program); + self + } + /// `[optional account, default to 'ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL']` + /// Program to create an ATA for receiving fee NFT + #[inline(always)] + pub fn associated_token_program( + &mut self, + associated_token_program: solana_address::Address, + ) -> &mut Self { + self.associated_token_program = Some(associated_token_program); + self + } + /// `[optional account, default to '11111111111111111111111111111111']` + /// Required for account creation + #[inline(always)] + pub fn system_program(&mut self, system_program: solana_address::Address) -> &mut Self { + self.system_program = Some(system_program); + self + } + /// `[optional account, default to 'SysvarRent111111111111111111111111111111111']` + /// Required for rent exempt calculations + #[inline(always)] + pub fn rent_program(&mut self, rent_program: solana_address::Address) -> &mut Self { + self.rent_program = Some(rent_program); + self + } + /// `[optional account, default to 'metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s']` + /// Program to create NFT metadata accunt + #[inline(always)] + pub fn metadata_program(&mut self, metadata_program: solana_address::Address) -> &mut Self { + self.metadata_program = Some(metadata_program); + self + } + /// Add an additional account to the instruction. + #[inline(always)] + pub fn add_remaining_account(&mut self, account: solana_instruction::AccountMeta) -> &mut Self { + self.__remaining_accounts.push(account); + self + } + /// Add additional accounts to the instruction. + #[inline(always)] + pub fn add_remaining_accounts( + &mut self, + accounts: &[solana_instruction::AccountMeta], + ) -> &mut Self { + self.__remaining_accounts.extend_from_slice(accounts); + self + } + #[allow(clippy::clone_on_copy)] + pub fn instruction(&self) -> solana_instruction::Instruction { + let accounts = MigrateToCpswap { + payer: self.payer.expect("payer is not set"), + base_mint: self.base_mint.expect("base_mint is not set"), + quote_mint: self.quote_mint.expect("quote_mint is not set"), + platform_config: self.platform_config.expect("platform_config is not set"), + cpswap_program: self.cpswap_program.unwrap_or(solana_address::address!( + "CPMMoo8L3F4NbTegBCKVNunggL7H1ZpdTHKxQB5qKP1C" + )), + cpswap_pool: self.cpswap_pool.expect("cpswap_pool is not set"), + cpswap_authority: self.cpswap_authority.expect("cpswap_authority is not set"), + cpswap_lp_mint: self.cpswap_lp_mint.expect("cpswap_lp_mint is not set"), + cpswap_base_vault: self + .cpswap_base_vault + .expect("cpswap_base_vault is not set"), + cpswap_quote_vault: self + .cpswap_quote_vault + .expect("cpswap_quote_vault is not set"), + cpswap_config: self.cpswap_config.expect("cpswap_config is not set"), + cpswap_create_pool_fee: self + .cpswap_create_pool_fee + .expect("cpswap_create_pool_fee is not set"), + cpswap_observation: self + .cpswap_observation + .expect("cpswap_observation is not set"), + lock_program: self.lock_program.unwrap_or(solana_address::address!( + "LockrWmn6K5twhz3y9w1dQERbmgSaRkfnTeTKbpofwE" + )), + lock_authority: self.lock_authority.expect("lock_authority is not set"), + lock_lp_vault: self.lock_lp_vault.expect("lock_lp_vault is not set"), + authority: self.authority.expect("authority is not set"), + pool_state: self.pool_state.expect("pool_state is not set"), + global_config: self.global_config.expect("global_config is not set"), + base_vault: self.base_vault.expect("base_vault is not set"), + quote_vault: self.quote_vault.expect("quote_vault is not set"), + pool_lp_token: self.pool_lp_token.expect("pool_lp_token is not set"), + base_token_program: self.base_token_program.unwrap_or(solana_address::address!( + "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA" + )), + quote_token_program: self.quote_token_program.unwrap_or(solana_address::address!( + "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA" + )), + associated_token_program: self.associated_token_program.unwrap_or( + solana_address::address!("ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL"), + ), + system_program: self + .system_program + .unwrap_or(solana_address::address!("11111111111111111111111111111111")), + rent_program: self.rent_program.unwrap_or(solana_address::address!( + "SysvarRent111111111111111111111111111111111" + )), + metadata_program: self.metadata_program.unwrap_or(solana_address::address!( + "metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s" + )), + }; + + accounts.instruction_with_remaining_accounts(&self.__remaining_accounts) + } +} + +/// `migrate_to_cpswap` CPI accounts. +pub struct MigrateToCpswapCpiAccounts<'a, 'b> { + /// Only migrate_to_cpswap_wallet can migrate to cpswap pool + /// This signer must match the migrate_to_cpswap_wallet saved in global_config + pub payer: &'b solana_account_info::AccountInfo<'a>, + /// The mint for the base token (token being sold) + pub base_mint: &'b solana_account_info::AccountInfo<'a>, + /// The mint for the quote token (token used to buy) + pub quote_mint: &'b solana_account_info::AccountInfo<'a>, + /// Platform configuration account containing platform-wide settings + /// Used to read platform fee rate + pub platform_config: &'b solana_account_info::AccountInfo<'a>, + + pub cpswap_program: &'b solana_account_info::AccountInfo<'a>, + /// PDA account: + /// seeds = [ + /// b"pool", + /// cpswap_config.key().as_ref(), + /// token_0_mint.key().as_ref(), + /// token_1_mint.key().as_ref(), + /// ], + /// seeds::program = cpswap_program, + /// + /// Or random account: must be signed by cli + pub cpswap_pool: &'b solana_account_info::AccountInfo<'a>, + + pub cpswap_authority: &'b solana_account_info::AccountInfo<'a>, + + pub cpswap_lp_mint: &'b solana_account_info::AccountInfo<'a>, + + pub cpswap_base_vault: &'b solana_account_info::AccountInfo<'a>, + + pub cpswap_quote_vault: &'b solana_account_info::AccountInfo<'a>, + + pub cpswap_config: &'b solana_account_info::AccountInfo<'a>, + + pub cpswap_create_pool_fee: &'b solana_account_info::AccountInfo<'a>, + + pub cpswap_observation: &'b solana_account_info::AccountInfo<'a>, + + pub lock_program: &'b solana_account_info::AccountInfo<'a>, + + pub lock_authority: &'b solana_account_info::AccountInfo<'a>, + + pub lock_lp_vault: &'b solana_account_info::AccountInfo<'a>, + /// PDA that acts as the authority for pool vault operations + /// Generated using AUTH_SEED + pub authority: &'b solana_account_info::AccountInfo<'a>, + /// Account that stores the pool's state and parameters + /// PDA generated using POOL_SEED and both token mints + pub pool_state: &'b solana_account_info::AccountInfo<'a>, + /// Global config account stores owner + pub global_config: &'b solana_account_info::AccountInfo<'a>, + /// The pool's vault for base tokens + /// Will be fully drained during migration + pub base_vault: &'b solana_account_info::AccountInfo<'a>, + /// The pool's vault for quote tokens + /// Will be fully drained during migration + pub quote_vault: &'b solana_account_info::AccountInfo<'a>, + + pub pool_lp_token: &'b solana_account_info::AccountInfo<'a>, + /// SPL Token program for the base token + /// Must be the standard Token program + pub base_token_program: &'b solana_account_info::AccountInfo<'a>, + /// SPL Token program for the quote token + pub quote_token_program: &'b solana_account_info::AccountInfo<'a>, + /// Program to create an ATA for receiving fee NFT + pub associated_token_program: &'b solana_account_info::AccountInfo<'a>, + /// Required for account creation + pub system_program: &'b solana_account_info::AccountInfo<'a>, + /// Required for rent exempt calculations + pub rent_program: &'b solana_account_info::AccountInfo<'a>, + /// Program to create NFT metadata accunt + pub metadata_program: &'b solana_account_info::AccountInfo<'a>, +} + +/// `migrate_to_cpswap` CPI instruction. +pub struct MigrateToCpswapCpi<'a, 'b> { + /// The program to invoke. + pub __program: &'b solana_account_info::AccountInfo<'a>, + /// Only migrate_to_cpswap_wallet can migrate to cpswap pool + /// This signer must match the migrate_to_cpswap_wallet saved in global_config + pub payer: &'b solana_account_info::AccountInfo<'a>, + /// The mint for the base token (token being sold) + pub base_mint: &'b solana_account_info::AccountInfo<'a>, + /// The mint for the quote token (token used to buy) + pub quote_mint: &'b solana_account_info::AccountInfo<'a>, + /// Platform configuration account containing platform-wide settings + /// Used to read platform fee rate + pub platform_config: &'b solana_account_info::AccountInfo<'a>, + + pub cpswap_program: &'b solana_account_info::AccountInfo<'a>, + /// PDA account: + /// seeds = [ + /// b"pool", + /// cpswap_config.key().as_ref(), + /// token_0_mint.key().as_ref(), + /// token_1_mint.key().as_ref(), + /// ], + /// seeds::program = cpswap_program, + /// + /// Or random account: must be signed by cli + pub cpswap_pool: &'b solana_account_info::AccountInfo<'a>, + + pub cpswap_authority: &'b solana_account_info::AccountInfo<'a>, + + pub cpswap_lp_mint: &'b solana_account_info::AccountInfo<'a>, + + pub cpswap_base_vault: &'b solana_account_info::AccountInfo<'a>, + + pub cpswap_quote_vault: &'b solana_account_info::AccountInfo<'a>, + + pub cpswap_config: &'b solana_account_info::AccountInfo<'a>, + + pub cpswap_create_pool_fee: &'b solana_account_info::AccountInfo<'a>, + + pub cpswap_observation: &'b solana_account_info::AccountInfo<'a>, + + pub lock_program: &'b solana_account_info::AccountInfo<'a>, + + pub lock_authority: &'b solana_account_info::AccountInfo<'a>, + + pub lock_lp_vault: &'b solana_account_info::AccountInfo<'a>, + /// PDA that acts as the authority for pool vault operations + /// Generated using AUTH_SEED + pub authority: &'b solana_account_info::AccountInfo<'a>, + /// Account that stores the pool's state and parameters + /// PDA generated using POOL_SEED and both token mints + pub pool_state: &'b solana_account_info::AccountInfo<'a>, + /// Global config account stores owner + pub global_config: &'b solana_account_info::AccountInfo<'a>, + /// The pool's vault for base tokens + /// Will be fully drained during migration + pub base_vault: &'b solana_account_info::AccountInfo<'a>, + /// The pool's vault for quote tokens + /// Will be fully drained during migration + pub quote_vault: &'b solana_account_info::AccountInfo<'a>, + + pub pool_lp_token: &'b solana_account_info::AccountInfo<'a>, + /// SPL Token program for the base token + /// Must be the standard Token program + pub base_token_program: &'b solana_account_info::AccountInfo<'a>, + /// SPL Token program for the quote token + pub quote_token_program: &'b solana_account_info::AccountInfo<'a>, + /// Program to create an ATA for receiving fee NFT + pub associated_token_program: &'b solana_account_info::AccountInfo<'a>, + /// Required for account creation + pub system_program: &'b solana_account_info::AccountInfo<'a>, + /// Required for rent exempt calculations + pub rent_program: &'b solana_account_info::AccountInfo<'a>, + /// Program to create NFT metadata accunt + pub metadata_program: &'b solana_account_info::AccountInfo<'a>, +} + +impl<'a, 'b> MigrateToCpswapCpi<'a, 'b> { + pub fn new( + program: &'b solana_account_info::AccountInfo<'a>, + accounts: MigrateToCpswapCpiAccounts<'a, 'b>, + ) -> Self { + Self { + __program: program, + payer: accounts.payer, + base_mint: accounts.base_mint, + quote_mint: accounts.quote_mint, + platform_config: accounts.platform_config, + cpswap_program: accounts.cpswap_program, + cpswap_pool: accounts.cpswap_pool, + cpswap_authority: accounts.cpswap_authority, + cpswap_lp_mint: accounts.cpswap_lp_mint, + cpswap_base_vault: accounts.cpswap_base_vault, + cpswap_quote_vault: accounts.cpswap_quote_vault, + cpswap_config: accounts.cpswap_config, + cpswap_create_pool_fee: accounts.cpswap_create_pool_fee, + cpswap_observation: accounts.cpswap_observation, + lock_program: accounts.lock_program, + lock_authority: accounts.lock_authority, + lock_lp_vault: accounts.lock_lp_vault, + authority: accounts.authority, + pool_state: accounts.pool_state, + global_config: accounts.global_config, + base_vault: accounts.base_vault, + quote_vault: accounts.quote_vault, + pool_lp_token: accounts.pool_lp_token, + base_token_program: accounts.base_token_program, + quote_token_program: accounts.quote_token_program, + associated_token_program: accounts.associated_token_program, + system_program: accounts.system_program, + rent_program: accounts.rent_program, + metadata_program: accounts.metadata_program, + } + } + #[inline(always)] + pub fn invoke(&self) -> solana_program_error::ProgramResult { + self.invoke_signed_with_remaining_accounts(&[], &[]) + } + #[inline(always)] + pub fn invoke_with_remaining_accounts( + &self, + remaining_accounts: &[(&'b solana_account_info::AccountInfo<'a>, bool, bool)], + ) -> solana_program_error::ProgramResult { + self.invoke_signed_with_remaining_accounts(&[], remaining_accounts) + } + #[inline(always)] + pub fn invoke_signed(&self, signers_seeds: &[&[&[u8]]]) -> solana_program_error::ProgramResult { + self.invoke_signed_with_remaining_accounts(signers_seeds, &[]) + } + #[allow(clippy::arithmetic_side_effects)] + #[allow(clippy::clone_on_copy)] + #[allow(clippy::vec_init_then_push)] + pub fn invoke_signed_with_remaining_accounts( + &self, + signers_seeds: &[&[&[u8]]], + remaining_accounts: &[(&'b solana_account_info::AccountInfo<'a>, bool, bool)], + ) -> solana_program_error::ProgramResult { + let mut accounts = Vec::with_capacity(28 + remaining_accounts.len()); + accounts.push(solana_instruction::AccountMeta::new(*self.payer.key, true)); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.base_mint.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.quote_mint.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.platform_config.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.cpswap_program.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + *self.cpswap_pool.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.cpswap_authority.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + *self.cpswap_lp_mint.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + *self.cpswap_base_vault.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + *self.cpswap_quote_vault.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.cpswap_config.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + *self.cpswap_create_pool_fee.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + *self.cpswap_observation.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.lock_program.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.lock_authority.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + *self.lock_lp_vault.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + *self.authority.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + *self.pool_state.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.global_config.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + *self.base_vault.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + *self.quote_vault.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + *self.pool_lp_token.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.base_token_program.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.quote_token_program.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.associated_token_program.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.system_program.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.rent_program.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.metadata_program.key, + false, + )); + remaining_accounts.iter().for_each(|remaining_account| { + accounts.push(solana_instruction::AccountMeta { + pubkey: *remaining_account.0.key, + is_signer: remaining_account.1, + is_writable: remaining_account.2, + }) + }); + let data = MigrateToCpswapInstructionData::new().try_to_vec().unwrap(); + + let instruction = solana_instruction::Instruction { + program_id: crate::RAYDIUM_LAUNCHPAD_ID, + accounts, + data, + }; + let mut account_infos = Vec::with_capacity(29 + remaining_accounts.len()); + account_infos.push(self.__program.clone()); + account_infos.push(self.payer.clone()); + account_infos.push(self.base_mint.clone()); + account_infos.push(self.quote_mint.clone()); + account_infos.push(self.platform_config.clone()); + account_infos.push(self.cpswap_program.clone()); + account_infos.push(self.cpswap_pool.clone()); + account_infos.push(self.cpswap_authority.clone()); + account_infos.push(self.cpswap_lp_mint.clone()); + account_infos.push(self.cpswap_base_vault.clone()); + account_infos.push(self.cpswap_quote_vault.clone()); + account_infos.push(self.cpswap_config.clone()); + account_infos.push(self.cpswap_create_pool_fee.clone()); + account_infos.push(self.cpswap_observation.clone()); + account_infos.push(self.lock_program.clone()); + account_infos.push(self.lock_authority.clone()); + account_infos.push(self.lock_lp_vault.clone()); + account_infos.push(self.authority.clone()); + account_infos.push(self.pool_state.clone()); + account_infos.push(self.global_config.clone()); + account_infos.push(self.base_vault.clone()); + account_infos.push(self.quote_vault.clone()); + account_infos.push(self.pool_lp_token.clone()); + account_infos.push(self.base_token_program.clone()); + account_infos.push(self.quote_token_program.clone()); + account_infos.push(self.associated_token_program.clone()); + account_infos.push(self.system_program.clone()); + account_infos.push(self.rent_program.clone()); + account_infos.push(self.metadata_program.clone()); + remaining_accounts + .iter() + .for_each(|remaining_account| account_infos.push(remaining_account.0.clone())); + + if signers_seeds.is_empty() { + solana_cpi::invoke(&instruction, &account_infos) + } else { + solana_cpi::invoke_signed(&instruction, &account_infos, signers_seeds) + } + } +} + +/// Instruction builder for `MigrateToCpswap` via CPI. +/// +/// ### Accounts: +/// +/// 0. `[writable, signer]` payer +/// 1. `[]` base_mint +/// 2. `[]` quote_mint +/// 3. `[]` platform_config +/// 4. `[]` cpswap_program +/// 5. `[writable]` cpswap_pool +/// 6. `[]` cpswap_authority +/// 7. `[writable]` cpswap_lp_mint +/// 8. `[writable]` cpswap_base_vault +/// 9. `[writable]` cpswap_quote_vault +/// 10. `[]` cpswap_config +/// 11. `[writable]` cpswap_create_pool_fee +/// 12. `[writable]` cpswap_observation +/// 13. `[]` lock_program +/// 14. `[]` lock_authority +/// 15. `[writable]` lock_lp_vault +/// 16. `[writable]` authority +/// 17. `[writable]` pool_state +/// 18. `[]` global_config +/// 19. `[writable]` base_vault +/// 20. `[writable]` quote_vault +/// 21. `[writable]` pool_lp_token +/// 22. `[]` base_token_program +/// 23. `[]` quote_token_program +/// 24. `[]` associated_token_program +/// 25. `[]` system_program +/// 26. `[]` rent_program +/// 27. `[]` metadata_program +#[derive(Clone, Debug)] +pub struct MigrateToCpswapCpiBuilder<'a, 'b> { + instruction: Box>, +} + +impl<'a, 'b> MigrateToCpswapCpiBuilder<'a, 'b> { + pub fn new(program: &'b solana_account_info::AccountInfo<'a>) -> Self { + let instruction = Box::new(MigrateToCpswapCpiBuilderInstruction { + __program: program, + payer: None, + base_mint: None, + quote_mint: None, + platform_config: None, + cpswap_program: None, + cpswap_pool: None, + cpswap_authority: None, + cpswap_lp_mint: None, + cpswap_base_vault: None, + cpswap_quote_vault: None, + cpswap_config: None, + cpswap_create_pool_fee: None, + cpswap_observation: None, + lock_program: None, + lock_authority: None, + lock_lp_vault: None, + authority: None, + pool_state: None, + global_config: None, + base_vault: None, + quote_vault: None, + pool_lp_token: None, + base_token_program: None, + quote_token_program: None, + associated_token_program: None, + system_program: None, + rent_program: None, + metadata_program: None, + __remaining_accounts: Vec::new(), + }); + Self { instruction } + } + /// Only migrate_to_cpswap_wallet can migrate to cpswap pool + /// This signer must match the migrate_to_cpswap_wallet saved in global_config + #[inline(always)] + pub fn payer(&mut self, payer: &'b solana_account_info::AccountInfo<'a>) -> &mut Self { + self.instruction.payer = Some(payer); + self + } + /// The mint for the base token (token being sold) + #[inline(always)] + pub fn base_mint(&mut self, base_mint: &'b solana_account_info::AccountInfo<'a>) -> &mut Self { + self.instruction.base_mint = Some(base_mint); + self + } + /// The mint for the quote token (token used to buy) + #[inline(always)] + pub fn quote_mint( + &mut self, + quote_mint: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.quote_mint = Some(quote_mint); + self + } + /// Platform configuration account containing platform-wide settings + /// Used to read platform fee rate + #[inline(always)] + pub fn platform_config( + &mut self, + platform_config: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.platform_config = Some(platform_config); + self + } + #[inline(always)] + pub fn cpswap_program( + &mut self, + cpswap_program: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.cpswap_program = Some(cpswap_program); + self + } + /// PDA account: + /// seeds = [ + /// b"pool", + /// cpswap_config.key().as_ref(), + /// token_0_mint.key().as_ref(), + /// token_1_mint.key().as_ref(), + /// ], + /// seeds::program = cpswap_program, + /// + /// Or random account: must be signed by cli + #[inline(always)] + pub fn cpswap_pool( + &mut self, + cpswap_pool: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.cpswap_pool = Some(cpswap_pool); + self + } + #[inline(always)] + pub fn cpswap_authority( + &mut self, + cpswap_authority: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.cpswap_authority = Some(cpswap_authority); + self + } + #[inline(always)] + pub fn cpswap_lp_mint( + &mut self, + cpswap_lp_mint: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.cpswap_lp_mint = Some(cpswap_lp_mint); + self + } + #[inline(always)] + pub fn cpswap_base_vault( + &mut self, + cpswap_base_vault: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.cpswap_base_vault = Some(cpswap_base_vault); + self + } + #[inline(always)] + pub fn cpswap_quote_vault( + &mut self, + cpswap_quote_vault: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.cpswap_quote_vault = Some(cpswap_quote_vault); + self + } + #[inline(always)] + pub fn cpswap_config( + &mut self, + cpswap_config: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.cpswap_config = Some(cpswap_config); + self + } + #[inline(always)] + pub fn cpswap_create_pool_fee( + &mut self, + cpswap_create_pool_fee: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.cpswap_create_pool_fee = Some(cpswap_create_pool_fee); + self + } + #[inline(always)] + pub fn cpswap_observation( + &mut self, + cpswap_observation: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.cpswap_observation = Some(cpswap_observation); + self + } + #[inline(always)] + pub fn lock_program( + &mut self, + lock_program: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.lock_program = Some(lock_program); + self + } + #[inline(always)] + pub fn lock_authority( + &mut self, + lock_authority: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.lock_authority = Some(lock_authority); + self + } + #[inline(always)] + pub fn lock_lp_vault( + &mut self, + lock_lp_vault: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.lock_lp_vault = Some(lock_lp_vault); + self + } + /// PDA that acts as the authority for pool vault operations + /// Generated using AUTH_SEED + #[inline(always)] + pub fn authority(&mut self, authority: &'b solana_account_info::AccountInfo<'a>) -> &mut Self { + self.instruction.authority = Some(authority); + self + } + /// Account that stores the pool's state and parameters + /// PDA generated using POOL_SEED and both token mints + #[inline(always)] + pub fn pool_state( + &mut self, + pool_state: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.pool_state = Some(pool_state); + self + } + /// Global config account stores owner + #[inline(always)] + pub fn global_config( + &mut self, + global_config: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.global_config = Some(global_config); + self + } + /// The pool's vault for base tokens + /// Will be fully drained during migration + #[inline(always)] + pub fn base_vault( + &mut self, + base_vault: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.base_vault = Some(base_vault); + self + } + /// The pool's vault for quote tokens + /// Will be fully drained during migration + #[inline(always)] + pub fn quote_vault( + &mut self, + quote_vault: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.quote_vault = Some(quote_vault); + self + } + #[inline(always)] + pub fn pool_lp_token( + &mut self, + pool_lp_token: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.pool_lp_token = Some(pool_lp_token); + self + } + /// SPL Token program for the base token + /// Must be the standard Token program + #[inline(always)] + pub fn base_token_program( + &mut self, + base_token_program: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.base_token_program = Some(base_token_program); + self + } + /// SPL Token program for the quote token + #[inline(always)] + pub fn quote_token_program( + &mut self, + quote_token_program: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.quote_token_program = Some(quote_token_program); + self + } + /// Program to create an ATA for receiving fee NFT + #[inline(always)] + pub fn associated_token_program( + &mut self, + associated_token_program: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.associated_token_program = Some(associated_token_program); + self + } + /// Required for account creation + #[inline(always)] + pub fn system_program( + &mut self, + system_program: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.system_program = Some(system_program); + self + } + /// Required for rent exempt calculations + #[inline(always)] + pub fn rent_program( + &mut self, + rent_program: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.rent_program = Some(rent_program); + self + } + /// Program to create NFT metadata accunt + #[inline(always)] + pub fn metadata_program( + &mut self, + metadata_program: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.metadata_program = Some(metadata_program); + self + } + /// Add an additional account to the instruction. + #[inline(always)] + pub fn add_remaining_account( + &mut self, + account: &'b solana_account_info::AccountInfo<'a>, + is_writable: bool, + is_signer: bool, + ) -> &mut Self { + self.instruction + .__remaining_accounts + .push((account, is_writable, is_signer)); + self + } + /// Add additional accounts to the instruction. + /// + /// Each account is represented by a tuple of the `AccountInfo`, a `bool` indicating whether the account is writable or not, + /// and a `bool` indicating whether the account is a signer or not. + #[inline(always)] + pub fn add_remaining_accounts( + &mut self, + accounts: &[(&'b solana_account_info::AccountInfo<'a>, bool, bool)], + ) -> &mut Self { + self.instruction + .__remaining_accounts + .extend_from_slice(accounts); + self + } + #[inline(always)] + pub fn invoke(&self) -> solana_program_error::ProgramResult { + self.invoke_signed(&[]) + } + #[allow(clippy::clone_on_copy)] + #[allow(clippy::vec_init_then_push)] + pub fn invoke_signed(&self, signers_seeds: &[&[&[u8]]]) -> solana_program_error::ProgramResult { + let instruction = MigrateToCpswapCpi { + __program: self.instruction.__program, + + payer: self.instruction.payer.expect("payer is not set"), + + base_mint: self.instruction.base_mint.expect("base_mint is not set"), + + quote_mint: self.instruction.quote_mint.expect("quote_mint is not set"), + + platform_config: self + .instruction + .platform_config + .expect("platform_config is not set"), + + cpswap_program: self + .instruction + .cpswap_program + .expect("cpswap_program is not set"), + + cpswap_pool: self + .instruction + .cpswap_pool + .expect("cpswap_pool is not set"), + + cpswap_authority: self + .instruction + .cpswap_authority + .expect("cpswap_authority is not set"), + + cpswap_lp_mint: self + .instruction + .cpswap_lp_mint + .expect("cpswap_lp_mint is not set"), + + cpswap_base_vault: self + .instruction + .cpswap_base_vault + .expect("cpswap_base_vault is not set"), + + cpswap_quote_vault: self + .instruction + .cpswap_quote_vault + .expect("cpswap_quote_vault is not set"), + + cpswap_config: self + .instruction + .cpswap_config + .expect("cpswap_config is not set"), + + cpswap_create_pool_fee: self + .instruction + .cpswap_create_pool_fee + .expect("cpswap_create_pool_fee is not set"), + + cpswap_observation: self + .instruction + .cpswap_observation + .expect("cpswap_observation is not set"), + + lock_program: self + .instruction + .lock_program + .expect("lock_program is not set"), + + lock_authority: self + .instruction + .lock_authority + .expect("lock_authority is not set"), + + lock_lp_vault: self + .instruction + .lock_lp_vault + .expect("lock_lp_vault is not set"), + + authority: self.instruction.authority.expect("authority is not set"), + + pool_state: self.instruction.pool_state.expect("pool_state is not set"), + + global_config: self + .instruction + .global_config + .expect("global_config is not set"), + + base_vault: self.instruction.base_vault.expect("base_vault is not set"), + + quote_vault: self + .instruction + .quote_vault + .expect("quote_vault is not set"), + + pool_lp_token: self + .instruction + .pool_lp_token + .expect("pool_lp_token is not set"), + + base_token_program: self + .instruction + .base_token_program + .expect("base_token_program is not set"), + + quote_token_program: self + .instruction + .quote_token_program + .expect("quote_token_program is not set"), + + associated_token_program: self + .instruction + .associated_token_program + .expect("associated_token_program is not set"), + + system_program: self + .instruction + .system_program + .expect("system_program is not set"), + + rent_program: self + .instruction + .rent_program + .expect("rent_program is not set"), + + metadata_program: self + .instruction + .metadata_program + .expect("metadata_program is not set"), + }; + instruction.invoke_signed_with_remaining_accounts( + signers_seeds, + &self.instruction.__remaining_accounts, + ) + } +} + +#[derive(Clone, Debug)] +struct MigrateToCpswapCpiBuilderInstruction<'a, 'b> { + __program: &'b solana_account_info::AccountInfo<'a>, + payer: Option<&'b solana_account_info::AccountInfo<'a>>, + base_mint: Option<&'b solana_account_info::AccountInfo<'a>>, + quote_mint: Option<&'b solana_account_info::AccountInfo<'a>>, + platform_config: Option<&'b solana_account_info::AccountInfo<'a>>, + cpswap_program: Option<&'b solana_account_info::AccountInfo<'a>>, + cpswap_pool: Option<&'b solana_account_info::AccountInfo<'a>>, + cpswap_authority: Option<&'b solana_account_info::AccountInfo<'a>>, + cpswap_lp_mint: Option<&'b solana_account_info::AccountInfo<'a>>, + cpswap_base_vault: Option<&'b solana_account_info::AccountInfo<'a>>, + cpswap_quote_vault: Option<&'b solana_account_info::AccountInfo<'a>>, + cpswap_config: Option<&'b solana_account_info::AccountInfo<'a>>, + cpswap_create_pool_fee: Option<&'b solana_account_info::AccountInfo<'a>>, + cpswap_observation: Option<&'b solana_account_info::AccountInfo<'a>>, + lock_program: Option<&'b solana_account_info::AccountInfo<'a>>, + lock_authority: Option<&'b solana_account_info::AccountInfo<'a>>, + lock_lp_vault: Option<&'b solana_account_info::AccountInfo<'a>>, + authority: Option<&'b solana_account_info::AccountInfo<'a>>, + pool_state: Option<&'b solana_account_info::AccountInfo<'a>>, + global_config: Option<&'b solana_account_info::AccountInfo<'a>>, + base_vault: Option<&'b solana_account_info::AccountInfo<'a>>, + quote_vault: Option<&'b solana_account_info::AccountInfo<'a>>, + pool_lp_token: Option<&'b solana_account_info::AccountInfo<'a>>, + base_token_program: Option<&'b solana_account_info::AccountInfo<'a>>, + quote_token_program: Option<&'b solana_account_info::AccountInfo<'a>>, + associated_token_program: Option<&'b solana_account_info::AccountInfo<'a>>, + system_program: Option<&'b solana_account_info::AccountInfo<'a>>, + rent_program: Option<&'b solana_account_info::AccountInfo<'a>>, + metadata_program: Option<&'b solana_account_info::AccountInfo<'a>>, + /// Additional instruction accounts `(AccountInfo, is_writable, is_signer)`. + __remaining_accounts: Vec<(&'b solana_account_info::AccountInfo<'a>, bool, bool)>, +} diff --git a/e2e/raydium-launchpad/src/generated/instructions/mod.rs b/e2e/raydium-launchpad/src/generated/instructions/mod.rs new file mode 100644 index 0000000..b460c40 --- /dev/null +++ b/e2e/raydium-launchpad/src/generated/instructions/mod.rs @@ -0,0 +1,40 @@ +//! This code was AUTOGENERATED using the codama library. +//! Please DO NOT EDIT THIS FILE, instead use visitors +//! to add features, then rerun codama to update it. +//! +//! +//! + +pub(crate) mod r#buy_exact_in; +pub(crate) mod r#buy_exact_out; +pub(crate) mod r#claim_platform_fee; +pub(crate) mod r#claim_vested_token; +pub(crate) mod r#collect_fee; +pub(crate) mod r#collect_migrate_fee; +pub(crate) mod r#create_config; +pub(crate) mod r#create_platform_config; +pub(crate) mod r#create_vesting_account; +pub(crate) mod r#initialize; +pub(crate) mod r#migrate_to_amm; +pub(crate) mod r#migrate_to_cpswap; +pub(crate) mod r#sell_exact_in; +pub(crate) mod r#sell_exact_out; +pub(crate) mod r#update_config; +pub(crate) mod r#update_platform_config; + +pub use self::r#buy_exact_in::*; +pub use self::r#buy_exact_out::*; +pub use self::r#claim_platform_fee::*; +pub use self::r#claim_vested_token::*; +pub use self::r#collect_fee::*; +pub use self::r#collect_migrate_fee::*; +pub use self::r#create_config::*; +pub use self::r#create_platform_config::*; +pub use self::r#create_vesting_account::*; +pub use self::r#initialize::*; +pub use self::r#migrate_to_amm::*; +pub use self::r#migrate_to_cpswap::*; +pub use self::r#sell_exact_in::*; +pub use self::r#sell_exact_out::*; +pub use self::r#update_config::*; +pub use self::r#update_platform_config::*; diff --git a/e2e/raydium-launchpad/src/generated/instructions/sell_exact_in.rs b/e2e/raydium-launchpad/src/generated/instructions/sell_exact_in.rs new file mode 100644 index 0000000..88279ab --- /dev/null +++ b/e2e/raydium-launchpad/src/generated/instructions/sell_exact_in.rs @@ -0,0 +1,980 @@ +//! This code was AUTOGENERATED using the codama library. +//! Please DO NOT EDIT THIS FILE, instead use visitors +//! to add features, then rerun codama to update it. +//! +//! +//! + +use borsh::BorshDeserialize; +use borsh::BorshSerialize; + +pub const SELL_EXACT_IN_DISCRIMINATOR: [u8; 8] = [149, 39, 222, 155, 211, 124, 152, 26]; + +/// Accounts. +#[derive(Debug)] +pub struct SellExactIn { + /// The user performing the swap operation + /// Must sign the transaction and pay for fees + pub payer: solana_address::Address, + /// PDA that acts as the authority for pool vault operations + /// Generated using AUTH_SEED + pub authority: solana_address::Address, + /// Global configuration account containing protocol-wide settings + /// Used to read protocol fee rates and curve type + pub global_config: solana_address::Address, + /// Platform configuration account containing platform-wide settings + /// Used to read platform fee rate + pub platform_config: solana_address::Address, + /// The pool state account where the swap will be performed + /// Contains current pool parameters and balances + pub pool_state: solana_address::Address, + /// The user's token account for base tokens (tokens being bought) + /// Will receive the output tokens after the swap + pub user_base_token: solana_address::Address, + /// The user's token account for quote tokens (tokens being sold) + /// Will be debited for the input amount + pub user_quote_token: solana_address::Address, + /// The pool's vault for base tokens + /// Will be debited to send tokens to the user + pub base_vault: solana_address::Address, + /// The pool's vault for quote tokens + /// Will receive the input tokens from the user + pub quote_vault: solana_address::Address, + /// The mint of the base token + /// Used for transfer fee calculations if applicable + pub base_token_mint: solana_address::Address, + /// The mint of the quote token + pub quote_token_mint: solana_address::Address, + /// SPL Token program for base token transfers + pub base_token_program: solana_address::Address, + /// SPL Token program for quote token transfers + pub quote_token_program: solana_address::Address, + + pub event_authority: solana_address::Address, + + pub program: solana_address::Address, +} + +impl SellExactIn { + pub fn instruction(&self, args: SellExactInInstructionArgs) -> solana_instruction::Instruction { + self.instruction_with_remaining_accounts(args, &[]) + } + #[allow(clippy::arithmetic_side_effects)] + #[allow(clippy::vec_init_then_push)] + pub fn instruction_with_remaining_accounts( + &self, + args: SellExactInInstructionArgs, + remaining_accounts: &[solana_instruction::AccountMeta], + ) -> solana_instruction::Instruction { + let mut accounts = Vec::with_capacity(15 + remaining_accounts.len()); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.payer, true, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.authority, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.global_config, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.platform_config, + false, + )); + accounts.push(solana_instruction::AccountMeta::new(self.pool_state, false)); + accounts.push(solana_instruction::AccountMeta::new( + self.user_base_token, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + self.user_quote_token, + false, + )); + accounts.push(solana_instruction::AccountMeta::new(self.base_vault, false)); + accounts.push(solana_instruction::AccountMeta::new( + self.quote_vault, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.base_token_mint, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.quote_token_mint, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.base_token_program, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.quote_token_program, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.event_authority, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.program, + false, + )); + accounts.extend_from_slice(remaining_accounts); + let mut data = SellExactInInstructionData::new().try_to_vec().unwrap(); + let mut args = args.try_to_vec().unwrap(); + data.append(&mut args); + + solana_instruction::Instruction { + program_id: crate::RAYDIUM_LAUNCHPAD_ID, + accounts, + data, + } + } +} + +#[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] +pub struct SellExactInInstructionData { + discriminator: [u8; 8], +} + +impl SellExactInInstructionData { + pub fn new() -> Self { + Self { + discriminator: [149, 39, 222, 155, 211, 124, 152, 26], + } + } + + pub(crate) fn try_to_vec(&self) -> Result, std::io::Error> { + borsh::to_vec(self) + } +} + +impl Default for SellExactInInstructionData { + fn default() -> Self { + Self::new() + } +} + +#[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] +pub struct SellExactInInstructionArgs { + pub amount_in: u64, + pub minimum_amount_out: u64, + pub share_fee_rate: u64, +} + +impl SellExactInInstructionArgs { + pub(crate) fn try_to_vec(&self) -> Result, std::io::Error> { + borsh::to_vec(self) + } +} + +/// Instruction builder for `SellExactIn`. +/// +/// ### Accounts: +/// +/// 0. `[signer]` payer +/// 1. `[]` authority +/// 2. `[]` global_config +/// 3. `[]` platform_config +/// 4. `[writable]` pool_state +/// 5. `[writable]` user_base_token +/// 6. `[writable]` user_quote_token +/// 7. `[writable]` base_vault +/// 8. `[writable]` quote_vault +/// 9. `[]` base_token_mint +/// 10. `[]` quote_token_mint +/// 11. `[]` base_token_program +/// 12. `[optional]` quote_token_program (default to `TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA`) +/// 13. `[]` event_authority +/// 14. `[]` program +#[derive(Clone, Debug, Default)] +pub struct SellExactInBuilder { + payer: Option, + authority: Option, + global_config: Option, + platform_config: Option, + pool_state: Option, + user_base_token: Option, + user_quote_token: Option, + base_vault: Option, + quote_vault: Option, + base_token_mint: Option, + quote_token_mint: Option, + base_token_program: Option, + quote_token_program: Option, + event_authority: Option, + program: Option, + amount_in: Option, + minimum_amount_out: Option, + share_fee_rate: Option, + __remaining_accounts: Vec, +} + +impl SellExactInBuilder { + pub fn new() -> Self { + Self::default() + } + /// The user performing the swap operation + /// Must sign the transaction and pay for fees + #[inline(always)] + pub fn payer(&mut self, payer: solana_address::Address) -> &mut Self { + self.payer = Some(payer); + self + } + /// PDA that acts as the authority for pool vault operations + /// Generated using AUTH_SEED + #[inline(always)] + pub fn authority(&mut self, authority: solana_address::Address) -> &mut Self { + self.authority = Some(authority); + self + } + /// Global configuration account containing protocol-wide settings + /// Used to read protocol fee rates and curve type + #[inline(always)] + pub fn global_config(&mut self, global_config: solana_address::Address) -> &mut Self { + self.global_config = Some(global_config); + self + } + /// Platform configuration account containing platform-wide settings + /// Used to read platform fee rate + #[inline(always)] + pub fn platform_config(&mut self, platform_config: solana_address::Address) -> &mut Self { + self.platform_config = Some(platform_config); + self + } + /// The pool state account where the swap will be performed + /// Contains current pool parameters and balances + #[inline(always)] + pub fn pool_state(&mut self, pool_state: solana_address::Address) -> &mut Self { + self.pool_state = Some(pool_state); + self + } + /// The user's token account for base tokens (tokens being bought) + /// Will receive the output tokens after the swap + #[inline(always)] + pub fn user_base_token(&mut self, user_base_token: solana_address::Address) -> &mut Self { + self.user_base_token = Some(user_base_token); + self + } + /// The user's token account for quote tokens (tokens being sold) + /// Will be debited for the input amount + #[inline(always)] + pub fn user_quote_token(&mut self, user_quote_token: solana_address::Address) -> &mut Self { + self.user_quote_token = Some(user_quote_token); + self + } + /// The pool's vault for base tokens + /// Will be debited to send tokens to the user + #[inline(always)] + pub fn base_vault(&mut self, base_vault: solana_address::Address) -> &mut Self { + self.base_vault = Some(base_vault); + self + } + /// The pool's vault for quote tokens + /// Will receive the input tokens from the user + #[inline(always)] + pub fn quote_vault(&mut self, quote_vault: solana_address::Address) -> &mut Self { + self.quote_vault = Some(quote_vault); + self + } + /// The mint of the base token + /// Used for transfer fee calculations if applicable + #[inline(always)] + pub fn base_token_mint(&mut self, base_token_mint: solana_address::Address) -> &mut Self { + self.base_token_mint = Some(base_token_mint); + self + } + /// The mint of the quote token + #[inline(always)] + pub fn quote_token_mint(&mut self, quote_token_mint: solana_address::Address) -> &mut Self { + self.quote_token_mint = Some(quote_token_mint); + self + } + /// SPL Token program for base token transfers + #[inline(always)] + pub fn base_token_program(&mut self, base_token_program: solana_address::Address) -> &mut Self { + self.base_token_program = Some(base_token_program); + self + } + /// `[optional account, default to 'TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA']` + /// SPL Token program for quote token transfers + #[inline(always)] + pub fn quote_token_program( + &mut self, + quote_token_program: solana_address::Address, + ) -> &mut Self { + self.quote_token_program = Some(quote_token_program); + self + } + #[inline(always)] + pub fn event_authority(&mut self, event_authority: solana_address::Address) -> &mut Self { + self.event_authority = Some(event_authority); + self + } + #[inline(always)] + pub fn program(&mut self, program: solana_address::Address) -> &mut Self { + self.program = Some(program); + self + } + #[inline(always)] + pub fn amount_in(&mut self, amount_in: u64) -> &mut Self { + self.amount_in = Some(amount_in); + self + } + #[inline(always)] + pub fn minimum_amount_out(&mut self, minimum_amount_out: u64) -> &mut Self { + self.minimum_amount_out = Some(minimum_amount_out); + self + } + #[inline(always)] + pub fn share_fee_rate(&mut self, share_fee_rate: u64) -> &mut Self { + self.share_fee_rate = Some(share_fee_rate); + self + } + /// Add an additional account to the instruction. + #[inline(always)] + pub fn add_remaining_account(&mut self, account: solana_instruction::AccountMeta) -> &mut Self { + self.__remaining_accounts.push(account); + self + } + /// Add additional accounts to the instruction. + #[inline(always)] + pub fn add_remaining_accounts( + &mut self, + accounts: &[solana_instruction::AccountMeta], + ) -> &mut Self { + self.__remaining_accounts.extend_from_slice(accounts); + self + } + #[allow(clippy::clone_on_copy)] + pub fn instruction(&self) -> solana_instruction::Instruction { + let accounts = SellExactIn { + payer: self.payer.expect("payer is not set"), + authority: self.authority.expect("authority is not set"), + global_config: self.global_config.expect("global_config is not set"), + platform_config: self.platform_config.expect("platform_config is not set"), + pool_state: self.pool_state.expect("pool_state is not set"), + user_base_token: self.user_base_token.expect("user_base_token is not set"), + user_quote_token: self.user_quote_token.expect("user_quote_token is not set"), + base_vault: self.base_vault.expect("base_vault is not set"), + quote_vault: self.quote_vault.expect("quote_vault is not set"), + base_token_mint: self.base_token_mint.expect("base_token_mint is not set"), + quote_token_mint: self.quote_token_mint.expect("quote_token_mint is not set"), + base_token_program: self + .base_token_program + .expect("base_token_program is not set"), + quote_token_program: self.quote_token_program.unwrap_or(solana_address::address!( + "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA" + )), + event_authority: self.event_authority.expect("event_authority is not set"), + program: self.program.expect("program is not set"), + }; + let args = SellExactInInstructionArgs { + amount_in: self.amount_in.clone().expect("amount_in is not set"), + minimum_amount_out: self + .minimum_amount_out + .clone() + .expect("minimum_amount_out is not set"), + share_fee_rate: self + .share_fee_rate + .clone() + .expect("share_fee_rate is not set"), + }; + + accounts.instruction_with_remaining_accounts(args, &self.__remaining_accounts) + } +} + +/// `sell_exact_in` CPI accounts. +pub struct SellExactInCpiAccounts<'a, 'b> { + /// The user performing the swap operation + /// Must sign the transaction and pay for fees + pub payer: &'b solana_account_info::AccountInfo<'a>, + /// PDA that acts as the authority for pool vault operations + /// Generated using AUTH_SEED + pub authority: &'b solana_account_info::AccountInfo<'a>, + /// Global configuration account containing protocol-wide settings + /// Used to read protocol fee rates and curve type + pub global_config: &'b solana_account_info::AccountInfo<'a>, + /// Platform configuration account containing platform-wide settings + /// Used to read platform fee rate + pub platform_config: &'b solana_account_info::AccountInfo<'a>, + /// The pool state account where the swap will be performed + /// Contains current pool parameters and balances + pub pool_state: &'b solana_account_info::AccountInfo<'a>, + /// The user's token account for base tokens (tokens being bought) + /// Will receive the output tokens after the swap + pub user_base_token: &'b solana_account_info::AccountInfo<'a>, + /// The user's token account for quote tokens (tokens being sold) + /// Will be debited for the input amount + pub user_quote_token: &'b solana_account_info::AccountInfo<'a>, + /// The pool's vault for base tokens + /// Will be debited to send tokens to the user + pub base_vault: &'b solana_account_info::AccountInfo<'a>, + /// The pool's vault for quote tokens + /// Will receive the input tokens from the user + pub quote_vault: &'b solana_account_info::AccountInfo<'a>, + /// The mint of the base token + /// Used for transfer fee calculations if applicable + pub base_token_mint: &'b solana_account_info::AccountInfo<'a>, + /// The mint of the quote token + pub quote_token_mint: &'b solana_account_info::AccountInfo<'a>, + /// SPL Token program for base token transfers + pub base_token_program: &'b solana_account_info::AccountInfo<'a>, + /// SPL Token program for quote token transfers + pub quote_token_program: &'b solana_account_info::AccountInfo<'a>, + + pub event_authority: &'b solana_account_info::AccountInfo<'a>, + + pub program: &'b solana_account_info::AccountInfo<'a>, +} + +/// `sell_exact_in` CPI instruction. +pub struct SellExactInCpi<'a, 'b> { + /// The program to invoke. + pub __program: &'b solana_account_info::AccountInfo<'a>, + /// The user performing the swap operation + /// Must sign the transaction and pay for fees + pub payer: &'b solana_account_info::AccountInfo<'a>, + /// PDA that acts as the authority for pool vault operations + /// Generated using AUTH_SEED + pub authority: &'b solana_account_info::AccountInfo<'a>, + /// Global configuration account containing protocol-wide settings + /// Used to read protocol fee rates and curve type + pub global_config: &'b solana_account_info::AccountInfo<'a>, + /// Platform configuration account containing platform-wide settings + /// Used to read platform fee rate + pub platform_config: &'b solana_account_info::AccountInfo<'a>, + /// The pool state account where the swap will be performed + /// Contains current pool parameters and balances + pub pool_state: &'b solana_account_info::AccountInfo<'a>, + /// The user's token account for base tokens (tokens being bought) + /// Will receive the output tokens after the swap + pub user_base_token: &'b solana_account_info::AccountInfo<'a>, + /// The user's token account for quote tokens (tokens being sold) + /// Will be debited for the input amount + pub user_quote_token: &'b solana_account_info::AccountInfo<'a>, + /// The pool's vault for base tokens + /// Will be debited to send tokens to the user + pub base_vault: &'b solana_account_info::AccountInfo<'a>, + /// The pool's vault for quote tokens + /// Will receive the input tokens from the user + pub quote_vault: &'b solana_account_info::AccountInfo<'a>, + /// The mint of the base token + /// Used for transfer fee calculations if applicable + pub base_token_mint: &'b solana_account_info::AccountInfo<'a>, + /// The mint of the quote token + pub quote_token_mint: &'b solana_account_info::AccountInfo<'a>, + /// SPL Token program for base token transfers + pub base_token_program: &'b solana_account_info::AccountInfo<'a>, + /// SPL Token program for quote token transfers + pub quote_token_program: &'b solana_account_info::AccountInfo<'a>, + + pub event_authority: &'b solana_account_info::AccountInfo<'a>, + + pub program: &'b solana_account_info::AccountInfo<'a>, + /// The arguments for the instruction. + pub __args: SellExactInInstructionArgs, +} + +impl<'a, 'b> SellExactInCpi<'a, 'b> { + pub fn new( + program: &'b solana_account_info::AccountInfo<'a>, + accounts: SellExactInCpiAccounts<'a, 'b>, + args: SellExactInInstructionArgs, + ) -> Self { + Self { + __program: program, + payer: accounts.payer, + authority: accounts.authority, + global_config: accounts.global_config, + platform_config: accounts.platform_config, + pool_state: accounts.pool_state, + user_base_token: accounts.user_base_token, + user_quote_token: accounts.user_quote_token, + base_vault: accounts.base_vault, + quote_vault: accounts.quote_vault, + base_token_mint: accounts.base_token_mint, + quote_token_mint: accounts.quote_token_mint, + base_token_program: accounts.base_token_program, + quote_token_program: accounts.quote_token_program, + event_authority: accounts.event_authority, + program: accounts.program, + __args: args, + } + } + #[inline(always)] + pub fn invoke(&self) -> solana_program_error::ProgramResult { + self.invoke_signed_with_remaining_accounts(&[], &[]) + } + #[inline(always)] + pub fn invoke_with_remaining_accounts( + &self, + remaining_accounts: &[(&'b solana_account_info::AccountInfo<'a>, bool, bool)], + ) -> solana_program_error::ProgramResult { + self.invoke_signed_with_remaining_accounts(&[], remaining_accounts) + } + #[inline(always)] + pub fn invoke_signed(&self, signers_seeds: &[&[&[u8]]]) -> solana_program_error::ProgramResult { + self.invoke_signed_with_remaining_accounts(signers_seeds, &[]) + } + #[allow(clippy::arithmetic_side_effects)] + #[allow(clippy::clone_on_copy)] + #[allow(clippy::vec_init_then_push)] + pub fn invoke_signed_with_remaining_accounts( + &self, + signers_seeds: &[&[&[u8]]], + remaining_accounts: &[(&'b solana_account_info::AccountInfo<'a>, bool, bool)], + ) -> solana_program_error::ProgramResult { + let mut accounts = Vec::with_capacity(15 + remaining_accounts.len()); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.payer.key, + true, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.authority.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.global_config.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.platform_config.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + *self.pool_state.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + *self.user_base_token.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + *self.user_quote_token.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + *self.base_vault.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + *self.quote_vault.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.base_token_mint.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.quote_token_mint.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.base_token_program.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.quote_token_program.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.event_authority.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.program.key, + false, + )); + remaining_accounts.iter().for_each(|remaining_account| { + accounts.push(solana_instruction::AccountMeta { + pubkey: *remaining_account.0.key, + is_signer: remaining_account.1, + is_writable: remaining_account.2, + }) + }); + let mut data = SellExactInInstructionData::new().try_to_vec().unwrap(); + let mut args = self.__args.try_to_vec().unwrap(); + data.append(&mut args); + + let instruction = solana_instruction::Instruction { + program_id: crate::RAYDIUM_LAUNCHPAD_ID, + accounts, + data, + }; + let mut account_infos = Vec::with_capacity(16 + remaining_accounts.len()); + account_infos.push(self.__program.clone()); + account_infos.push(self.payer.clone()); + account_infos.push(self.authority.clone()); + account_infos.push(self.global_config.clone()); + account_infos.push(self.platform_config.clone()); + account_infos.push(self.pool_state.clone()); + account_infos.push(self.user_base_token.clone()); + account_infos.push(self.user_quote_token.clone()); + account_infos.push(self.base_vault.clone()); + account_infos.push(self.quote_vault.clone()); + account_infos.push(self.base_token_mint.clone()); + account_infos.push(self.quote_token_mint.clone()); + account_infos.push(self.base_token_program.clone()); + account_infos.push(self.quote_token_program.clone()); + account_infos.push(self.event_authority.clone()); + account_infos.push(self.program.clone()); + remaining_accounts + .iter() + .for_each(|remaining_account| account_infos.push(remaining_account.0.clone())); + + if signers_seeds.is_empty() { + solana_cpi::invoke(&instruction, &account_infos) + } else { + solana_cpi::invoke_signed(&instruction, &account_infos, signers_seeds) + } + } +} + +/// Instruction builder for `SellExactIn` via CPI. +/// +/// ### Accounts: +/// +/// 0. `[signer]` payer +/// 1. `[]` authority +/// 2. `[]` global_config +/// 3. `[]` platform_config +/// 4. `[writable]` pool_state +/// 5. `[writable]` user_base_token +/// 6. `[writable]` user_quote_token +/// 7. `[writable]` base_vault +/// 8. `[writable]` quote_vault +/// 9. `[]` base_token_mint +/// 10. `[]` quote_token_mint +/// 11. `[]` base_token_program +/// 12. `[]` quote_token_program +/// 13. `[]` event_authority +/// 14. `[]` program +#[derive(Clone, Debug)] +pub struct SellExactInCpiBuilder<'a, 'b> { + instruction: Box>, +} + +impl<'a, 'b> SellExactInCpiBuilder<'a, 'b> { + pub fn new(program: &'b solana_account_info::AccountInfo<'a>) -> Self { + let instruction = Box::new(SellExactInCpiBuilderInstruction { + __program: program, + payer: None, + authority: None, + global_config: None, + platform_config: None, + pool_state: None, + user_base_token: None, + user_quote_token: None, + base_vault: None, + quote_vault: None, + base_token_mint: None, + quote_token_mint: None, + base_token_program: None, + quote_token_program: None, + event_authority: None, + program: None, + amount_in: None, + minimum_amount_out: None, + share_fee_rate: None, + __remaining_accounts: Vec::new(), + }); + Self { instruction } + } + /// The user performing the swap operation + /// Must sign the transaction and pay for fees + #[inline(always)] + pub fn payer(&mut self, payer: &'b solana_account_info::AccountInfo<'a>) -> &mut Self { + self.instruction.payer = Some(payer); + self + } + /// PDA that acts as the authority for pool vault operations + /// Generated using AUTH_SEED + #[inline(always)] + pub fn authority(&mut self, authority: &'b solana_account_info::AccountInfo<'a>) -> &mut Self { + self.instruction.authority = Some(authority); + self + } + /// Global configuration account containing protocol-wide settings + /// Used to read protocol fee rates and curve type + #[inline(always)] + pub fn global_config( + &mut self, + global_config: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.global_config = Some(global_config); + self + } + /// Platform configuration account containing platform-wide settings + /// Used to read platform fee rate + #[inline(always)] + pub fn platform_config( + &mut self, + platform_config: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.platform_config = Some(platform_config); + self + } + /// The pool state account where the swap will be performed + /// Contains current pool parameters and balances + #[inline(always)] + pub fn pool_state( + &mut self, + pool_state: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.pool_state = Some(pool_state); + self + } + /// The user's token account for base tokens (tokens being bought) + /// Will receive the output tokens after the swap + #[inline(always)] + pub fn user_base_token( + &mut self, + user_base_token: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.user_base_token = Some(user_base_token); + self + } + /// The user's token account for quote tokens (tokens being sold) + /// Will be debited for the input amount + #[inline(always)] + pub fn user_quote_token( + &mut self, + user_quote_token: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.user_quote_token = Some(user_quote_token); + self + } + /// The pool's vault for base tokens + /// Will be debited to send tokens to the user + #[inline(always)] + pub fn base_vault( + &mut self, + base_vault: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.base_vault = Some(base_vault); + self + } + /// The pool's vault for quote tokens + /// Will receive the input tokens from the user + #[inline(always)] + pub fn quote_vault( + &mut self, + quote_vault: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.quote_vault = Some(quote_vault); + self + } + /// The mint of the base token + /// Used for transfer fee calculations if applicable + #[inline(always)] + pub fn base_token_mint( + &mut self, + base_token_mint: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.base_token_mint = Some(base_token_mint); + self + } + /// The mint of the quote token + #[inline(always)] + pub fn quote_token_mint( + &mut self, + quote_token_mint: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.quote_token_mint = Some(quote_token_mint); + self + } + /// SPL Token program for base token transfers + #[inline(always)] + pub fn base_token_program( + &mut self, + base_token_program: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.base_token_program = Some(base_token_program); + self + } + /// SPL Token program for quote token transfers + #[inline(always)] + pub fn quote_token_program( + &mut self, + quote_token_program: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.quote_token_program = Some(quote_token_program); + self + } + #[inline(always)] + pub fn event_authority( + &mut self, + event_authority: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.event_authority = Some(event_authority); + self + } + #[inline(always)] + pub fn program(&mut self, program: &'b solana_account_info::AccountInfo<'a>) -> &mut Self { + self.instruction.program = Some(program); + self + } + #[inline(always)] + pub fn amount_in(&mut self, amount_in: u64) -> &mut Self { + self.instruction.amount_in = Some(amount_in); + self + } + #[inline(always)] + pub fn minimum_amount_out(&mut self, minimum_amount_out: u64) -> &mut Self { + self.instruction.minimum_amount_out = Some(minimum_amount_out); + self + } + #[inline(always)] + pub fn share_fee_rate(&mut self, share_fee_rate: u64) -> &mut Self { + self.instruction.share_fee_rate = Some(share_fee_rate); + self + } + /// Add an additional account to the instruction. + #[inline(always)] + pub fn add_remaining_account( + &mut self, + account: &'b solana_account_info::AccountInfo<'a>, + is_writable: bool, + is_signer: bool, + ) -> &mut Self { + self.instruction + .__remaining_accounts + .push((account, is_writable, is_signer)); + self + } + /// Add additional accounts to the instruction. + /// + /// Each account is represented by a tuple of the `AccountInfo`, a `bool` indicating whether the account is writable or not, + /// and a `bool` indicating whether the account is a signer or not. + #[inline(always)] + pub fn add_remaining_accounts( + &mut self, + accounts: &[(&'b solana_account_info::AccountInfo<'a>, bool, bool)], + ) -> &mut Self { + self.instruction + .__remaining_accounts + .extend_from_slice(accounts); + self + } + #[inline(always)] + pub fn invoke(&self) -> solana_program_error::ProgramResult { + self.invoke_signed(&[]) + } + #[allow(clippy::clone_on_copy)] + #[allow(clippy::vec_init_then_push)] + pub fn invoke_signed(&self, signers_seeds: &[&[&[u8]]]) -> solana_program_error::ProgramResult { + let args = SellExactInInstructionArgs { + amount_in: self + .instruction + .amount_in + .clone() + .expect("amount_in is not set"), + minimum_amount_out: self + .instruction + .minimum_amount_out + .clone() + .expect("minimum_amount_out is not set"), + share_fee_rate: self + .instruction + .share_fee_rate + .clone() + .expect("share_fee_rate is not set"), + }; + let instruction = SellExactInCpi { + __program: self.instruction.__program, + + payer: self.instruction.payer.expect("payer is not set"), + + authority: self.instruction.authority.expect("authority is not set"), + + global_config: self + .instruction + .global_config + .expect("global_config is not set"), + + platform_config: self + .instruction + .platform_config + .expect("platform_config is not set"), + + pool_state: self.instruction.pool_state.expect("pool_state is not set"), + + user_base_token: self + .instruction + .user_base_token + .expect("user_base_token is not set"), + + user_quote_token: self + .instruction + .user_quote_token + .expect("user_quote_token is not set"), + + base_vault: self.instruction.base_vault.expect("base_vault is not set"), + + quote_vault: self + .instruction + .quote_vault + .expect("quote_vault is not set"), + + base_token_mint: self + .instruction + .base_token_mint + .expect("base_token_mint is not set"), + + quote_token_mint: self + .instruction + .quote_token_mint + .expect("quote_token_mint is not set"), + + base_token_program: self + .instruction + .base_token_program + .expect("base_token_program is not set"), + + quote_token_program: self + .instruction + .quote_token_program + .expect("quote_token_program is not set"), + + event_authority: self + .instruction + .event_authority + .expect("event_authority is not set"), + + program: self.instruction.program.expect("program is not set"), + __args: args, + }; + instruction.invoke_signed_with_remaining_accounts( + signers_seeds, + &self.instruction.__remaining_accounts, + ) + } +} + +#[derive(Clone, Debug)] +struct SellExactInCpiBuilderInstruction<'a, 'b> { + __program: &'b solana_account_info::AccountInfo<'a>, + payer: Option<&'b solana_account_info::AccountInfo<'a>>, + authority: Option<&'b solana_account_info::AccountInfo<'a>>, + global_config: Option<&'b solana_account_info::AccountInfo<'a>>, + platform_config: Option<&'b solana_account_info::AccountInfo<'a>>, + pool_state: Option<&'b solana_account_info::AccountInfo<'a>>, + user_base_token: Option<&'b solana_account_info::AccountInfo<'a>>, + user_quote_token: Option<&'b solana_account_info::AccountInfo<'a>>, + base_vault: Option<&'b solana_account_info::AccountInfo<'a>>, + quote_vault: Option<&'b solana_account_info::AccountInfo<'a>>, + base_token_mint: Option<&'b solana_account_info::AccountInfo<'a>>, + quote_token_mint: Option<&'b solana_account_info::AccountInfo<'a>>, + base_token_program: Option<&'b solana_account_info::AccountInfo<'a>>, + quote_token_program: Option<&'b solana_account_info::AccountInfo<'a>>, + event_authority: Option<&'b solana_account_info::AccountInfo<'a>>, + program: Option<&'b solana_account_info::AccountInfo<'a>>, + amount_in: Option, + minimum_amount_out: Option, + share_fee_rate: Option, + /// Additional instruction accounts `(AccountInfo, is_writable, is_signer)`. + __remaining_accounts: Vec<(&'b solana_account_info::AccountInfo<'a>, bool, bool)>, +} diff --git a/e2e/raydium-launchpad/src/generated/instructions/sell_exact_out.rs b/e2e/raydium-launchpad/src/generated/instructions/sell_exact_out.rs new file mode 100644 index 0000000..b54955a --- /dev/null +++ b/e2e/raydium-launchpad/src/generated/instructions/sell_exact_out.rs @@ -0,0 +1,983 @@ +//! This code was AUTOGENERATED using the codama library. +//! Please DO NOT EDIT THIS FILE, instead use visitors +//! to add features, then rerun codama to update it. +//! +//! +//! + +use borsh::BorshDeserialize; +use borsh::BorshSerialize; + +pub const SELL_EXACT_OUT_DISCRIMINATOR: [u8; 8] = [95, 200, 71, 34, 8, 9, 11, 166]; + +/// Accounts. +#[derive(Debug)] +pub struct SellExactOut { + /// The user performing the swap operation + /// Must sign the transaction and pay for fees + pub payer: solana_address::Address, + /// PDA that acts as the authority for pool vault operations + /// Generated using AUTH_SEED + pub authority: solana_address::Address, + /// Global configuration account containing protocol-wide settings + /// Used to read protocol fee rates and curve type + pub global_config: solana_address::Address, + /// Platform configuration account containing platform-wide settings + /// Used to read platform fee rate + pub platform_config: solana_address::Address, + /// The pool state account where the swap will be performed + /// Contains current pool parameters and balances + pub pool_state: solana_address::Address, + /// The user's token account for base tokens (tokens being bought) + /// Will receive the output tokens after the swap + pub user_base_token: solana_address::Address, + /// The user's token account for quote tokens (tokens being sold) + /// Will be debited for the input amount + pub user_quote_token: solana_address::Address, + /// The pool's vault for base tokens + /// Will be debited to send tokens to the user + pub base_vault: solana_address::Address, + /// The pool's vault for quote tokens + /// Will receive the input tokens from the user + pub quote_vault: solana_address::Address, + /// The mint of the base token + /// Used for transfer fee calculations if applicable + pub base_token_mint: solana_address::Address, + /// The mint of the quote token + pub quote_token_mint: solana_address::Address, + /// SPL Token program for base token transfers + pub base_token_program: solana_address::Address, + /// SPL Token program for quote token transfers + pub quote_token_program: solana_address::Address, + + pub event_authority: solana_address::Address, + + pub program: solana_address::Address, +} + +impl SellExactOut { + pub fn instruction( + &self, + args: SellExactOutInstructionArgs, + ) -> solana_instruction::Instruction { + self.instruction_with_remaining_accounts(args, &[]) + } + #[allow(clippy::arithmetic_side_effects)] + #[allow(clippy::vec_init_then_push)] + pub fn instruction_with_remaining_accounts( + &self, + args: SellExactOutInstructionArgs, + remaining_accounts: &[solana_instruction::AccountMeta], + ) -> solana_instruction::Instruction { + let mut accounts = Vec::with_capacity(15 + remaining_accounts.len()); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.payer, true, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.authority, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.global_config, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.platform_config, + false, + )); + accounts.push(solana_instruction::AccountMeta::new(self.pool_state, false)); + accounts.push(solana_instruction::AccountMeta::new( + self.user_base_token, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + self.user_quote_token, + false, + )); + accounts.push(solana_instruction::AccountMeta::new(self.base_vault, false)); + accounts.push(solana_instruction::AccountMeta::new( + self.quote_vault, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.base_token_mint, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.quote_token_mint, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.base_token_program, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.quote_token_program, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.event_authority, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.program, + false, + )); + accounts.extend_from_slice(remaining_accounts); + let mut data = SellExactOutInstructionData::new().try_to_vec().unwrap(); + let mut args = args.try_to_vec().unwrap(); + data.append(&mut args); + + solana_instruction::Instruction { + program_id: crate::RAYDIUM_LAUNCHPAD_ID, + accounts, + data, + } + } +} + +#[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] +pub struct SellExactOutInstructionData { + discriminator: [u8; 8], +} + +impl SellExactOutInstructionData { + pub fn new() -> Self { + Self { + discriminator: [95, 200, 71, 34, 8, 9, 11, 166], + } + } + + pub(crate) fn try_to_vec(&self) -> Result, std::io::Error> { + borsh::to_vec(self) + } +} + +impl Default for SellExactOutInstructionData { + fn default() -> Self { + Self::new() + } +} + +#[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] +pub struct SellExactOutInstructionArgs { + pub amount_out: u64, + pub maximum_amount_in: u64, + pub share_fee_rate: u64, +} + +impl SellExactOutInstructionArgs { + pub(crate) fn try_to_vec(&self) -> Result, std::io::Error> { + borsh::to_vec(self) + } +} + +/// Instruction builder for `SellExactOut`. +/// +/// ### Accounts: +/// +/// 0. `[signer]` payer +/// 1. `[]` authority +/// 2. `[]` global_config +/// 3. `[]` platform_config +/// 4. `[writable]` pool_state +/// 5. `[writable]` user_base_token +/// 6. `[writable]` user_quote_token +/// 7. `[writable]` base_vault +/// 8. `[writable]` quote_vault +/// 9. `[]` base_token_mint +/// 10. `[]` quote_token_mint +/// 11. `[]` base_token_program +/// 12. `[optional]` quote_token_program (default to `TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA`) +/// 13. `[]` event_authority +/// 14. `[]` program +#[derive(Clone, Debug, Default)] +pub struct SellExactOutBuilder { + payer: Option, + authority: Option, + global_config: Option, + platform_config: Option, + pool_state: Option, + user_base_token: Option, + user_quote_token: Option, + base_vault: Option, + quote_vault: Option, + base_token_mint: Option, + quote_token_mint: Option, + base_token_program: Option, + quote_token_program: Option, + event_authority: Option, + program: Option, + amount_out: Option, + maximum_amount_in: Option, + share_fee_rate: Option, + __remaining_accounts: Vec, +} + +impl SellExactOutBuilder { + pub fn new() -> Self { + Self::default() + } + /// The user performing the swap operation + /// Must sign the transaction and pay for fees + #[inline(always)] + pub fn payer(&mut self, payer: solana_address::Address) -> &mut Self { + self.payer = Some(payer); + self + } + /// PDA that acts as the authority for pool vault operations + /// Generated using AUTH_SEED + #[inline(always)] + pub fn authority(&mut self, authority: solana_address::Address) -> &mut Self { + self.authority = Some(authority); + self + } + /// Global configuration account containing protocol-wide settings + /// Used to read protocol fee rates and curve type + #[inline(always)] + pub fn global_config(&mut self, global_config: solana_address::Address) -> &mut Self { + self.global_config = Some(global_config); + self + } + /// Platform configuration account containing platform-wide settings + /// Used to read platform fee rate + #[inline(always)] + pub fn platform_config(&mut self, platform_config: solana_address::Address) -> &mut Self { + self.platform_config = Some(platform_config); + self + } + /// The pool state account where the swap will be performed + /// Contains current pool parameters and balances + #[inline(always)] + pub fn pool_state(&mut self, pool_state: solana_address::Address) -> &mut Self { + self.pool_state = Some(pool_state); + self + } + /// The user's token account for base tokens (tokens being bought) + /// Will receive the output tokens after the swap + #[inline(always)] + pub fn user_base_token(&mut self, user_base_token: solana_address::Address) -> &mut Self { + self.user_base_token = Some(user_base_token); + self + } + /// The user's token account for quote tokens (tokens being sold) + /// Will be debited for the input amount + #[inline(always)] + pub fn user_quote_token(&mut self, user_quote_token: solana_address::Address) -> &mut Self { + self.user_quote_token = Some(user_quote_token); + self + } + /// The pool's vault for base tokens + /// Will be debited to send tokens to the user + #[inline(always)] + pub fn base_vault(&mut self, base_vault: solana_address::Address) -> &mut Self { + self.base_vault = Some(base_vault); + self + } + /// The pool's vault for quote tokens + /// Will receive the input tokens from the user + #[inline(always)] + pub fn quote_vault(&mut self, quote_vault: solana_address::Address) -> &mut Self { + self.quote_vault = Some(quote_vault); + self + } + /// The mint of the base token + /// Used for transfer fee calculations if applicable + #[inline(always)] + pub fn base_token_mint(&mut self, base_token_mint: solana_address::Address) -> &mut Self { + self.base_token_mint = Some(base_token_mint); + self + } + /// The mint of the quote token + #[inline(always)] + pub fn quote_token_mint(&mut self, quote_token_mint: solana_address::Address) -> &mut Self { + self.quote_token_mint = Some(quote_token_mint); + self + } + /// SPL Token program for base token transfers + #[inline(always)] + pub fn base_token_program(&mut self, base_token_program: solana_address::Address) -> &mut Self { + self.base_token_program = Some(base_token_program); + self + } + /// `[optional account, default to 'TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA']` + /// SPL Token program for quote token transfers + #[inline(always)] + pub fn quote_token_program( + &mut self, + quote_token_program: solana_address::Address, + ) -> &mut Self { + self.quote_token_program = Some(quote_token_program); + self + } + #[inline(always)] + pub fn event_authority(&mut self, event_authority: solana_address::Address) -> &mut Self { + self.event_authority = Some(event_authority); + self + } + #[inline(always)] + pub fn program(&mut self, program: solana_address::Address) -> &mut Self { + self.program = Some(program); + self + } + #[inline(always)] + pub fn amount_out(&mut self, amount_out: u64) -> &mut Self { + self.amount_out = Some(amount_out); + self + } + #[inline(always)] + pub fn maximum_amount_in(&mut self, maximum_amount_in: u64) -> &mut Self { + self.maximum_amount_in = Some(maximum_amount_in); + self + } + #[inline(always)] + pub fn share_fee_rate(&mut self, share_fee_rate: u64) -> &mut Self { + self.share_fee_rate = Some(share_fee_rate); + self + } + /// Add an additional account to the instruction. + #[inline(always)] + pub fn add_remaining_account(&mut self, account: solana_instruction::AccountMeta) -> &mut Self { + self.__remaining_accounts.push(account); + self + } + /// Add additional accounts to the instruction. + #[inline(always)] + pub fn add_remaining_accounts( + &mut self, + accounts: &[solana_instruction::AccountMeta], + ) -> &mut Self { + self.__remaining_accounts.extend_from_slice(accounts); + self + } + #[allow(clippy::clone_on_copy)] + pub fn instruction(&self) -> solana_instruction::Instruction { + let accounts = SellExactOut { + payer: self.payer.expect("payer is not set"), + authority: self.authority.expect("authority is not set"), + global_config: self.global_config.expect("global_config is not set"), + platform_config: self.platform_config.expect("platform_config is not set"), + pool_state: self.pool_state.expect("pool_state is not set"), + user_base_token: self.user_base_token.expect("user_base_token is not set"), + user_quote_token: self.user_quote_token.expect("user_quote_token is not set"), + base_vault: self.base_vault.expect("base_vault is not set"), + quote_vault: self.quote_vault.expect("quote_vault is not set"), + base_token_mint: self.base_token_mint.expect("base_token_mint is not set"), + quote_token_mint: self.quote_token_mint.expect("quote_token_mint is not set"), + base_token_program: self + .base_token_program + .expect("base_token_program is not set"), + quote_token_program: self.quote_token_program.unwrap_or(solana_address::address!( + "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA" + )), + event_authority: self.event_authority.expect("event_authority is not set"), + program: self.program.expect("program is not set"), + }; + let args = SellExactOutInstructionArgs { + amount_out: self.amount_out.clone().expect("amount_out is not set"), + maximum_amount_in: self + .maximum_amount_in + .clone() + .expect("maximum_amount_in is not set"), + share_fee_rate: self + .share_fee_rate + .clone() + .expect("share_fee_rate is not set"), + }; + + accounts.instruction_with_remaining_accounts(args, &self.__remaining_accounts) + } +} + +/// `sell_exact_out` CPI accounts. +pub struct SellExactOutCpiAccounts<'a, 'b> { + /// The user performing the swap operation + /// Must sign the transaction and pay for fees + pub payer: &'b solana_account_info::AccountInfo<'a>, + /// PDA that acts as the authority for pool vault operations + /// Generated using AUTH_SEED + pub authority: &'b solana_account_info::AccountInfo<'a>, + /// Global configuration account containing protocol-wide settings + /// Used to read protocol fee rates and curve type + pub global_config: &'b solana_account_info::AccountInfo<'a>, + /// Platform configuration account containing platform-wide settings + /// Used to read platform fee rate + pub platform_config: &'b solana_account_info::AccountInfo<'a>, + /// The pool state account where the swap will be performed + /// Contains current pool parameters and balances + pub pool_state: &'b solana_account_info::AccountInfo<'a>, + /// The user's token account for base tokens (tokens being bought) + /// Will receive the output tokens after the swap + pub user_base_token: &'b solana_account_info::AccountInfo<'a>, + /// The user's token account for quote tokens (tokens being sold) + /// Will be debited for the input amount + pub user_quote_token: &'b solana_account_info::AccountInfo<'a>, + /// The pool's vault for base tokens + /// Will be debited to send tokens to the user + pub base_vault: &'b solana_account_info::AccountInfo<'a>, + /// The pool's vault for quote tokens + /// Will receive the input tokens from the user + pub quote_vault: &'b solana_account_info::AccountInfo<'a>, + /// The mint of the base token + /// Used for transfer fee calculations if applicable + pub base_token_mint: &'b solana_account_info::AccountInfo<'a>, + /// The mint of the quote token + pub quote_token_mint: &'b solana_account_info::AccountInfo<'a>, + /// SPL Token program for base token transfers + pub base_token_program: &'b solana_account_info::AccountInfo<'a>, + /// SPL Token program for quote token transfers + pub quote_token_program: &'b solana_account_info::AccountInfo<'a>, + + pub event_authority: &'b solana_account_info::AccountInfo<'a>, + + pub program: &'b solana_account_info::AccountInfo<'a>, +} + +/// `sell_exact_out` CPI instruction. +pub struct SellExactOutCpi<'a, 'b> { + /// The program to invoke. + pub __program: &'b solana_account_info::AccountInfo<'a>, + /// The user performing the swap operation + /// Must sign the transaction and pay for fees + pub payer: &'b solana_account_info::AccountInfo<'a>, + /// PDA that acts as the authority for pool vault operations + /// Generated using AUTH_SEED + pub authority: &'b solana_account_info::AccountInfo<'a>, + /// Global configuration account containing protocol-wide settings + /// Used to read protocol fee rates and curve type + pub global_config: &'b solana_account_info::AccountInfo<'a>, + /// Platform configuration account containing platform-wide settings + /// Used to read platform fee rate + pub platform_config: &'b solana_account_info::AccountInfo<'a>, + /// The pool state account where the swap will be performed + /// Contains current pool parameters and balances + pub pool_state: &'b solana_account_info::AccountInfo<'a>, + /// The user's token account for base tokens (tokens being bought) + /// Will receive the output tokens after the swap + pub user_base_token: &'b solana_account_info::AccountInfo<'a>, + /// The user's token account for quote tokens (tokens being sold) + /// Will be debited for the input amount + pub user_quote_token: &'b solana_account_info::AccountInfo<'a>, + /// The pool's vault for base tokens + /// Will be debited to send tokens to the user + pub base_vault: &'b solana_account_info::AccountInfo<'a>, + /// The pool's vault for quote tokens + /// Will receive the input tokens from the user + pub quote_vault: &'b solana_account_info::AccountInfo<'a>, + /// The mint of the base token + /// Used for transfer fee calculations if applicable + pub base_token_mint: &'b solana_account_info::AccountInfo<'a>, + /// The mint of the quote token + pub quote_token_mint: &'b solana_account_info::AccountInfo<'a>, + /// SPL Token program for base token transfers + pub base_token_program: &'b solana_account_info::AccountInfo<'a>, + /// SPL Token program for quote token transfers + pub quote_token_program: &'b solana_account_info::AccountInfo<'a>, + + pub event_authority: &'b solana_account_info::AccountInfo<'a>, + + pub program: &'b solana_account_info::AccountInfo<'a>, + /// The arguments for the instruction. + pub __args: SellExactOutInstructionArgs, +} + +impl<'a, 'b> SellExactOutCpi<'a, 'b> { + pub fn new( + program: &'b solana_account_info::AccountInfo<'a>, + accounts: SellExactOutCpiAccounts<'a, 'b>, + args: SellExactOutInstructionArgs, + ) -> Self { + Self { + __program: program, + payer: accounts.payer, + authority: accounts.authority, + global_config: accounts.global_config, + platform_config: accounts.platform_config, + pool_state: accounts.pool_state, + user_base_token: accounts.user_base_token, + user_quote_token: accounts.user_quote_token, + base_vault: accounts.base_vault, + quote_vault: accounts.quote_vault, + base_token_mint: accounts.base_token_mint, + quote_token_mint: accounts.quote_token_mint, + base_token_program: accounts.base_token_program, + quote_token_program: accounts.quote_token_program, + event_authority: accounts.event_authority, + program: accounts.program, + __args: args, + } + } + #[inline(always)] + pub fn invoke(&self) -> solana_program_error::ProgramResult { + self.invoke_signed_with_remaining_accounts(&[], &[]) + } + #[inline(always)] + pub fn invoke_with_remaining_accounts( + &self, + remaining_accounts: &[(&'b solana_account_info::AccountInfo<'a>, bool, bool)], + ) -> solana_program_error::ProgramResult { + self.invoke_signed_with_remaining_accounts(&[], remaining_accounts) + } + #[inline(always)] + pub fn invoke_signed(&self, signers_seeds: &[&[&[u8]]]) -> solana_program_error::ProgramResult { + self.invoke_signed_with_remaining_accounts(signers_seeds, &[]) + } + #[allow(clippy::arithmetic_side_effects)] + #[allow(clippy::clone_on_copy)] + #[allow(clippy::vec_init_then_push)] + pub fn invoke_signed_with_remaining_accounts( + &self, + signers_seeds: &[&[&[u8]]], + remaining_accounts: &[(&'b solana_account_info::AccountInfo<'a>, bool, bool)], + ) -> solana_program_error::ProgramResult { + let mut accounts = Vec::with_capacity(15 + remaining_accounts.len()); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.payer.key, + true, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.authority.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.global_config.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.platform_config.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + *self.pool_state.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + *self.user_base_token.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + *self.user_quote_token.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + *self.base_vault.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + *self.quote_vault.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.base_token_mint.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.quote_token_mint.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.base_token_program.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.quote_token_program.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.event_authority.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.program.key, + false, + )); + remaining_accounts.iter().for_each(|remaining_account| { + accounts.push(solana_instruction::AccountMeta { + pubkey: *remaining_account.0.key, + is_signer: remaining_account.1, + is_writable: remaining_account.2, + }) + }); + let mut data = SellExactOutInstructionData::new().try_to_vec().unwrap(); + let mut args = self.__args.try_to_vec().unwrap(); + data.append(&mut args); + + let instruction = solana_instruction::Instruction { + program_id: crate::RAYDIUM_LAUNCHPAD_ID, + accounts, + data, + }; + let mut account_infos = Vec::with_capacity(16 + remaining_accounts.len()); + account_infos.push(self.__program.clone()); + account_infos.push(self.payer.clone()); + account_infos.push(self.authority.clone()); + account_infos.push(self.global_config.clone()); + account_infos.push(self.platform_config.clone()); + account_infos.push(self.pool_state.clone()); + account_infos.push(self.user_base_token.clone()); + account_infos.push(self.user_quote_token.clone()); + account_infos.push(self.base_vault.clone()); + account_infos.push(self.quote_vault.clone()); + account_infos.push(self.base_token_mint.clone()); + account_infos.push(self.quote_token_mint.clone()); + account_infos.push(self.base_token_program.clone()); + account_infos.push(self.quote_token_program.clone()); + account_infos.push(self.event_authority.clone()); + account_infos.push(self.program.clone()); + remaining_accounts + .iter() + .for_each(|remaining_account| account_infos.push(remaining_account.0.clone())); + + if signers_seeds.is_empty() { + solana_cpi::invoke(&instruction, &account_infos) + } else { + solana_cpi::invoke_signed(&instruction, &account_infos, signers_seeds) + } + } +} + +/// Instruction builder for `SellExactOut` via CPI. +/// +/// ### Accounts: +/// +/// 0. `[signer]` payer +/// 1. `[]` authority +/// 2. `[]` global_config +/// 3. `[]` platform_config +/// 4. `[writable]` pool_state +/// 5. `[writable]` user_base_token +/// 6. `[writable]` user_quote_token +/// 7. `[writable]` base_vault +/// 8. `[writable]` quote_vault +/// 9. `[]` base_token_mint +/// 10. `[]` quote_token_mint +/// 11. `[]` base_token_program +/// 12. `[]` quote_token_program +/// 13. `[]` event_authority +/// 14. `[]` program +#[derive(Clone, Debug)] +pub struct SellExactOutCpiBuilder<'a, 'b> { + instruction: Box>, +} + +impl<'a, 'b> SellExactOutCpiBuilder<'a, 'b> { + pub fn new(program: &'b solana_account_info::AccountInfo<'a>) -> Self { + let instruction = Box::new(SellExactOutCpiBuilderInstruction { + __program: program, + payer: None, + authority: None, + global_config: None, + platform_config: None, + pool_state: None, + user_base_token: None, + user_quote_token: None, + base_vault: None, + quote_vault: None, + base_token_mint: None, + quote_token_mint: None, + base_token_program: None, + quote_token_program: None, + event_authority: None, + program: None, + amount_out: None, + maximum_amount_in: None, + share_fee_rate: None, + __remaining_accounts: Vec::new(), + }); + Self { instruction } + } + /// The user performing the swap operation + /// Must sign the transaction and pay for fees + #[inline(always)] + pub fn payer(&mut self, payer: &'b solana_account_info::AccountInfo<'a>) -> &mut Self { + self.instruction.payer = Some(payer); + self + } + /// PDA that acts as the authority for pool vault operations + /// Generated using AUTH_SEED + #[inline(always)] + pub fn authority(&mut self, authority: &'b solana_account_info::AccountInfo<'a>) -> &mut Self { + self.instruction.authority = Some(authority); + self + } + /// Global configuration account containing protocol-wide settings + /// Used to read protocol fee rates and curve type + #[inline(always)] + pub fn global_config( + &mut self, + global_config: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.global_config = Some(global_config); + self + } + /// Platform configuration account containing platform-wide settings + /// Used to read platform fee rate + #[inline(always)] + pub fn platform_config( + &mut self, + platform_config: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.platform_config = Some(platform_config); + self + } + /// The pool state account where the swap will be performed + /// Contains current pool parameters and balances + #[inline(always)] + pub fn pool_state( + &mut self, + pool_state: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.pool_state = Some(pool_state); + self + } + /// The user's token account for base tokens (tokens being bought) + /// Will receive the output tokens after the swap + #[inline(always)] + pub fn user_base_token( + &mut self, + user_base_token: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.user_base_token = Some(user_base_token); + self + } + /// The user's token account for quote tokens (tokens being sold) + /// Will be debited for the input amount + #[inline(always)] + pub fn user_quote_token( + &mut self, + user_quote_token: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.user_quote_token = Some(user_quote_token); + self + } + /// The pool's vault for base tokens + /// Will be debited to send tokens to the user + #[inline(always)] + pub fn base_vault( + &mut self, + base_vault: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.base_vault = Some(base_vault); + self + } + /// The pool's vault for quote tokens + /// Will receive the input tokens from the user + #[inline(always)] + pub fn quote_vault( + &mut self, + quote_vault: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.quote_vault = Some(quote_vault); + self + } + /// The mint of the base token + /// Used for transfer fee calculations if applicable + #[inline(always)] + pub fn base_token_mint( + &mut self, + base_token_mint: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.base_token_mint = Some(base_token_mint); + self + } + /// The mint of the quote token + #[inline(always)] + pub fn quote_token_mint( + &mut self, + quote_token_mint: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.quote_token_mint = Some(quote_token_mint); + self + } + /// SPL Token program for base token transfers + #[inline(always)] + pub fn base_token_program( + &mut self, + base_token_program: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.base_token_program = Some(base_token_program); + self + } + /// SPL Token program for quote token transfers + #[inline(always)] + pub fn quote_token_program( + &mut self, + quote_token_program: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.quote_token_program = Some(quote_token_program); + self + } + #[inline(always)] + pub fn event_authority( + &mut self, + event_authority: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.event_authority = Some(event_authority); + self + } + #[inline(always)] + pub fn program(&mut self, program: &'b solana_account_info::AccountInfo<'a>) -> &mut Self { + self.instruction.program = Some(program); + self + } + #[inline(always)] + pub fn amount_out(&mut self, amount_out: u64) -> &mut Self { + self.instruction.amount_out = Some(amount_out); + self + } + #[inline(always)] + pub fn maximum_amount_in(&mut self, maximum_amount_in: u64) -> &mut Self { + self.instruction.maximum_amount_in = Some(maximum_amount_in); + self + } + #[inline(always)] + pub fn share_fee_rate(&mut self, share_fee_rate: u64) -> &mut Self { + self.instruction.share_fee_rate = Some(share_fee_rate); + self + } + /// Add an additional account to the instruction. + #[inline(always)] + pub fn add_remaining_account( + &mut self, + account: &'b solana_account_info::AccountInfo<'a>, + is_writable: bool, + is_signer: bool, + ) -> &mut Self { + self.instruction + .__remaining_accounts + .push((account, is_writable, is_signer)); + self + } + /// Add additional accounts to the instruction. + /// + /// Each account is represented by a tuple of the `AccountInfo`, a `bool` indicating whether the account is writable or not, + /// and a `bool` indicating whether the account is a signer or not. + #[inline(always)] + pub fn add_remaining_accounts( + &mut self, + accounts: &[(&'b solana_account_info::AccountInfo<'a>, bool, bool)], + ) -> &mut Self { + self.instruction + .__remaining_accounts + .extend_from_slice(accounts); + self + } + #[inline(always)] + pub fn invoke(&self) -> solana_program_error::ProgramResult { + self.invoke_signed(&[]) + } + #[allow(clippy::clone_on_copy)] + #[allow(clippy::vec_init_then_push)] + pub fn invoke_signed(&self, signers_seeds: &[&[&[u8]]]) -> solana_program_error::ProgramResult { + let args = SellExactOutInstructionArgs { + amount_out: self + .instruction + .amount_out + .clone() + .expect("amount_out is not set"), + maximum_amount_in: self + .instruction + .maximum_amount_in + .clone() + .expect("maximum_amount_in is not set"), + share_fee_rate: self + .instruction + .share_fee_rate + .clone() + .expect("share_fee_rate is not set"), + }; + let instruction = SellExactOutCpi { + __program: self.instruction.__program, + + payer: self.instruction.payer.expect("payer is not set"), + + authority: self.instruction.authority.expect("authority is not set"), + + global_config: self + .instruction + .global_config + .expect("global_config is not set"), + + platform_config: self + .instruction + .platform_config + .expect("platform_config is not set"), + + pool_state: self.instruction.pool_state.expect("pool_state is not set"), + + user_base_token: self + .instruction + .user_base_token + .expect("user_base_token is not set"), + + user_quote_token: self + .instruction + .user_quote_token + .expect("user_quote_token is not set"), + + base_vault: self.instruction.base_vault.expect("base_vault is not set"), + + quote_vault: self + .instruction + .quote_vault + .expect("quote_vault is not set"), + + base_token_mint: self + .instruction + .base_token_mint + .expect("base_token_mint is not set"), + + quote_token_mint: self + .instruction + .quote_token_mint + .expect("quote_token_mint is not set"), + + base_token_program: self + .instruction + .base_token_program + .expect("base_token_program is not set"), + + quote_token_program: self + .instruction + .quote_token_program + .expect("quote_token_program is not set"), + + event_authority: self + .instruction + .event_authority + .expect("event_authority is not set"), + + program: self.instruction.program.expect("program is not set"), + __args: args, + }; + instruction.invoke_signed_with_remaining_accounts( + signers_seeds, + &self.instruction.__remaining_accounts, + ) + } +} + +#[derive(Clone, Debug)] +struct SellExactOutCpiBuilderInstruction<'a, 'b> { + __program: &'b solana_account_info::AccountInfo<'a>, + payer: Option<&'b solana_account_info::AccountInfo<'a>>, + authority: Option<&'b solana_account_info::AccountInfo<'a>>, + global_config: Option<&'b solana_account_info::AccountInfo<'a>>, + platform_config: Option<&'b solana_account_info::AccountInfo<'a>>, + pool_state: Option<&'b solana_account_info::AccountInfo<'a>>, + user_base_token: Option<&'b solana_account_info::AccountInfo<'a>>, + user_quote_token: Option<&'b solana_account_info::AccountInfo<'a>>, + base_vault: Option<&'b solana_account_info::AccountInfo<'a>>, + quote_vault: Option<&'b solana_account_info::AccountInfo<'a>>, + base_token_mint: Option<&'b solana_account_info::AccountInfo<'a>>, + quote_token_mint: Option<&'b solana_account_info::AccountInfo<'a>>, + base_token_program: Option<&'b solana_account_info::AccountInfo<'a>>, + quote_token_program: Option<&'b solana_account_info::AccountInfo<'a>>, + event_authority: Option<&'b solana_account_info::AccountInfo<'a>>, + program: Option<&'b solana_account_info::AccountInfo<'a>>, + amount_out: Option, + maximum_amount_in: Option, + share_fee_rate: Option, + /// Additional instruction accounts `(AccountInfo, is_writable, is_signer)`. + __remaining_accounts: Vec<(&'b solana_account_info::AccountInfo<'a>, bool, bool)>, +} diff --git a/e2e/raydium-launchpad/src/generated/instructions/update_config.rs b/e2e/raydium-launchpad/src/generated/instructions/update_config.rs new file mode 100644 index 0000000..d3d9418 --- /dev/null +++ b/e2e/raydium-launchpad/src/generated/instructions/update_config.rs @@ -0,0 +1,376 @@ +//! This code was AUTOGENERATED using the codama library. +//! Please DO NOT EDIT THIS FILE, instead use visitors +//! to add features, then rerun codama to update it. +//! +//! +//! + +use borsh::BorshDeserialize; +use borsh::BorshSerialize; + +pub const UPDATE_CONFIG_DISCRIMINATOR: [u8; 8] = [29, 158, 252, 191, 10, 83, 219, 99]; + +/// Accounts. +#[derive(Debug)] +pub struct UpdateConfig { + /// The global config owner or admin + pub owner: solana_address::Address, + /// Global config account to be changed + pub global_config: solana_address::Address, +} + +impl UpdateConfig { + pub fn instruction( + &self, + args: UpdateConfigInstructionArgs, + ) -> solana_instruction::Instruction { + self.instruction_with_remaining_accounts(args, &[]) + } + #[allow(clippy::arithmetic_side_effects)] + #[allow(clippy::vec_init_then_push)] + pub fn instruction_with_remaining_accounts( + &self, + args: UpdateConfigInstructionArgs, + remaining_accounts: &[solana_instruction::AccountMeta], + ) -> solana_instruction::Instruction { + let mut accounts = Vec::with_capacity(2 + remaining_accounts.len()); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.owner, true, + )); + accounts.push(solana_instruction::AccountMeta::new( + self.global_config, + false, + )); + accounts.extend_from_slice(remaining_accounts); + let mut data = UpdateConfigInstructionData::new().try_to_vec().unwrap(); + let mut args = args.try_to_vec().unwrap(); + data.append(&mut args); + + solana_instruction::Instruction { + program_id: crate::RAYDIUM_LAUNCHPAD_ID, + accounts, + data, + } + } +} + +#[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] +pub struct UpdateConfigInstructionData { + discriminator: [u8; 8], +} + +impl UpdateConfigInstructionData { + pub fn new() -> Self { + Self { + discriminator: [29, 158, 252, 191, 10, 83, 219, 99], + } + } + + pub(crate) fn try_to_vec(&self) -> Result, std::io::Error> { + borsh::to_vec(self) + } +} + +impl Default for UpdateConfigInstructionData { + fn default() -> Self { + Self::new() + } +} + +#[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] +pub struct UpdateConfigInstructionArgs { + pub param: u8, + pub value: u64, +} + +impl UpdateConfigInstructionArgs { + pub(crate) fn try_to_vec(&self) -> Result, std::io::Error> { + borsh::to_vec(self) + } +} + +/// Instruction builder for `UpdateConfig`. +/// +/// ### Accounts: +/// +/// 0. `[signer, optional]` owner (default to `GThUX1Atko4tqhN2NaiTazWSeFWMuiUvfFnyJyUghFMJ`) +/// 1. `[writable]` global_config +#[derive(Clone, Debug, Default)] +pub struct UpdateConfigBuilder { + owner: Option, + global_config: Option, + param: Option, + value: Option, + __remaining_accounts: Vec, +} + +impl UpdateConfigBuilder { + pub fn new() -> Self { + Self::default() + } + /// `[optional account, default to 'GThUX1Atko4tqhN2NaiTazWSeFWMuiUvfFnyJyUghFMJ']` + /// The global config owner or admin + #[inline(always)] + pub fn owner(&mut self, owner: solana_address::Address) -> &mut Self { + self.owner = Some(owner); + self + } + /// Global config account to be changed + #[inline(always)] + pub fn global_config(&mut self, global_config: solana_address::Address) -> &mut Self { + self.global_config = Some(global_config); + self + } + #[inline(always)] + pub fn param(&mut self, param: u8) -> &mut Self { + self.param = Some(param); + self + } + #[inline(always)] + pub fn value(&mut self, value: u64) -> &mut Self { + self.value = Some(value); + self + } + /// Add an additional account to the instruction. + #[inline(always)] + pub fn add_remaining_account(&mut self, account: solana_instruction::AccountMeta) -> &mut Self { + self.__remaining_accounts.push(account); + self + } + /// Add additional accounts to the instruction. + #[inline(always)] + pub fn add_remaining_accounts( + &mut self, + accounts: &[solana_instruction::AccountMeta], + ) -> &mut Self { + self.__remaining_accounts.extend_from_slice(accounts); + self + } + #[allow(clippy::clone_on_copy)] + pub fn instruction(&self) -> solana_instruction::Instruction { + let accounts = UpdateConfig { + owner: self.owner.unwrap_or(solana_address::address!( + "GThUX1Atko4tqhN2NaiTazWSeFWMuiUvfFnyJyUghFMJ" + )), + global_config: self.global_config.expect("global_config is not set"), + }; + let args = UpdateConfigInstructionArgs { + param: self.param.clone().expect("param is not set"), + value: self.value.clone().expect("value is not set"), + }; + + accounts.instruction_with_remaining_accounts(args, &self.__remaining_accounts) + } +} + +/// `update_config` CPI accounts. +pub struct UpdateConfigCpiAccounts<'a, 'b> { + /// The global config owner or admin + pub owner: &'b solana_account_info::AccountInfo<'a>, + /// Global config account to be changed + pub global_config: &'b solana_account_info::AccountInfo<'a>, +} + +/// `update_config` CPI instruction. +pub struct UpdateConfigCpi<'a, 'b> { + /// The program to invoke. + pub __program: &'b solana_account_info::AccountInfo<'a>, + /// The global config owner or admin + pub owner: &'b solana_account_info::AccountInfo<'a>, + /// Global config account to be changed + pub global_config: &'b solana_account_info::AccountInfo<'a>, + /// The arguments for the instruction. + pub __args: UpdateConfigInstructionArgs, +} + +impl<'a, 'b> UpdateConfigCpi<'a, 'b> { + pub fn new( + program: &'b solana_account_info::AccountInfo<'a>, + accounts: UpdateConfigCpiAccounts<'a, 'b>, + args: UpdateConfigInstructionArgs, + ) -> Self { + Self { + __program: program, + owner: accounts.owner, + global_config: accounts.global_config, + __args: args, + } + } + #[inline(always)] + pub fn invoke(&self) -> solana_program_error::ProgramResult { + self.invoke_signed_with_remaining_accounts(&[], &[]) + } + #[inline(always)] + pub fn invoke_with_remaining_accounts( + &self, + remaining_accounts: &[(&'b solana_account_info::AccountInfo<'a>, bool, bool)], + ) -> solana_program_error::ProgramResult { + self.invoke_signed_with_remaining_accounts(&[], remaining_accounts) + } + #[inline(always)] + pub fn invoke_signed(&self, signers_seeds: &[&[&[u8]]]) -> solana_program_error::ProgramResult { + self.invoke_signed_with_remaining_accounts(signers_seeds, &[]) + } + #[allow(clippy::arithmetic_side_effects)] + #[allow(clippy::clone_on_copy)] + #[allow(clippy::vec_init_then_push)] + pub fn invoke_signed_with_remaining_accounts( + &self, + signers_seeds: &[&[&[u8]]], + remaining_accounts: &[(&'b solana_account_info::AccountInfo<'a>, bool, bool)], + ) -> solana_program_error::ProgramResult { + let mut accounts = Vec::with_capacity(2 + remaining_accounts.len()); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.owner.key, + true, + )); + accounts.push(solana_instruction::AccountMeta::new( + *self.global_config.key, + false, + )); + remaining_accounts.iter().for_each(|remaining_account| { + accounts.push(solana_instruction::AccountMeta { + pubkey: *remaining_account.0.key, + is_signer: remaining_account.1, + is_writable: remaining_account.2, + }) + }); + let mut data = UpdateConfigInstructionData::new().try_to_vec().unwrap(); + let mut args = self.__args.try_to_vec().unwrap(); + data.append(&mut args); + + let instruction = solana_instruction::Instruction { + program_id: crate::RAYDIUM_LAUNCHPAD_ID, + accounts, + data, + }; + let mut account_infos = Vec::with_capacity(3 + remaining_accounts.len()); + account_infos.push(self.__program.clone()); + account_infos.push(self.owner.clone()); + account_infos.push(self.global_config.clone()); + remaining_accounts + .iter() + .for_each(|remaining_account| account_infos.push(remaining_account.0.clone())); + + if signers_seeds.is_empty() { + solana_cpi::invoke(&instruction, &account_infos) + } else { + solana_cpi::invoke_signed(&instruction, &account_infos, signers_seeds) + } + } +} + +/// Instruction builder for `UpdateConfig` via CPI. +/// +/// ### Accounts: +/// +/// 0. `[signer]` owner +/// 1. `[writable]` global_config +#[derive(Clone, Debug)] +pub struct UpdateConfigCpiBuilder<'a, 'b> { + instruction: Box>, +} + +impl<'a, 'b> UpdateConfigCpiBuilder<'a, 'b> { + pub fn new(program: &'b solana_account_info::AccountInfo<'a>) -> Self { + let instruction = Box::new(UpdateConfigCpiBuilderInstruction { + __program: program, + owner: None, + global_config: None, + param: None, + value: None, + __remaining_accounts: Vec::new(), + }); + Self { instruction } + } + /// The global config owner or admin + #[inline(always)] + pub fn owner(&mut self, owner: &'b solana_account_info::AccountInfo<'a>) -> &mut Self { + self.instruction.owner = Some(owner); + self + } + /// Global config account to be changed + #[inline(always)] + pub fn global_config( + &mut self, + global_config: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.global_config = Some(global_config); + self + } + #[inline(always)] + pub fn param(&mut self, param: u8) -> &mut Self { + self.instruction.param = Some(param); + self + } + #[inline(always)] + pub fn value(&mut self, value: u64) -> &mut Self { + self.instruction.value = Some(value); + self + } + /// Add an additional account to the instruction. + #[inline(always)] + pub fn add_remaining_account( + &mut self, + account: &'b solana_account_info::AccountInfo<'a>, + is_writable: bool, + is_signer: bool, + ) -> &mut Self { + self.instruction + .__remaining_accounts + .push((account, is_writable, is_signer)); + self + } + /// Add additional accounts to the instruction. + /// + /// Each account is represented by a tuple of the `AccountInfo`, a `bool` indicating whether the account is writable or not, + /// and a `bool` indicating whether the account is a signer or not. + #[inline(always)] + pub fn add_remaining_accounts( + &mut self, + accounts: &[(&'b solana_account_info::AccountInfo<'a>, bool, bool)], + ) -> &mut Self { + self.instruction + .__remaining_accounts + .extend_from_slice(accounts); + self + } + #[inline(always)] + pub fn invoke(&self) -> solana_program_error::ProgramResult { + self.invoke_signed(&[]) + } + #[allow(clippy::clone_on_copy)] + #[allow(clippy::vec_init_then_push)] + pub fn invoke_signed(&self, signers_seeds: &[&[&[u8]]]) -> solana_program_error::ProgramResult { + let args = UpdateConfigInstructionArgs { + param: self.instruction.param.clone().expect("param is not set"), + value: self.instruction.value.clone().expect("value is not set"), + }; + let instruction = UpdateConfigCpi { + __program: self.instruction.__program, + + owner: self.instruction.owner.expect("owner is not set"), + + global_config: self + .instruction + .global_config + .expect("global_config is not set"), + __args: args, + }; + instruction.invoke_signed_with_remaining_accounts( + signers_seeds, + &self.instruction.__remaining_accounts, + ) + } +} + +#[derive(Clone, Debug)] +struct UpdateConfigCpiBuilderInstruction<'a, 'b> { + __program: &'b solana_account_info::AccountInfo<'a>, + owner: Option<&'b solana_account_info::AccountInfo<'a>>, + global_config: Option<&'b solana_account_info::AccountInfo<'a>>, + param: Option, + value: Option, + /// Additional instruction accounts `(AccountInfo, is_writable, is_signer)`. + __remaining_accounts: Vec<(&'b solana_account_info::AccountInfo<'a>, bool, bool)>, +} diff --git a/e2e/raydium-launchpad/src/generated/instructions/update_platform_config.rs b/e2e/raydium-launchpad/src/generated/instructions/update_platform_config.rs new file mode 100644 index 0000000..e731a40 --- /dev/null +++ b/e2e/raydium-launchpad/src/generated/instructions/update_platform_config.rs @@ -0,0 +1,369 @@ +//! This code was AUTOGENERATED using the codama library. +//! Please DO NOT EDIT THIS FILE, instead use visitors +//! to add features, then rerun codama to update it. +//! +//! +//! + +use crate::generated::types::PlatformConfigParam; +use borsh::BorshDeserialize; +use borsh::BorshSerialize; + +pub const UPDATE_PLATFORM_CONFIG_DISCRIMINATOR: [u8; 8] = [195, 60, 76, 129, 146, 45, 67, 143]; + +/// Accounts. +#[derive(Debug)] +pub struct UpdatePlatformConfig { + /// The account paying for the initialization costs + pub platform_admin: solana_address::Address, + /// Platform config account to be changed + pub platform_config: solana_address::Address, +} + +impl UpdatePlatformConfig { + pub fn instruction( + &self, + args: UpdatePlatformConfigInstructionArgs, + ) -> solana_instruction::Instruction { + self.instruction_with_remaining_accounts(args, &[]) + } + #[allow(clippy::arithmetic_side_effects)] + #[allow(clippy::vec_init_then_push)] + pub fn instruction_with_remaining_accounts( + &self, + args: UpdatePlatformConfigInstructionArgs, + remaining_accounts: &[solana_instruction::AccountMeta], + ) -> solana_instruction::Instruction { + let mut accounts = Vec::with_capacity(2 + remaining_accounts.len()); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.platform_admin, + true, + )); + accounts.push(solana_instruction::AccountMeta::new( + self.platform_config, + false, + )); + accounts.extend_from_slice(remaining_accounts); + let mut data = UpdatePlatformConfigInstructionData::new() + .try_to_vec() + .unwrap(); + let mut args = args.try_to_vec().unwrap(); + data.append(&mut args); + + solana_instruction::Instruction { + program_id: crate::RAYDIUM_LAUNCHPAD_ID, + accounts, + data, + } + } +} + +#[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] +pub struct UpdatePlatformConfigInstructionData { + discriminator: [u8; 8], +} + +impl UpdatePlatformConfigInstructionData { + pub fn new() -> Self { + Self { + discriminator: [195, 60, 76, 129, 146, 45, 67, 143], + } + } + + pub(crate) fn try_to_vec(&self) -> Result, std::io::Error> { + borsh::to_vec(self) + } +} + +impl Default for UpdatePlatformConfigInstructionData { + fn default() -> Self { + Self::new() + } +} + +#[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] +pub struct UpdatePlatformConfigInstructionArgs { + pub param: PlatformConfigParam, +} + +impl UpdatePlatformConfigInstructionArgs { + pub(crate) fn try_to_vec(&self) -> Result, std::io::Error> { + borsh::to_vec(self) + } +} + +/// Instruction builder for `UpdatePlatformConfig`. +/// +/// ### Accounts: +/// +/// 0. `[signer]` platform_admin +/// 1. `[writable]` platform_config +#[derive(Clone, Debug, Default)] +pub struct UpdatePlatformConfigBuilder { + platform_admin: Option, + platform_config: Option, + param: Option, + __remaining_accounts: Vec, +} + +impl UpdatePlatformConfigBuilder { + pub fn new() -> Self { + Self::default() + } + /// The account paying for the initialization costs + #[inline(always)] + pub fn platform_admin(&mut self, platform_admin: solana_address::Address) -> &mut Self { + self.platform_admin = Some(platform_admin); + self + } + /// Platform config account to be changed + #[inline(always)] + pub fn platform_config(&mut self, platform_config: solana_address::Address) -> &mut Self { + self.platform_config = Some(platform_config); + self + } + #[inline(always)] + pub fn param(&mut self, param: PlatformConfigParam) -> &mut Self { + self.param = Some(param); + self + } + /// Add an additional account to the instruction. + #[inline(always)] + pub fn add_remaining_account(&mut self, account: solana_instruction::AccountMeta) -> &mut Self { + self.__remaining_accounts.push(account); + self + } + /// Add additional accounts to the instruction. + #[inline(always)] + pub fn add_remaining_accounts( + &mut self, + accounts: &[solana_instruction::AccountMeta], + ) -> &mut Self { + self.__remaining_accounts.extend_from_slice(accounts); + self + } + #[allow(clippy::clone_on_copy)] + pub fn instruction(&self) -> solana_instruction::Instruction { + let accounts = UpdatePlatformConfig { + platform_admin: self.platform_admin.expect("platform_admin is not set"), + platform_config: self.platform_config.expect("platform_config is not set"), + }; + let args = UpdatePlatformConfigInstructionArgs { + param: self.param.clone().expect("param is not set"), + }; + + accounts.instruction_with_remaining_accounts(args, &self.__remaining_accounts) + } +} + +/// `update_platform_config` CPI accounts. +pub struct UpdatePlatformConfigCpiAccounts<'a, 'b> { + /// The account paying for the initialization costs + pub platform_admin: &'b solana_account_info::AccountInfo<'a>, + /// Platform config account to be changed + pub platform_config: &'b solana_account_info::AccountInfo<'a>, +} + +/// `update_platform_config` CPI instruction. +pub struct UpdatePlatformConfigCpi<'a, 'b> { + /// The program to invoke. + pub __program: &'b solana_account_info::AccountInfo<'a>, + /// The account paying for the initialization costs + pub platform_admin: &'b solana_account_info::AccountInfo<'a>, + /// Platform config account to be changed + pub platform_config: &'b solana_account_info::AccountInfo<'a>, + /// The arguments for the instruction. + pub __args: UpdatePlatformConfigInstructionArgs, +} + +impl<'a, 'b> UpdatePlatformConfigCpi<'a, 'b> { + pub fn new( + program: &'b solana_account_info::AccountInfo<'a>, + accounts: UpdatePlatformConfigCpiAccounts<'a, 'b>, + args: UpdatePlatformConfigInstructionArgs, + ) -> Self { + Self { + __program: program, + platform_admin: accounts.platform_admin, + platform_config: accounts.platform_config, + __args: args, + } + } + #[inline(always)] + pub fn invoke(&self) -> solana_program_error::ProgramResult { + self.invoke_signed_with_remaining_accounts(&[], &[]) + } + #[inline(always)] + pub fn invoke_with_remaining_accounts( + &self, + remaining_accounts: &[(&'b solana_account_info::AccountInfo<'a>, bool, bool)], + ) -> solana_program_error::ProgramResult { + self.invoke_signed_with_remaining_accounts(&[], remaining_accounts) + } + #[inline(always)] + pub fn invoke_signed(&self, signers_seeds: &[&[&[u8]]]) -> solana_program_error::ProgramResult { + self.invoke_signed_with_remaining_accounts(signers_seeds, &[]) + } + #[allow(clippy::arithmetic_side_effects)] + #[allow(clippy::clone_on_copy)] + #[allow(clippy::vec_init_then_push)] + pub fn invoke_signed_with_remaining_accounts( + &self, + signers_seeds: &[&[&[u8]]], + remaining_accounts: &[(&'b solana_account_info::AccountInfo<'a>, bool, bool)], + ) -> solana_program_error::ProgramResult { + let mut accounts = Vec::with_capacity(2 + remaining_accounts.len()); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.platform_admin.key, + true, + )); + accounts.push(solana_instruction::AccountMeta::new( + *self.platform_config.key, + false, + )); + remaining_accounts.iter().for_each(|remaining_account| { + accounts.push(solana_instruction::AccountMeta { + pubkey: *remaining_account.0.key, + is_signer: remaining_account.1, + is_writable: remaining_account.2, + }) + }); + let mut data = UpdatePlatformConfigInstructionData::new() + .try_to_vec() + .unwrap(); + let mut args = self.__args.try_to_vec().unwrap(); + data.append(&mut args); + + let instruction = solana_instruction::Instruction { + program_id: crate::RAYDIUM_LAUNCHPAD_ID, + accounts, + data, + }; + let mut account_infos = Vec::with_capacity(3 + remaining_accounts.len()); + account_infos.push(self.__program.clone()); + account_infos.push(self.platform_admin.clone()); + account_infos.push(self.platform_config.clone()); + remaining_accounts + .iter() + .for_each(|remaining_account| account_infos.push(remaining_account.0.clone())); + + if signers_seeds.is_empty() { + solana_cpi::invoke(&instruction, &account_infos) + } else { + solana_cpi::invoke_signed(&instruction, &account_infos, signers_seeds) + } + } +} + +/// Instruction builder for `UpdatePlatformConfig` via CPI. +/// +/// ### Accounts: +/// +/// 0. `[signer]` platform_admin +/// 1. `[writable]` platform_config +#[derive(Clone, Debug)] +pub struct UpdatePlatformConfigCpiBuilder<'a, 'b> { + instruction: Box>, +} + +impl<'a, 'b> UpdatePlatformConfigCpiBuilder<'a, 'b> { + pub fn new(program: &'b solana_account_info::AccountInfo<'a>) -> Self { + let instruction = Box::new(UpdatePlatformConfigCpiBuilderInstruction { + __program: program, + platform_admin: None, + platform_config: None, + param: None, + __remaining_accounts: Vec::new(), + }); + Self { instruction } + } + /// The account paying for the initialization costs + #[inline(always)] + pub fn platform_admin( + &mut self, + platform_admin: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.platform_admin = Some(platform_admin); + self + } + /// Platform config account to be changed + #[inline(always)] + pub fn platform_config( + &mut self, + platform_config: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.platform_config = Some(platform_config); + self + } + #[inline(always)] + pub fn param(&mut self, param: PlatformConfigParam) -> &mut Self { + self.instruction.param = Some(param); + self + } + /// Add an additional account to the instruction. + #[inline(always)] + pub fn add_remaining_account( + &mut self, + account: &'b solana_account_info::AccountInfo<'a>, + is_writable: bool, + is_signer: bool, + ) -> &mut Self { + self.instruction + .__remaining_accounts + .push((account, is_writable, is_signer)); + self + } + /// Add additional accounts to the instruction. + /// + /// Each account is represented by a tuple of the `AccountInfo`, a `bool` indicating whether the account is writable or not, + /// and a `bool` indicating whether the account is a signer or not. + #[inline(always)] + pub fn add_remaining_accounts( + &mut self, + accounts: &[(&'b solana_account_info::AccountInfo<'a>, bool, bool)], + ) -> &mut Self { + self.instruction + .__remaining_accounts + .extend_from_slice(accounts); + self + } + #[inline(always)] + pub fn invoke(&self) -> solana_program_error::ProgramResult { + self.invoke_signed(&[]) + } + #[allow(clippy::clone_on_copy)] + #[allow(clippy::vec_init_then_push)] + pub fn invoke_signed(&self, signers_seeds: &[&[&[u8]]]) -> solana_program_error::ProgramResult { + let args = UpdatePlatformConfigInstructionArgs { + param: self.instruction.param.clone().expect("param is not set"), + }; + let instruction = UpdatePlatformConfigCpi { + __program: self.instruction.__program, + + platform_admin: self + .instruction + .platform_admin + .expect("platform_admin is not set"), + + platform_config: self + .instruction + .platform_config + .expect("platform_config is not set"), + __args: args, + }; + instruction.invoke_signed_with_remaining_accounts( + signers_seeds, + &self.instruction.__remaining_accounts, + ) + } +} + +#[derive(Clone, Debug)] +struct UpdatePlatformConfigCpiBuilderInstruction<'a, 'b> { + __program: &'b solana_account_info::AccountInfo<'a>, + platform_admin: Option<&'b solana_account_info::AccountInfo<'a>>, + platform_config: Option<&'b solana_account_info::AccountInfo<'a>>, + param: Option, + /// Additional instruction accounts `(AccountInfo, is_writable, is_signer)`. + __remaining_accounts: Vec<(&'b solana_account_info::AccountInfo<'a>, bool, bool)>, +} diff --git a/e2e/raydium-launchpad/src/generated/mod.rs b/e2e/raydium-launchpad/src/generated/mod.rs new file mode 100644 index 0000000..e0d740a --- /dev/null +++ b/e2e/raydium-launchpad/src/generated/mod.rs @@ -0,0 +1,15 @@ +//! This code was AUTOGENERATED using the codama library. +//! Please DO NOT EDIT THIS FILE, instead use visitors +//! to add features, then rerun codama to update it. +//! +//! +//! + +pub mod accounts; +pub mod errors; +pub mod instructions; +pub mod programs; +pub mod shared; +pub mod types; + +pub(crate) use programs::*; diff --git a/e2e/raydium-launchpad/src/generated/programs.rs b/e2e/raydium-launchpad/src/generated/programs.rs new file mode 100644 index 0000000..d363645 --- /dev/null +++ b/e2e/raydium-launchpad/src/generated/programs.rs @@ -0,0 +1,11 @@ +//! This code was AUTOGENERATED using the codama library. +//! Please DO NOT EDIT THIS FILE, instead use visitors +//! to add features, then rerun codama to update it. +//! +//! +//! + +use solana_address::{address, Address}; + +/// `raydium_launchpad` program ID. +pub const RAYDIUM_LAUNCHPAD_ID: Address = address!("LanMV9sAd7wArD4vJFi2qDdfnVhFxYSUg6eADduJ3uj"); diff --git a/e2e/raydium-launchpad/src/generated/shared.rs b/e2e/raydium-launchpad/src/generated/shared.rs new file mode 100644 index 0000000..42eae7f --- /dev/null +++ b/e2e/raydium-launchpad/src/generated/shared.rs @@ -0,0 +1,21 @@ +//! This code was AUTOGENERATED using the codama library. +//! Please DO NOT EDIT THIS FILE, instead use visitors +//! to add features, then rerun codama to update it. +//! +//! +//! + +#[cfg(feature = "fetch")] +#[derive(Debug, Clone)] +pub struct DecodedAccount { + pub address: solana_address::Address, + pub account: solana_account::Account, + pub data: T, +} + +#[cfg(feature = "fetch")] +#[derive(Debug, Clone)] +pub enum MaybeAccount { + Exists(DecodedAccount), + NotFound(solana_address::Address), +} diff --git a/e2e/raydium-launchpad/src/generated/types/constant_curve.rs b/e2e/raydium-launchpad/src/generated/types/constant_curve.rs new file mode 100644 index 0000000..5681344 --- /dev/null +++ b/e2e/raydium-launchpad/src/generated/types/constant_curve.rs @@ -0,0 +1,17 @@ +//! This code was AUTOGENERATED using the codama library. +//! Please DO NOT EDIT THIS FILE, instead use visitors +//! to add features, then rerun codama to update it. +//! +//! +//! + +use borsh::BorshDeserialize; +use borsh::BorshSerialize; + +#[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] +pub struct ConstantCurve { + pub supply: u64, + pub total_base_sell: u64, + pub total_quote_fund_raising: u64, + pub migrate_type: u8, +} diff --git a/e2e/raydium-launchpad/src/generated/types/curve_params.rs b/e2e/raydium-launchpad/src/generated/types/curve_params.rs new file mode 100644 index 0000000..210309d --- /dev/null +++ b/e2e/raydium-launchpad/src/generated/types/curve_params.rs @@ -0,0 +1,19 @@ +//! This code was AUTOGENERATED using the codama library. +//! Please DO NOT EDIT THIS FILE, instead use visitors +//! to add features, then rerun codama to update it. +//! +//! +//! + +use crate::generated::types::ConstantCurve; +use crate::generated::types::FixedCurve; +use crate::generated::types::LinearCurve; +use borsh::BorshDeserialize; +use borsh::BorshSerialize; + +#[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] +pub enum CurveParams { + Constant { data: ConstantCurve }, + Fixed { data: FixedCurve }, + Linear { data: LinearCurve }, +} diff --git a/e2e/raydium-launchpad/src/generated/types/fixed_curve.rs b/e2e/raydium-launchpad/src/generated/types/fixed_curve.rs new file mode 100644 index 0000000..e29ed07 --- /dev/null +++ b/e2e/raydium-launchpad/src/generated/types/fixed_curve.rs @@ -0,0 +1,16 @@ +//! This code was AUTOGENERATED using the codama library. +//! Please DO NOT EDIT THIS FILE, instead use visitors +//! to add features, then rerun codama to update it. +//! +//! +//! + +use borsh::BorshDeserialize; +use borsh::BorshSerialize; + +#[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] +pub struct FixedCurve { + pub supply: u64, + pub total_quote_fund_raising: u64, + pub migrate_type: u8, +} diff --git a/e2e/raydium-launchpad/src/generated/types/linear_curve.rs b/e2e/raydium-launchpad/src/generated/types/linear_curve.rs new file mode 100644 index 0000000..98367b1 --- /dev/null +++ b/e2e/raydium-launchpad/src/generated/types/linear_curve.rs @@ -0,0 +1,16 @@ +//! This code was AUTOGENERATED using the codama library. +//! Please DO NOT EDIT THIS FILE, instead use visitors +//! to add features, then rerun codama to update it. +//! +//! +//! + +use borsh::BorshDeserialize; +use borsh::BorshSerialize; + +#[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] +pub struct LinearCurve { + pub supply: u64, + pub total_quote_fund_raising: u64, + pub migrate_type: u8, +} diff --git a/e2e/raydium-launchpad/src/generated/types/migrate_nft_info.rs b/e2e/raydium-launchpad/src/generated/types/migrate_nft_info.rs new file mode 100644 index 0000000..75dcc37 --- /dev/null +++ b/e2e/raydium-launchpad/src/generated/types/migrate_nft_info.rs @@ -0,0 +1,23 @@ +//! This code was AUTOGENERATED using the codama library. +//! Please DO NOT EDIT THIS FILE, instead use visitors +//! to add features, then rerun codama to update it. +//! +//! +//! + +use borsh::BorshDeserialize; +use borsh::BorshSerialize; + +/// Represents the parameters for initializing a platform config account(Only support MigrateType::CPSWAP) +/// # Fields +/// * `platform_scale` - Scale of the platform liquidity quantity rights will be converted into NFT +/// * `creator_scale` - Scale of the token creator liquidity quantity rights will be converted into NFT +/// * `burn_scale` - Scale of liquidity directly to burn +/// +/// * platform_scale + creator_scale + burn_scale = RATE_DENOMINATOR_VALUE +#[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] +pub struct MigrateNftInfo { + pub platform_scale: u64, + pub creator_scale: u64, + pub burn_scale: u64, +} diff --git a/e2e/raydium-launchpad/src/generated/types/mint_params.rs b/e2e/raydium-launchpad/src/generated/types/mint_params.rs new file mode 100644 index 0000000..2f209c4 --- /dev/null +++ b/e2e/raydium-launchpad/src/generated/types/mint_params.rs @@ -0,0 +1,23 @@ +//! This code was AUTOGENERATED using the codama library. +//! Please DO NOT EDIT THIS FILE, instead use visitors +//! to add features, then rerun codama to update it. +//! +//! +//! + +use borsh::BorshDeserialize; +use borsh::BorshSerialize; + +/// Represents the parameters for initializing a new token mint +/// # Fields +/// * `decimals` - Number of decimal places for the token +/// * `name` - Name of the token +/// * `symbol` - Symbol/ticker of the token +/// * `uri` - URI pointing to token metadata +#[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] +pub struct MintParams { + pub decimals: u8, + pub name: String, + pub symbol: String, + pub uri: String, +} diff --git a/e2e/raydium-launchpad/src/generated/types/mod.rs b/e2e/raydium-launchpad/src/generated/types/mod.rs new file mode 100644 index 0000000..f72256d --- /dev/null +++ b/e2e/raydium-launchpad/src/generated/types/mod.rs @@ -0,0 +1,30 @@ +//! This code was AUTOGENERATED using the codama library. +//! Please DO NOT EDIT THIS FILE, instead use visitors +//! to add features, then rerun codama to update it. +//! +//! +//! + +pub(crate) mod r#constant_curve; +pub(crate) mod r#curve_params; +pub(crate) mod r#fixed_curve; +pub(crate) mod r#linear_curve; +pub(crate) mod r#migrate_nft_info; +pub(crate) mod r#mint_params; +pub(crate) mod r#platform_config_param; +pub(crate) mod r#pool_status; +pub(crate) mod r#trade_direction; +pub(crate) mod r#vesting_params; +pub(crate) mod r#vesting_schedule; + +pub use self::r#constant_curve::*; +pub use self::r#curve_params::*; +pub use self::r#fixed_curve::*; +pub use self::r#linear_curve::*; +pub use self::r#migrate_nft_info::*; +pub use self::r#mint_params::*; +pub use self::r#platform_config_param::*; +pub use self::r#pool_status::*; +pub use self::r#trade_direction::*; +pub use self::r#vesting_params::*; +pub use self::r#vesting_schedule::*; diff --git a/e2e/raydium-launchpad/src/generated/types/platform_config_param.rs b/e2e/raydium-launchpad/src/generated/types/platform_config_param.rs new file mode 100644 index 0000000..8bc34a1 --- /dev/null +++ b/e2e/raydium-launchpad/src/generated/types/platform_config_param.rs @@ -0,0 +1,22 @@ +//! This code was AUTOGENERATED using the codama library. +//! Please DO NOT EDIT THIS FILE, instead use visitors +//! to add features, then rerun codama to update it. +//! +//! +//! + +use crate::generated::types::MigrateNftInfo; +use borsh::BorshDeserialize; +use borsh::BorshSerialize; +use solana_address::Address; + +#[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] +pub enum PlatformConfigParam { + FeeWallet(Address), + NFTWallet(Address), + MigrateNftInfo(MigrateNftInfo), + FeeRate(u64), + Name(String), + Web(String), + Img(String), +} diff --git a/e2e/raydium-launchpad/src/generated/types/pool_status.rs b/e2e/raydium-launchpad/src/generated/types/pool_status.rs new file mode 100644 index 0000000..c1c93c1 --- /dev/null +++ b/e2e/raydium-launchpad/src/generated/types/pool_status.rs @@ -0,0 +1,32 @@ +//! This code was AUTOGENERATED using the codama library. +//! Please DO NOT EDIT THIS FILE, instead use visitors +//! to add features, then rerun codama to update it. +//! +//! +//! + +use borsh::BorshDeserialize; +use borsh::BorshSerialize; +use num_derive::FromPrimitive; + +/// Represents the different states a pool can be in +/// * Fund - Initial state where pool is accepting funds +/// * Migrate - Pool funding has ended and waiting for migration +/// * Trade - Pool migration is complete and amm trading is enabled +#[derive( + BorshSerialize, + BorshDeserialize, + Clone, + Debug, + Eq, + PartialEq, + Copy, + PartialOrd, + Hash, + FromPrimitive, +)] +pub enum PoolStatus { + Fund, + Migrate, + Trade, +} diff --git a/e2e/raydium-launchpad/src/generated/types/trade_direction.rs b/e2e/raydium-launchpad/src/generated/types/trade_direction.rs new file mode 100644 index 0000000..2de0f0e --- /dev/null +++ b/e2e/raydium-launchpad/src/generated/types/trade_direction.rs @@ -0,0 +1,29 @@ +//! This code was AUTOGENERATED using the codama library. +//! Please DO NOT EDIT THIS FILE, instead use visitors +//! to add features, then rerun codama to update it. +//! +//! +//! + +use borsh::BorshDeserialize; +use borsh::BorshSerialize; +use num_derive::FromPrimitive; + +/// Specifies the direction of a trade in the bonding curve +/// This is important because curves can treat tokens differently through weights or offsets +#[derive( + BorshSerialize, + BorshDeserialize, + Clone, + Debug, + Eq, + PartialEq, + Copy, + PartialOrd, + Hash, + FromPrimitive, +)] +pub enum TradeDirection { + Buy, + Sell, +} diff --git a/e2e/raydium-launchpad/src/generated/types/vesting_params.rs b/e2e/raydium-launchpad/src/generated/types/vesting_params.rs new file mode 100644 index 0000000..7451193 --- /dev/null +++ b/e2e/raydium-launchpad/src/generated/types/vesting_params.rs @@ -0,0 +1,16 @@ +//! This code was AUTOGENERATED using the codama library. +//! Please DO NOT EDIT THIS FILE, instead use visitors +//! to add features, then rerun codama to update it. +//! +//! +//! + +use borsh::BorshDeserialize; +use borsh::BorshSerialize; + +#[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] +pub struct VestingParams { + pub total_locked_amount: u64, + pub cliff_period: u64, + pub unlock_period: u64, +} diff --git a/e2e/raydium-launchpad/src/generated/types/vesting_schedule.rs b/e2e/raydium-launchpad/src/generated/types/vesting_schedule.rs new file mode 100644 index 0000000..d91c454 --- /dev/null +++ b/e2e/raydium-launchpad/src/generated/types/vesting_schedule.rs @@ -0,0 +1,19 @@ +//! This code was AUTOGENERATED using the codama library. +//! Please DO NOT EDIT THIS FILE, instead use visitors +//! to add features, then rerun codama to update it. +//! +//! +//! + +use borsh::BorshDeserialize; +use borsh::BorshSerialize; + +#[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] +pub struct VestingSchedule { + pub total_locked_amount: u64, + pub cliff_period: u64, + pub unlock_period: u64, + pub start_time: u64, + /// Total allocated share amount of the base token, not greater than total_locked_amount + pub allocated_share_amount: u64, +} diff --git a/e2e/raydium-launchpad/src/lib.rs b/e2e/raydium-launchpad/src/lib.rs new file mode 100644 index 0000000..847ba65 --- /dev/null +++ b/e2e/raydium-launchpad/src/lib.rs @@ -0,0 +1,4 @@ +mod generated; + +pub use generated::programs::RAYDIUM_LAUNCHPAD_ID as ID; +pub use generated::*; diff --git a/e2e/test.sh b/e2e/test.sh index 74582ab..0a97d20 100755 --- a/e2e/test.sh +++ b/e2e/test.sh @@ -20,4 +20,5 @@ test_project system test_project memo # test_project meteora # TODO: uncomment after some internal fixes test_anchor_project anchor -test_anchor_project raydium-cpmm \ No newline at end of file +test_anchor_project raydium-cpmm +test_anchor_project raydium-launchpad \ No newline at end of file diff --git a/src/utils/cargoToml.ts b/src/utils/cargoToml.ts index a7da14a..b4683ba 100644 --- a/src/utils/cargoToml.ts +++ b/src/utils/cargoToml.ts @@ -246,8 +246,9 @@ function getUsedImportNames(renderMap: RenderMap, dependencyMap: Recor // and capturing only the crate name (first segment). For instance, // "some_crate::some_module::SomeType" or "::some_crate::SomeType". const PATH_REGEX = /\b(?:::)?([a-z_][a-z0-9_]*)(?:::[a-zA-Z0-9_]+)+/g; + const LINE_COMMENT_REGEX = /\/\/[^\n]*/g; const fromContent = fragments.flatMap(({ content }) => { - return [...content.matchAll(PATH_REGEX)] + return [...content.replace(LINE_COMMENT_REGEX, '').matchAll(PATH_REGEX)] .map(match => match[1]) .filter(crateName => !RUST_CORE_IMPORTS.has(crateName)); }); From aa1a344a7707c0252ee3436ce1768c51415524cd Mon Sep 17 00:00:00 2001 From: ioxde <228087182+ioxde@users.noreply.github.com> Date: Tue, 14 Apr 2026 14:15:45 -0700 Subject: [PATCH 04/24] Add event codegen support --- .changeset/add-event-codegen.md | 5 + .../src/generated/events/lp_change_event.rs | 45 + e2e/raydium-cpmm/src/generated/events/mod.rs | 14 + .../events/raydium_cp_swap_events.rs | 54 ++ .../src/generated/events/swap_event.rs | 42 + e2e/raydium-cpmm/src/generated/mod.rs | 1 + public/templates/eventsMod.njk | 23 + public/templates/eventsPage.njk | 39 + public/templates/programEventsPage.njk | 55 ++ public/templates/rootMod.njk | 3 + src/ImportMap.ts | 1 + src/getRenderMapVisitor.ts | 198 ++++- src/utils/discriminatorConstant.ts | 141 ++- test/eventsPage.test.ts | 802 ++++++++++++++++++ 14 files changed, 1414 insertions(+), 9 deletions(-) create mode 100644 .changeset/add-event-codegen.md create mode 100644 e2e/raydium-cpmm/src/generated/events/lp_change_event.rs create mode 100644 e2e/raydium-cpmm/src/generated/events/mod.rs create mode 100644 e2e/raydium-cpmm/src/generated/events/raydium_cp_swap_events.rs create mode 100644 e2e/raydium-cpmm/src/generated/events/swap_event.rs create mode 100644 public/templates/eventsMod.njk create mode 100644 public/templates/eventsPage.njk create mode 100644 public/templates/programEventsPage.njk create mode 100644 test/eventsPage.test.ts diff --git a/.changeset/add-event-codegen.md b/.changeset/add-event-codegen.md new file mode 100644 index 0000000..e3c7c4b --- /dev/null +++ b/.changeset/add-event-codegen.md @@ -0,0 +1,5 @@ +--- +'@codama/renderers-rust': minor +--- + +Add event codegen support diff --git a/e2e/raydium-cpmm/src/generated/events/lp_change_event.rs b/e2e/raydium-cpmm/src/generated/events/lp_change_event.rs new file mode 100644 index 0000000..15dbf98 --- /dev/null +++ b/e2e/raydium-cpmm/src/generated/events/lp_change_event.rs @@ -0,0 +1,45 @@ +//! This code was AUTOGENERATED using the codama library. +//! Please DO NOT EDIT THIS FILE, instead use visitors +//! to add features, then rerun codama to update it. +//! +//! +//! + +use borsh::BorshDeserialize; +use borsh::BorshSerialize; +use solana_address::Address; + +#[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] +pub struct LpChangeEvent { + pub pool_id: Address, + pub lp_amount_before: u64, + /// pool vault sub trade fees + pub token0_vault_before: u64, + /// pool vault sub trade fees + pub token1_vault_before: u64, + /// calculate result without transfer fee + pub token0_amount: u64, + /// calculate result without transfer fee + pub token1_amount: u64, + pub token0_transfer_fee: u64, + pub token1_transfer_fee: u64, + pub change_type: u8, +} + +pub const LP_CHANGE_EVENT_DISCRIMINATOR: [u8; 8] = [121, 163, 205, 201, 57, 218, 117, 60]; + +impl LpChangeEvent { + #[inline(always)] + pub fn from_bytes(data: &[u8]) -> Result { + if data.get(..LP_CHANGE_EVENT_DISCRIMINATOR.len()) + != Some(&LP_CHANGE_EVENT_DISCRIMINATOR[..]) + { + return Err(std::io::Error::new( + std::io::ErrorKind::InvalidData, + "invalid event discriminator", + )); + } + let mut data = &data[LP_CHANGE_EVENT_DISCRIMINATOR.len()..]; + Self::deserialize(&mut data) + } +} diff --git a/e2e/raydium-cpmm/src/generated/events/mod.rs b/e2e/raydium-cpmm/src/generated/events/mod.rs new file mode 100644 index 0000000..d36c7e6 --- /dev/null +++ b/e2e/raydium-cpmm/src/generated/events/mod.rs @@ -0,0 +1,14 @@ +//! This code was AUTOGENERATED using the codama library. +//! Please DO NOT EDIT THIS FILE, instead use visitors +//! to add features, then rerun codama to update it. +//! +//! +//! + +pub(crate) mod r#lp_change_event; +pub(crate) mod r#raydium_cp_swap_events; +pub(crate) mod r#swap_event; + +pub use self::r#lp_change_event::*; +pub use self::r#raydium_cp_swap_events::*; +pub use self::r#swap_event::*; diff --git a/e2e/raydium-cpmm/src/generated/events/raydium_cp_swap_events.rs b/e2e/raydium-cpmm/src/generated/events/raydium_cp_swap_events.rs new file mode 100644 index 0000000..affde9d --- /dev/null +++ b/e2e/raydium-cpmm/src/generated/events/raydium_cp_swap_events.rs @@ -0,0 +1,54 @@ +//! This code was AUTOGENERATED using the codama library. +//! Please DO NOT EDIT THIS FILE, instead use visitors +//! to add features, then rerun codama to update it. +//! +//! +//! + +use crate::generated::events::LpChangeEvent; +use crate::generated::events::SwapEvent; +use crate::generated::events::LP_CHANGE_EVENT_DISCRIMINATOR; +use crate::generated::events::SWAP_EVENT_DISCRIMINATOR; +use borsh::BorshDeserialize; + +/// Event kinds for the `raydium_cp_swap` program. +#[derive(Clone, Debug, Eq, PartialEq)] +pub enum RaydiumCpSwapEventKind { + LpChangeEvent, + SwapEvent, +} + +/// Identifies a `raydium_cp_swap` event from the provided data. +pub fn identify_raydium_cp_swap_event(data: &[u8]) -> Option { + if data.get(..LP_CHANGE_EVENT_DISCRIMINATOR.len()) == Some(&LP_CHANGE_EVENT_DISCRIMINATOR[..]) { + return Some(RaydiumCpSwapEventKind::LpChangeEvent); + } + if data.get(..SWAP_EVENT_DISCRIMINATOR.len()) == Some(&SWAP_EVENT_DISCRIMINATOR[..]) { + return Some(RaydiumCpSwapEventKind::SwapEvent); + } + None +} + +/// Parsed event variants for the `raydium_cp_swap` program. +#[derive(Clone, Debug, PartialEq)] +pub enum RaydiumCpSwapEvent { + LpChangeEvent(LpChangeEvent), + SwapEvent(SwapEvent), +} + +/// Tries to parse a `raydium_cp_swap` event from the provided data. +pub fn try_parse_raydium_cp_swap_event( + data: &[u8], +) -> Option> { + let event_kind = identify_raydium_cp_swap_event(data)?; + Some(match event_kind { + RaydiumCpSwapEventKind::LpChangeEvent => { + let mut data = &data[LP_CHANGE_EVENT_DISCRIMINATOR.len()..]; + LpChangeEvent::deserialize(&mut data).map(RaydiumCpSwapEvent::LpChangeEvent) + } + RaydiumCpSwapEventKind::SwapEvent => { + let mut data = &data[SWAP_EVENT_DISCRIMINATOR.len()..]; + SwapEvent::deserialize(&mut data).map(RaydiumCpSwapEvent::SwapEvent) + } + }) +} diff --git a/e2e/raydium-cpmm/src/generated/events/swap_event.rs b/e2e/raydium-cpmm/src/generated/events/swap_event.rs new file mode 100644 index 0000000..d3f68cf --- /dev/null +++ b/e2e/raydium-cpmm/src/generated/events/swap_event.rs @@ -0,0 +1,42 @@ +//! This code was AUTOGENERATED using the codama library. +//! Please DO NOT EDIT THIS FILE, instead use visitors +//! to add features, then rerun codama to update it. +//! +//! +//! + +use borsh::BorshDeserialize; +use borsh::BorshSerialize; +use solana_address::Address; + +#[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] +pub struct SwapEvent { + pub pool_id: Address, + /// pool vault sub trade fees + pub input_vault_before: u64, + /// pool vault sub trade fees + pub output_vault_before: u64, + /// calculate result without transfer fee + pub input_amount: u64, + /// calculate result without transfer fee + pub output_amount: u64, + pub input_transfer_fee: u64, + pub output_transfer_fee: u64, + pub base_input: bool, +} + +pub const SWAP_EVENT_DISCRIMINATOR: [u8; 8] = [64, 198, 205, 232, 38, 8, 113, 226]; + +impl SwapEvent { + #[inline(always)] + pub fn from_bytes(data: &[u8]) -> Result { + if data.get(..SWAP_EVENT_DISCRIMINATOR.len()) != Some(&SWAP_EVENT_DISCRIMINATOR[..]) { + return Err(std::io::Error::new( + std::io::ErrorKind::InvalidData, + "invalid event discriminator", + )); + } + let mut data = &data[SWAP_EVENT_DISCRIMINATOR.len()..]; + Self::deserialize(&mut data) + } +} diff --git a/e2e/raydium-cpmm/src/generated/mod.rs b/e2e/raydium-cpmm/src/generated/mod.rs index e0d740a..f3510ac 100644 --- a/e2e/raydium-cpmm/src/generated/mod.rs +++ b/e2e/raydium-cpmm/src/generated/mod.rs @@ -7,6 +7,7 @@ pub mod accounts; pub mod errors; +pub mod events; pub mod instructions; pub mod programs; pub mod shared; diff --git a/public/templates/eventsMod.njk b/public/templates/eventsMod.njk new file mode 100644 index 0000000..db434ef --- /dev/null +++ b/public/templates/eventsMod.njk @@ -0,0 +1,23 @@ +{% extends "layout.njk" %} + +{% block main %} + +{% for event in eventsToExport | sort(false, false, 'name') %} + pub(crate) mod r#{{ event.name | snakeCase }}; +{% endfor %} +{% for program in programsToExport | sort(false, false, 'name') %} +{% if programsWithEventEnum.has(program.name) %} + pub(crate) mod r#{{ program.name | snakeCase }}_events; +{% endif %} +{% endfor %} + +{% for event in eventsToExport | sort(false, false, 'name') %} + pub use self::r#{{ event.name | snakeCase }}::*; +{% endfor %} +{% for program in programsToExport | sort(false, false, 'name') %} +{% if programsWithEventEnum.has(program.name) %} + pub use self::r#{{ program.name | snakeCase }}_events::*; +{% endif %} +{% endfor %} + +{% endblock %} diff --git a/public/templates/eventsPage.njk b/public/templates/eventsPage.njk new file mode 100644 index 0000000..05b176a --- /dev/null +++ b/public/templates/eventsPage.njk @@ -0,0 +1,39 @@ +{% extends "layout.njk" %} +{% import "macros.njk" as macros %} + +{% block main %} + +{{ imports }} + +{{ macros.docblock(event.docs) }} +{{- typeManifest.type }} + +{% for nestedStruct in typeManifest.nestedStructs %} +{{ nestedStruct }} +{% endfor %} + +{{ discriminatorConstants }} + +{% if constantDiscriminators.length > 0 %} +impl {{ event.name | pascalCase }} { + #[inline(always)] + pub fn from_bytes(data: &[u8]) -> Result { +{% for disc in constantDiscriminators %} +{% if disc.offset === 0 %} + if data.get(..{{ disc.name }}.len()) != Some(&{{ disc.name }}[..]) { +{% else %} + if data.get({{ disc.offset }}..{{ disc.offset }} + {{ disc.name }}.len()) != Some(&{{ disc.name }}[..]) { +{% endif %} + return Err(std::io::Error::new( + std::io::ErrorKind::InvalidData, + "invalid event discriminator", + )); + } +{% endfor %} + let mut data = &data[{{ hiddenPrefixSkip }}..]; + Self::deserialize(&mut data) + } +} +{% endif %} + +{% endblock %} diff --git a/public/templates/programEventsPage.njk b/public/templates/programEventsPage.njk new file mode 100644 index 0000000..71a15fa --- /dev/null +++ b/public/templates/programEventsPage.njk @@ -0,0 +1,55 @@ +{% extends "layout.njk" %} + +{% block main %} + +{{ imports }} + +/// Event kinds for the `{{ program.name | snakeCase }}` program. +#[derive(Clone, Debug, Eq, PartialEq)] +pub enum {{ program.name | pascalCase }}EventKind { +{% for event in eventsWithDiscriminators | sort(false, false, 'name') %} + {{ event.name | pascalCase }}, +{% endfor %} +} + +/// Identifies a `{{ program.name | snakeCase }}` event from the provided data. +pub fn identify_{{ program.name | snakeCase }}_event(data: &[u8]) -> Option<{{ program.name | pascalCase }}EventKind> { +{% for event in eventsWithDiscriminators | sort(false, false, 'name') %} + if {{ event.conditions | join(' && ') }} { + return Some({{ program.name | pascalCase }}EventKind::{{ event.name | pascalCase }}); + } +{% endfor %} + None +} + +/// Parsed event variants for the `{{ program.name | snakeCase }}` program. +#[derive(Clone, Debug, PartialEq)] +pub enum {{ program.name | pascalCase }}Event { +{% for event in eventsWithDiscriminators | sort(false, false, 'name') %} + {{ event.name | pascalCase }}({{ event.name | pascalCase }}), +{% endfor %} +} + +/// Tries to parse a `{{ program.name | snakeCase }}` event from the provided data. +pub fn try_parse_{{ program.name | snakeCase }}_event(data: &[u8]) -> Option> { + let event_kind = identify_{{ program.name | snakeCase }}_event(data)?; + Some(match event_kind { +{% for event in eventsWithDiscriminators | sort(false, false, 'name') %} +{% if event.hiddenPrefixSkip != '0' %} + {{ program.name | pascalCase }}EventKind::{{ event.name | pascalCase }} => { + let mut data = &data[{{ event.hiddenPrefixSkip }}..]; + {{ event.name | pascalCase }}::deserialize(&mut data) + .map({{ program.name | pascalCase }}Event::{{ event.name | pascalCase }}) + } +{% else %} + {{ program.name | pascalCase }}EventKind::{{ event.name | pascalCase }} => { + let mut data = data; + {{ event.name | pascalCase }}::deserialize(&mut data) + .map({{ program.name | pascalCase }}Event::{{ event.name | pascalCase }}) + } +{% endif %} +{% endfor %} + }) +} + +{% endblock %} diff --git a/public/templates/rootMod.njk b/public/templates/rootMod.njk index d792bcb..d4c553c 100644 --- a/public/templates/rootMod.njk +++ b/public/templates/rootMod.njk @@ -9,6 +9,9 @@ {% if programsToExport.length > 0 %} pub mod errors; {% endif %} + {% if eventsToExport.length > 0 %} + pub mod events; + {% endif %} {% if instructionsToExport.length > 0 %} pub mod instructions; {% endif %} diff --git a/src/ImportMap.ts b/src/ImportMap.ts index f4a59c6..9dee67e 100644 --- a/src/ImportMap.ts +++ b/src/ImportMap.ts @@ -7,6 +7,7 @@ const DEFAULT_MODULE_MAP: Record = { generated: 'crate::generated', generatedAccounts: 'crate::generated::accounts', generatedErrors: 'crate::generated::errors', + generatedEvents: 'crate::generated::events', generatedInstructions: 'crate::generated::instructions', generatedTypes: 'crate::generated::types', hooked: 'crate::hooked', diff --git a/src/getRenderMapVisitor.ts b/src/getRenderMapVisitor.ts index 55e65a1..21c6a3e 100644 --- a/src/getRenderMapVisitor.ts +++ b/src/getRenderMapVisitor.ts @@ -1,7 +1,10 @@ import { logWarn } from '@codama/errors'; import { + definedTypeNode, + EventNode, getAllAccounts, getAllDefinedTypes, + getAllEvents, getAllInstructionsWithSubs, getAllPrograms, InstructionNode, @@ -31,9 +34,12 @@ import { ImportMap } from './ImportMap'; import { renderValueNode } from './renderValueNodeVisitor'; import { CargoDependencies, + constantDiscriminatorName, Fragment, + getDiscriminatorConditions, getDiscriminatorConstants, getImportFromFactory, + GetImportFromFunction, getTraitsFromNodeFactory, LinkOverrides, render, @@ -54,6 +60,7 @@ export function getRenderMapVisitor(options: GetRenderMapOptions = {}) { const linkables = new LinkableDictionary(); const stack = new NodeStack(); let program: ProgramNode | null = null; + const programsWithEventEnum = new Set(); const renderParentInstructions = options.renderParentInstructions ?? false; const dependencyMap = options.dependencyMap ?? {}; @@ -68,7 +75,7 @@ export function getRenderMapVisitor(options: GetRenderMapOptions = {}) { return pipe( staticVisitor(() => createRenderMap(), { - keys: ['rootNode', 'programNode', 'instructionNode', 'accountNode', 'definedTypeNode'], + keys: ['rootNode', 'programNode', 'instructionNode', 'accountNode', 'definedTypeNode', 'eventNode'], }), v => extendVisitor(v, { @@ -148,6 +155,65 @@ export function getRenderMapVisitor(options: GetRenderMapOptions = {}) { }); }, + visitEvent(node) { + const discriminators = node.discriminators ?? []; + const innerType = resolveNestedTypeNode(node.data); + // Wrap as definedTypeNode so typeManifestVisitor generates the struct with derives. + const syntheticType = definedTypeNode({ + docs: node.docs, + name: node.name, + type: innerType, + }); + const typeManifest = visit(syntheticType, typeManifestVisitor); + + // Discriminator constants. + const fields = isNode(innerType, 'structTypeNode') ? innerType.fields : []; + const discriminatorConstants = getDiscriminatorConstants({ + discriminatorNodes: discriminators, + fields, + getImportFrom, + prefix: node.name, + typeManifestVisitor, + }); + + const hasFromBytes = eventHasFromBytes(node); + const allConstantDiscriminators = hasFromBytes + ? discriminators + .filter(isNodeFilter('constantDiscriminatorNode')) + .map(d => ({ + name: snakeCase( + constantDiscriminatorName(node.name, d, discriminators), + ).toUpperCase(), + offset: d.offset, + })) + .sort((a, b) => a.offset - b.offset) + : []; + + const hiddenPrefixSkipResult = hasFromBytes + ? getHiddenPrefixSkip(node, allConstantDiscriminators) + : null; + const generateFromBytes = hasFromBytes && hiddenPrefixSkipResult !== null; + const hiddenPrefixSkip = hiddenPrefixSkipResult ?? '0'; + const constantDiscriminators = generateFromBytes ? allConstantDiscriminators : []; + + const imports = new ImportMap() + .mergeWithManifest(typeManifest) + .mergeWith(discriminatorConstants.imports) + .remove(`generatedEvents::${pascalCase(node.name)}`); + + return createRenderMap(`events/${snakeCase(node.name)}.rs`, { + content: render('eventsPage.njk', { + constantDiscriminators, + discriminatorConstants: discriminatorConstants.render, + event: node, + hiddenPrefixSkip, + imports: imports.toString(dependencyMap), + typeManifest, + }), + imports, + }); + }, + visitInstruction(node) { // Imports. const imports = new ImportMap(); @@ -260,6 +326,7 @@ export function getRenderMapVisitor(options: GetRenderMapOptions = {}) { let renders = mergeRenderMaps([ ...node.accounts.map(account => visit(account, self)), ...node.definedTypes.map(type => visit(type, self)), + ...(node.events ?? []).map(event => visit(event, self)), ...getAllInstructionsWithSubs(node, { leavesOnly: !renderParentInstructions, }).map(ix => visit(ix, self)), @@ -277,6 +344,23 @@ export function getRenderMapVisitor(options: GetRenderMapOptions = {}) { }); } + // Program events (enum + identify + try_parse). + const programEventsRender = buildProgramEventsRender( + node.events ?? [], + node, + getImportFrom, + typeManifestVisitor, + dependencyMap, + ); + if (programEventsRender) { + programsWithEventEnum.add(node.name); + renders = addToRenderMap( + renders, + `events/${snakeCase(node.name)}_events.rs`, + programEventsRender, + ); + } + program = null; return renders; }, @@ -288,21 +372,28 @@ export function getRenderMapVisitor(options: GetRenderMapOptions = {}) { leavesOnly: !renderParentInstructions, }); const definedTypesToExport = getAllDefinedTypes(node); + const eventsToExport = getAllEvents(node).filter(Boolean); const hasAnythingToExport = programsToExport.length > 0 || accountsToExport.length > 0 || instructionsToExport.length > 0 || - definedTypesToExport.length > 0; + definedTypesToExport.length > 0 || + eventsToExport.length > 0; const ctx = { accountsToExport, definedTypesToExport, + eventsToExport, hasAnythingToExport, instructionsToExport, programsToExport, + programsWithEventEnum, root: node, }; + // Visit programs first so programsWithEventEnum is populated. + const programRenders = getAllPrograms(node).map(p => visit(p, self)); + return mergeRenderMaps([ createRenderMap({ ['accounts/mod.rs']: @@ -313,6 +404,10 @@ export function getRenderMapVisitor(options: GetRenderMapOptions = {}) { programsToExport.length > 0 ? { content: render('errorsMod.njk', ctx), imports: new ImportMap() } : undefined, + ['events/mod.rs']: + eventsToExport.length > 0 + ? { content: render('eventsMod.njk', ctx), imports: new ImportMap() } + : undefined, ['instructions/mod.rs']: instructionsToExport.length > 0 ? { content: render('instructionsMod.njk', ctx), imports: new ImportMap() } @@ -331,7 +426,7 @@ export function getRenderMapVisitor(options: GetRenderMapOptions = {}) { ? { content: render('definedTypesMod.njk', ctx), imports: new ImportMap() } : undefined, }), - ...getAllPrograms(node).map(p => visit(p, self)), + ...programRenders, ]); }, }), @@ -340,6 +435,103 @@ export function getRenderMapVisitor(options: GetRenderMapOptions = {}) { ); } +function eventHasFromBytes(event: EventNode): boolean { + const hasConstantDiscriminator = (event.discriminators ?? []).some(d => isNode(d, 'constantDiscriminatorNode')); + const dataHasHiddenPrefix = isNode(event.data, 'hiddenPrefixTypeNode'); + return hasConstantDiscriminator && dataHasHiddenPrefix; +} + +function getHiddenPrefixSkip( + event: EventNode, + constantDiscriminators: { name: string; offset: number }[], +): string | null { + if (!isNode(event.data, 'hiddenPrefixTypeNode')) { + return '0'; + } + let hasNonFixedSize = false; + const prefixSize = event.data.prefix.reduce((sum, p) => { + if (!isNode(p.type, 'fixedSizeTypeNode')) { + logWarn( + `[Rust] Event [${event.name}] has a non-fixed-size hidden prefix entry; ` + + `from_bytes will not be generated.`, + ); + hasNonFixedSize = true; + return sum; + } + return sum + p.type.size; + }, 0); + if (hasNonFixedSize) { + return null; + } + const firstDisc = constantDiscriminators.find(d => d.offset === 0); + if (event.data.prefix.length === 1 && firstDisc) { + return `${firstDisc.name}.len()`; + } + return String(prefixSize); +} + +function buildProgramEventsRender( + events: EventNode[], + programNode: ProgramNode, + getImportFrom: GetImportFromFunction, + typeManifestVisitor: ReturnType, + dependencyMap: Record, +): { content: string; imports: ImportMap } | null { + if (events.length === 0) { + return null; + } + + const imports = new ImportMap(); + + const eventsWithDiscriminators = events + .filter(event => (event.discriminators ?? []).length > 0) + .flatMap(event => { + const innerType = resolveNestedTypeNode(event.data); + const fields = isNode(innerType, 'structTypeNode') ? innerType.fields : []; + const { conditions, imports: condImports } = getDiscriminatorConditions({ + discriminatorNodes: event.discriminators ?? [], + fields, + getImportFrom, + importPrefix: 'generatedEvents', + prefix: event.name, + typeManifestVisitor, + }); + const discriminators = event.discriminators ?? []; + const eventConstantDiscs = discriminators.filter(isNodeFilter('constantDiscriminatorNode')).map(d => ({ + name: snakeCase(constantDiscriminatorName(event.name, d, discriminators)).toUpperCase(), + offset: d.offset, + })); + const hiddenPrefixSkipResult = isNode(event.data, 'hiddenPrefixTypeNode') + ? getHiddenPrefixSkip(event, eventConstantDiscs) + : '0'; + + if (hiddenPrefixSkipResult === null || conditions.length === 0) { + return []; + } + + imports.mergeWith(condImports); + return [{ ...event, conditions, hiddenPrefixSkip: hiddenPrefixSkipResult }]; + }); + + if (eventsWithDiscriminators.length === 0) { + return null; + } + + imports.add('borsh::BorshDeserialize'); + eventsWithDiscriminators.forEach(event => { + imports.add(`generatedEvents::${pascalCase(event.name)}`); + }); + + return { + content: render('programEventsPage.njk', { + eventsWithDiscriminators, + imports: imports.toString(dependencyMap), + program: programNode, + }), + imports, + }; +} + function getConflictsForInstructionAccountsAndArgs(instruction: InstructionNode): string[] { const allNames = [ ...instruction.accounts.map(account => account.name), diff --git a/src/utils/discriminatorConstant.ts b/src/utils/discriminatorConstant.ts index 8e88e34..943abb2 100644 --- a/src/utils/discriminatorConstant.ts +++ b/src/utils/discriminatorConstant.ts @@ -6,6 +6,7 @@ import { InstructionArgumentNode, isNode, isNodeFilter, + SizeDiscriminatorNode, snakeCase, StructFieldTypeNode, VALUE_NODES, @@ -70,10 +71,7 @@ function getConstantDiscriminatorConstant( ): Fragment { const { discriminatorNodes, getImportFrom, prefix, typeManifestVisitor } = scope; - const index = discriminatorNodes.filter(isNodeFilter('constantDiscriminatorNode')).indexOf(discriminatorNode); - const suffix = index <= 0 ? '' : `_${index + 1}`; - - const name = camelCase(`${prefix}_discriminator${suffix}`); + const name = constantDiscriminatorName(prefix, discriminatorNode, discriminatorNodes); const typeManifest = visit(discriminatorNode.constant.type, typeManifestVisitor); const value = renderValueNode(discriminatorNode.constant.value, getImportFrom); return getConstant(name, typeManifest, value); @@ -95,13 +93,144 @@ function getFieldDiscriminatorConstant( return null; } - const name = camelCase(`${prefix}_${discriminatorNode.name}`); const typeManifest = visit(field.type, typeManifestVisitor); const value = renderValueNode(field.defaultValue, getImportFrom); - return getConstant(name, typeManifest, value); + return getConstant(fieldDiscriminatorName(prefix, discriminatorNode.name), typeManifest, value); } function getConstant(name: string, typeManifest: TypeManifest, value: Fragment): Fragment { const type: Fragment = { imports: typeManifest.imports, render: typeManifest.type }; return mergeFragments([type, value], ([t, v]) => `pub const ${snakeCase(name).toUpperCase()}: ${t} = ${v};`); } + +export function constantDiscriminatorName( + prefix: string, + discriminatorNode: ConstantDiscriminatorNode, + discriminatorNodes: DiscriminatorNode[], +): string { + const index = discriminatorNodes.filter(isNodeFilter('constantDiscriminatorNode')).indexOf(discriminatorNode); + const suffix = index <= 0 ? '' : `_${index + 1}`; + return camelCase(`${prefix}_discriminator${suffix}`); +} + +function fieldDiscriminatorName(prefix: string, fieldName: string): string { + return camelCase(`${prefix}_${fieldName}`); +} + +export function getDiscriminatorConditions(scope: { + discriminatorNodes: DiscriminatorNode[]; + fields: InstructionArgumentNode[] | StructFieldTypeNode[]; + getImportFrom: GetImportFromFunction; + importPrefix: string; + prefix: string; + typeManifestVisitor: ReturnType; +}): { conditions: string[]; imports: ImportMap } { + const imports = new ImportMap(); + const conditions = scope.discriminatorNodes + .map(node => getDiscriminatorCondition(node, scope, imports)) + .filter(Boolean) as string[]; + return { conditions, imports }; +} + +function getDiscriminatorCondition( + discriminatorNode: DiscriminatorNode, + scope: { + discriminatorNodes: DiscriminatorNode[]; + fields: InstructionArgumentNode[] | StructFieldTypeNode[]; + getImportFrom: GetImportFromFunction; + importPrefix: string; + prefix: string; + typeManifestVisitor: ReturnType; + }, + imports: ImportMap, +): string | null { + switch (discriminatorNode.kind) { + case 'sizeDiscriminatorNode': + return getSizeCondition(discriminatorNode); + case 'constantDiscriminatorNode': + return getConstantCondition(discriminatorNode, scope, imports); + case 'fieldDiscriminatorNode': + return getFieldCondition(discriminatorNode, scope, imports); + default: + return null; + } +} + +function getSizeCondition(discriminatorNode: SizeDiscriminatorNode): string { + return `data.len() == ${discriminatorNode.size}`; +} + +function getConstantCondition( + discriminatorNode: ConstantDiscriminatorNode, + scope: { + discriminatorNodes: DiscriminatorNode[]; + importPrefix: string; + prefix: string; + }, + imports: ImportMap, +): string { + const { discriminatorNodes, importPrefix, prefix } = scope; + const constName = snakeCase(constantDiscriminatorName(prefix, discriminatorNode, discriminatorNodes)).toUpperCase(); + imports.add(`${importPrefix}::${constName}`); + + const offset = discriminatorNode.offset; + if (offset === 0) { + return `data.get(..${constName}.len()) == Some(&${constName}[..])`; + } + return `data.get(${offset}..${offset} + ${constName}.len()) == Some(&${constName}[..])`; +} + +function getFieldCondition( + discriminatorNode: FieldDiscriminatorNode, + scope: { + fields: InstructionArgumentNode[] | StructFieldTypeNode[]; + importPrefix: string; + prefix: string; + }, + imports: ImportMap, +): string | null { + const { fields, importPrefix, prefix } = scope; + const field = fields.find(f => f.name === discriminatorNode.name); + if (!field || !field.defaultValue || !isNode(field.defaultValue, VALUE_NODES)) { + return null; + } + + const constName = snakeCase(fieldDiscriminatorName(prefix, discriminatorNode.name)).toUpperCase(); + imports.add(`${importPrefix}::${constName}`); + const offset = discriminatorNode.offset; + + if (isNode(field.type, 'numberTypeNode')) { + const byteSize = getNumberByteSize(field.type.format); + const bytesFn = field.type.endian === 'le' ? 'to_le_bytes' : 'to_be_bytes'; + const range = offset === 0 ? `..${byteSize}` : `${offset}..${offset + byteSize}`; + return `data.get(${range}) == Some(&${constName}.${bytesFn}())`; + } + + if (offset === 0) { + return `data.get(..${constName}.len()) == Some(&${constName}[..])`; + } + return `data.get(${offset}..${offset} + ${constName}.len()) == Some(&${constName}[..])`; +} + +const NUMBER_BYTE_SIZES: Record = { + f32: 4, + f64: 8, + i128: 16, + i16: 2, + i32: 4, + i64: 8, + i8: 1, + u128: 16, + u16: 2, + u32: 4, + u64: 8, + u8: 1, +}; + +function getNumberByteSize(format: string): number { + const size = NUMBER_BYTE_SIZES[format]; + if (size === undefined) { + throw new Error(`Unknown number format: ${format}`); + } + return size; +} diff --git a/test/eventsPage.test.ts b/test/eventsPage.test.ts new file mode 100644 index 0000000..0de92bd --- /dev/null +++ b/test/eventsPage.test.ts @@ -0,0 +1,802 @@ +import { + arrayTypeNode, + arrayValueNode, + bytesTypeNode, + bytesValueNode, + constantDiscriminatorNode, + constantValueNode, + eventNode, + fieldDiscriminatorNode, + fixedCountNode, + fixedSizeTypeNode, + hiddenPrefixTypeNode, + numberTypeNode, + numberValueNode, + programNode, + rootNode, + sizeDiscriminatorNode, + structFieldTypeNode, + structTypeNode, +} from '@codama/nodes'; +import { getFromRenderMap } from '@codama/renderers-core'; +import { visit } from '@codama/visitors-core'; +import { expect, test } from 'vitest'; + +import { getRenderMapVisitor } from '../src'; +import { codeContains, codeDoesNotContains } from './_setup'; + +test('it renders an event with discriminator as a struct with from_bytes', () => { + const node = programNode({ + events: [ + eventNode({ + data: hiddenPrefixTypeNode( + structTypeNode([ + structFieldTypeNode({ name: 'amount', type: numberTypeNode('u64') }), + structFieldTypeNode({ name: 'price', type: numberTypeNode('u64') }), + ]), + [ + constantValueNode( + fixedSizeTypeNode(bytesTypeNode(), 8), + bytesValueNode('base16', 'bddB7fd34ee661ee'), + ), + ], + ), + discriminators: [ + constantDiscriminatorNode( + constantValueNode( + fixedSizeTypeNode(bytesTypeNode(), 8), + bytesValueNode('base16', 'bddB7fd34ee661ee'), + ), + ), + ], + name: 'tradeEvent', + }), + ], + name: 'myProgram', + publicKey: '11111111111111111111111111111111', + }); + + const renderMap = visit(node, getRenderMapVisitor()); + + codeContains(getFromRenderMap(renderMap, 'events/trade_event.rs').content, [ + '#[derive(', + 'BorshSerialize', + 'BorshDeserialize', + 'pub struct TradeEvent', + 'pub amount: u64,', + 'pub price: u64,', + 'TRADE_EVENT_DISCRIMINATOR', + 'pub fn from_bytes', + '"invalid event discriminator"', + 'Self::deserialize(&mut data)', + ]); +}); + +test('it renders an event without discriminator as a plain struct', () => { + const node = programNode({ + events: [ + eventNode({ + data: structTypeNode([structFieldTypeNode({ name: 'value', type: numberTypeNode('u32') })]), + name: 'simpleEvent', + }), + ], + name: 'myProgram', + publicKey: '11111111111111111111111111111111', + }); + + const renderMap = visit(node, getRenderMapVisitor()); + codeContains(getFromRenderMap(renderMap, 'events/simple_event.rs').content, [ + 'pub struct SimpleEvent', + 'pub value: u32,', + ]); + codeDoesNotContains(getFromRenderMap(renderMap, 'events/simple_event.rs').content, ['DISCRIMINATOR', 'from_bytes']); +}); + +test('it does not render events module for programs without events', () => { + const node = rootNode( + programNode({ + name: 'myProgram', + publicKey: '11111111111111111111111111111111', + }), + ); + + const renderMap = visit(node, getRenderMapVisitor()); + + codeDoesNotContains(getFromRenderMap(renderMap, 'mod.rs').content, 'pub mod events;'); +}); + +test('it renders events in the events module', () => { + const node = rootNode( + programNode({ + events: [ + eventNode({ + data: structTypeNode([structFieldTypeNode({ name: 'amount', type: numberTypeNode('u64') })]), + name: 'transferEvent', + }), + eventNode({ + data: structTypeNode([structFieldTypeNode({ name: 'delegate', type: numberTypeNode('u64') })]), + name: 'approveEvent', + }), + ], + name: 'myProgram', + publicKey: '11111111111111111111111111111111', + }), + ); + + const renderMap = visit(node, getRenderMapVisitor()); + codeContains(getFromRenderMap(renderMap, 'events/mod.rs').content, [ + 'pub(crate) mod r#approve_event;', + 'pub use self::r#approve_event::*;', + 'pub(crate) mod r#transfer_event;', + 'pub use self::r#transfer_event::*;', + ]); + + codeContains(getFromRenderMap(renderMap, 'mod.rs').content, 'pub mod events;'); +}); + +test('it renders an event with an empty struct', () => { + const node = programNode({ + events: [ + eventNode({ + data: structTypeNode([]), + name: 'emptyEvent', + }), + ], + name: 'myProgram', + publicKey: '11111111111111111111111111111111', + }); + + const renderMap = visit(node, getRenderMapVisitor()); + codeContains(getFromRenderMap(renderMap, 'events/empty_event.rs').content, ['pub struct EmptyEvent']); + codeDoesNotContains(getFromRenderMap(renderMap, 'events/empty_event.rs').content, ['from_bytes', 'DISCRIMINATOR']); +}); + +test('it renders event docs', () => { + const node = programNode({ + events: [ + eventNode({ + data: structTypeNode([structFieldTypeNode({ name: 'value', type: numberTypeNode('u32') })]), + docs: ['Some documentation.', 'Second line.'], + name: 'documentedEvent', + }), + ], + name: 'myProgram', + publicKey: '11111111111111111111111111111111', + }); + + const renderMap = visit(node, getRenderMapVisitor()); + codeContains(getFromRenderMap(renderMap, 'events/documented_event.rs').content, [ + '/// Some documentation.', + '/// Second line.', + 'pub struct DocumentedEvent', + ]); +}); + +test('it renders an event with a nested struct field', () => { + const node = programNode({ + events: [ + eventNode({ + data: structTypeNode([ + structFieldTypeNode({ name: 'amount', type: numberTypeNode('u64') }), + structFieldTypeNode({ + name: 'metadata', + type: structTypeNode([ + structFieldTypeNode({ name: 'label', type: numberTypeNode('u8') }), + structFieldTypeNode({ name: 'version', type: numberTypeNode('u16') }), + ]), + }), + ]), + name: 'complexEvent', + }), + ], + name: 'myProgram', + publicKey: '11111111111111111111111111111111', + }); + + const renderMap = visit(node, getRenderMapVisitor()); + codeContains(getFromRenderMap(renderMap, 'events/complex_event.rs').content, [ + 'pub struct ComplexEvent', + 'pub amount: u64,', + 'pub metadata: ComplexEventMetadata,', + 'pub struct ComplexEventMetadata', + 'pub label: u8,', + 'pub version: u16,', + ]); +}); + +test('it renders field discriminator constants and skips from_bytes without hidden prefix', () => { + const node = programNode({ + events: [ + eventNode({ + data: structTypeNode([ + structFieldTypeNode({ + defaultValue: numberValueNode(7), + name: 'eventType', + type: numberTypeNode('u8'), + }), + structFieldTypeNode({ name: 'value', type: numberTypeNode('u64') }), + ]), + discriminators: [ + fieldDiscriminatorNode('eventType'), + constantDiscriminatorNode( + constantValueNode( + fixedSizeTypeNode(bytesTypeNode(), 8), + bytesValueNode('base16', 'aabbccdd11223344'), + ), + ), + ], + name: 'mixedEvent', + }), + ], + name: 'myProgram', + publicKey: '11111111111111111111111111111111', + }); + + const renderMap = visit(node, getRenderMapVisitor()); + const code = getFromRenderMap(renderMap, 'events/mixed_event.rs').content; + + codeContains(code, ['MIXED_EVENT_EVENT_TYPE: u8 = 7']); + codeContains(code, ['MIXED_EVENT_DISCRIMINATOR']); + codeDoesNotContains(code, ['from_bytes']); +}); + +test('it validates all constant discriminators in from_bytes for multi-disc events', () => { + const disc1 = constantValueNode( + fixedSizeTypeNode(bytesTypeNode(), 8), + bytesValueNode('base16', 'aabbccdd11223344'), + ); + const disc2 = constantValueNode(fixedSizeTypeNode(bytesTypeNode(), 4), bytesValueNode('base16', 'eeff0011')); + const node = programNode({ + events: [ + eventNode({ + data: hiddenPrefixTypeNode( + structTypeNode([structFieldTypeNode({ name: 'value', type: numberTypeNode('u64') })]), + [disc1], + ), + discriminators: [constantDiscriminatorNode(disc1, 0), constantDiscriminatorNode(disc2, 12)], + name: 'multiDiscEvent', + }), + ], + name: 'myProgram', + publicKey: '11111111111111111111111111111111', + }); + + const renderMap = visit(node, getRenderMapVisitor()); + const code = getFromRenderMap(renderMap, 'events/multi_disc_event.rs').content; + + codeContains(code, [ + 'pub fn from_bytes', + 'MULTI_DISC_EVENT_DISCRIMINATOR.len()) != Some(&MULTI_DISC_EVENT_DISCRIMINATOR[..])', + 'data.get(12..12 + MULTI_DISC_EVENT_DISCRIMINATOR2.len()) != Some(&MULTI_DISC_EVENT_DISCRIMINATOR2[..])', + 'Self::deserialize(&mut data)', + ]); +}); + +test('it uses literal byte count in from_bytes for multi-prefix hidden prefix', () => { + const prefix1 = constantValueNode( + fixedSizeTypeNode(bytesTypeNode(), 8), + bytesValueNode('base16', 'aabbccdd11223344'), + ); + const prefix2 = constantValueNode(fixedSizeTypeNode(bytesTypeNode(), 4), bytesValueNode('base16', 'eeff0011')); + const node = programNode({ + events: [ + eventNode({ + data: hiddenPrefixTypeNode( + structTypeNode([structFieldTypeNode({ name: 'value', type: numberTypeNode('u64') })]), + [prefix1, prefix2], + ), + discriminators: [constantDiscriminatorNode(prefix1, 0)], + name: 'multiPrefixEvent', + }), + ], + name: 'myProgram', + publicKey: '11111111111111111111111111111111', + }); + + const renderMap = visit(node, getRenderMapVisitor()); + const code = getFromRenderMap(renderMap, 'events/multi_prefix_event.rs').content; + + codeContains(code, ['let mut data = &data[12..];']); + codeDoesNotContains(code, ['.len()..']); +}); + +test('it uses literal byte count in from_bytes when constant disc is not at offset 0', () => { + const prefix = constantValueNode( + fixedSizeTypeNode(bytesTypeNode(), 8), + bytesValueNode('base16', 'aabbccdd11223344'), + ); + const node = programNode({ + events: [ + eventNode({ + data: hiddenPrefixTypeNode( + structTypeNode([structFieldTypeNode({ name: 'value', type: numberTypeNode('u64') })]), + [prefix], + ), + discriminators: [constantDiscriminatorNode(prefix, 8)], + name: 'offsetPrefixEvent', + }), + ], + name: 'myProgram', + publicKey: '11111111111111111111111111111111', + }); + + const renderMap = visit(node, getRenderMapVisitor()); + const code = getFromRenderMap(renderMap, 'events/offset_prefix_event.rs').content; + + codeContains(code, ['let mut data = &data[8..];']); + codeDoesNotContains(code, ['.len()..']); +}); + +test('it does not render from_bytes when hidden prefix has a non-fixed-size entry', () => { + const prefix1 = constantValueNode( + fixedSizeTypeNode(bytesTypeNode(), 8), + bytesValueNode('base16', 'aabbccdd11223344'), + ); + const prefix2 = constantValueNode(numberTypeNode('u32'), numberValueNode(42)); + const node = programNode({ + events: [ + eventNode({ + data: hiddenPrefixTypeNode( + structTypeNode([structFieldTypeNode({ name: 'value', type: numberTypeNode('u64') })]), + [prefix1, prefix2], + ), + discriminators: [constantDiscriminatorNode(prefix1)], + name: 'dynamicPrefixEvent', + }), + ], + name: 'myProgram', + publicKey: '11111111111111111111111111111111', + }); + + const renderMap = visit(node, getRenderMapVisitor()); + const code = getFromRenderMap(renderMap, 'events/dynamic_prefix_event.rs').content; + + codeContains(code, ['pub struct DynamicPrefixEvent', 'DYNAMIC_PREFIX_EVENT_DISCRIMINATOR']); + codeDoesNotContains(code, ['from_bytes']); +}); +// --- Program-level event codegen tests --- + +test('it does not render program events file when no events have discriminators', () => { + const node = programNode({ + events: [ + eventNode({ + data: structTypeNode([structFieldTypeNode({ name: 'amount', type: numberTypeNode('u64') })]), + name: 'transferEvent', + }), + eventNode({ + data: structTypeNode([structFieldTypeNode({ name: 'delegate', type: numberTypeNode('u64') })]), + name: 'approveEvent', + }), + ], + name: 'myProgram', + publicKey: '11111111111111111111111111111111', + }); + + const renderMap = visit(node, getRenderMapVisitor()); + const keys = [...renderMap.keys()]; + const programEventsFiles = keys.filter(k => k.includes('my_program_events')); + expect(programEventsFiles).toHaveLength(0); +}); + +test('it renders identify and try_parse for events with constant discriminators', () => { + const node = programNode({ + events: [ + eventNode({ + data: hiddenPrefixTypeNode( + structTypeNode([structFieldTypeNode({ name: 'amount', type: numberTypeNode('u64') })]), + [ + constantValueNode( + fixedSizeTypeNode(bytesTypeNode(), 8), + bytesValueNode('base16', 'aabbccdd11223344'), + ), + ], + ), + discriminators: [ + constantDiscriminatorNode( + constantValueNode( + fixedSizeTypeNode(bytesTypeNode(), 8), + bytesValueNode('base16', 'aabbccdd11223344'), + ), + ), + ], + name: 'tradeEvent', + }), + eventNode({ + data: hiddenPrefixTypeNode( + structTypeNode([structFieldTypeNode({ name: 'price', type: numberTypeNode('u64') })]), + [ + constantValueNode( + fixedSizeTypeNode(bytesTypeNode(), 8), + bytesValueNode('base16', '1122334455667788'), + ), + ], + ), + discriminators: [ + constantDiscriminatorNode( + constantValueNode( + fixedSizeTypeNode(bytesTypeNode(), 8), + bytesValueNode('base16', '1122334455667788'), + ), + ), + ], + name: 'settleEvent', + }), + ], + name: 'myProgram', + publicKey: '11111111111111111111111111111111', + }); + + const renderMap = visit(node, getRenderMapVisitor()); + const code = getFromRenderMap(renderMap, 'events/my_program_events.rs').content; + + codeContains(code, [ + 'pub fn identify_my_program_event(data: &[u8]) -> Option', + 'SETTLE_EVENT_DISCRIMINATOR', + 'return Some(MyProgramEventKind::SettleEvent)', + 'TRADE_EVENT_DISCRIMINATOR', + 'return Some(MyProgramEventKind::TradeEvent)', + 'pub fn try_parse_my_program_event(data: &[u8]) -> Option>', + 'identify_my_program_event(data)?', + 'MyProgramEventKind::SettleEvent =>', + 'let mut data = &data[SETTLE_EVENT_DISCRIMINATOR.len()..]', + 'SettleEvent::deserialize(&mut data)', + 'MyProgramEventKind::TradeEvent =>', + 'let mut data = &data[TRADE_EVENT_DISCRIMINATOR.len()..]', + 'TradeEvent::deserialize(&mut data)', + ]); + codeDoesNotContains(code, ['from_bytes', 'Err(std::io::Error::new']); +}); + +test('it uses BorshDeserialize for events without from_bytes in try_parse', () => { + const node = programNode({ + events: [ + eventNode({ + data: hiddenPrefixTypeNode( + structTypeNode([structFieldTypeNode({ name: 'amount', type: numberTypeNode('u64') })]), + [ + constantValueNode( + fixedSizeTypeNode(bytesTypeNode(), 8), + bytesValueNode('base16', 'aabbccdd11223344'), + ), + ], + ), + discriminators: [ + constantDiscriminatorNode( + constantValueNode( + fixedSizeTypeNode(bytesTypeNode(), 8), + bytesValueNode('base16', 'aabbccdd11223344'), + ), + ), + ], + name: 'tradeEvent', + }), + eventNode({ + data: structTypeNode([structFieldTypeNode({ name: 'value', type: numberTypeNode('u32') })]), + discriminators: [ + constantDiscriminatorNode( + constantValueNode( + fixedSizeTypeNode(bytesTypeNode(), 8), + bytesValueNode('base16', '5566778899aabbcc'), + ), + ), + ], + name: 'simpleEvent', + }), + ], + name: 'myProgram', + publicKey: '11111111111111111111111111111111', + }); + + const renderMap = visit(node, getRenderMapVisitor()); + const code = getFromRenderMap(renderMap, 'events/my_program_events.rs').content; + + codeContains(code, [ + 'let mut data = &data[TRADE_EVENT_DISCRIMINATOR.len()..]', + 'TradeEvent::deserialize(&mut data)', + ]); + codeContains(code, ['SimpleEvent::deserialize(&mut data)']); + codeDoesNotContains(code, ['from_bytes']); +}); + +test('it excludes non-fixed-size prefix events from program-level try_parse', () => { + const fixedPrefix = constantValueNode( + fixedSizeTypeNode(bytesTypeNode(), 8), + bytesValueNode('base16', 'aabbccdd11223344'), + ); + const nonFixedPrefix = constantValueNode(numberTypeNode('u32'), numberValueNode(42)); + const node = programNode({ + events: [ + eventNode({ + data: hiddenPrefixTypeNode( + structTypeNode([structFieldTypeNode({ name: 'value', type: numberTypeNode('u64') })]), + [fixedPrefix], + ), + discriminators: [constantDiscriminatorNode(fixedPrefix)], + name: 'goodEvent', + }), + eventNode({ + data: hiddenPrefixTypeNode( + structTypeNode([structFieldTypeNode({ name: 'value', type: numberTypeNode('u64') })]), + [fixedPrefix, nonFixedPrefix], + ), + discriminators: [constantDiscriminatorNode(fixedPrefix)], + name: 'dynamicEvent', + }), + ], + name: 'myProgram', + publicKey: '11111111111111111111111111111111', + }); + + const renderMap = visit(node, getRenderMapVisitor()); + const code = getFromRenderMap(renderMap, 'events/my_program_events.rs').content; + + codeContains(code, ['GoodEvent', 'GoodEvent::deserialize']); + codeDoesNotContains(code, ['DynamicEvent']); +}); + +test('it does not render program events file when program has no events', () => { + const node = programNode({ + name: 'myProgram', + publicKey: '11111111111111111111111111111111', + }); + + const renderMap = visit(node, getRenderMapVisitor()); + const keys = [...renderMap.keys()]; + const programEventsFiles = keys.filter(k => k.includes('_events.rs')); + expect(programEventsFiles).toHaveLength(0); +}); + +test('it includes program events module in events mod.rs', () => { + const node = rootNode( + programNode({ + events: [ + eventNode({ + data: hiddenPrefixTypeNode( + structTypeNode([structFieldTypeNode({ name: 'amount', type: numberTypeNode('u64') })]), + [ + constantValueNode( + fixedSizeTypeNode(bytesTypeNode(), 8), + bytesValueNode('base16', 'aabbccdd11223344'), + ), + ], + ), + discriminators: [ + constantDiscriminatorNode( + constantValueNode( + fixedSizeTypeNode(bytesTypeNode(), 8), + bytesValueNode('base16', 'aabbccdd11223344'), + ), + ), + ], + name: 'transferEvent', + }), + ], + name: 'myProgram', + publicKey: '11111111111111111111111111111111', + }), + ); + + const renderMap = visit(node, getRenderMapVisitor()); + expect(renderMap.has('events/my_program_events.rs')).toBe(true); + codeContains(getFromRenderMap(renderMap, 'events/mod.rs').content, [ + 'pub(crate) mod r#my_program_events;', + 'pub use self::r#my_program_events::*;', + ]); +}); + +test('it excludes program events module from events mod.rs when no events have discriminators', () => { + const node = rootNode( + programNode({ + events: [ + eventNode({ + data: structTypeNode([structFieldTypeNode({ name: 'amount', type: numberTypeNode('u64') })]), + name: 'transferEvent', + }), + ], + name: 'myProgram', + publicKey: '11111111111111111111111111111111', + }), + ); + + const renderMap = visit(node, getRenderMapVisitor()); + codeDoesNotContains(getFromRenderMap(renderMap, 'events/mod.rs').content, ['my_program_events']); +}); + +test('it renders identify and try_parse for events with field discriminators', () => { + const node = programNode({ + events: [ + eventNode({ + data: structTypeNode([ + structFieldTypeNode({ + defaultValue: numberValueNode(7), + name: 'eventType', + type: numberTypeNode('u8'), + }), + structFieldTypeNode({ name: 'value', type: numberTypeNode('u64') }), + ]), + discriminators: [fieldDiscriminatorNode('eventType')], + name: 'typedEvent', + }), + eventNode({ + data: structTypeNode([ + structFieldTypeNode({ + defaultValue: numberValueNode(1.0), + name: 'version', + type: numberTypeNode('f32'), + }), + structFieldTypeNode({ name: 'value', type: numberTypeNode('u64') }), + ]), + discriminators: [fieldDiscriminatorNode('version')], + name: 'floatDiscEvent', + }), + ], + name: 'myProgram', + publicKey: '11111111111111111111111111111111', + }); + + const renderMap = visit(node, getRenderMapVisitor()); + const code = getFromRenderMap(renderMap, 'events/my_program_events.rs').content; + + codeContains(code, [ + 'pub fn identify_my_program_event', + 'data.get(..1) == Some(&TYPED_EVENT_EVENT_TYPE.to_le_bytes())', + 'return Some(MyProgramEventKind::TypedEvent)', + 'data.get(..4) == Some(&FLOAT_DISC_EVENT_VERSION.to_le_bytes())', + 'return Some(MyProgramEventKind::FloatDiscEvent)', + 'pub fn try_parse_my_program_event', + ]); +}); + +test('it renders identify and try_parse for events with size discriminators', () => { + const node = programNode({ + events: [ + eventNode({ + data: structTypeNode([structFieldTypeNode({ name: 'value', type: numberTypeNode('u64') })]), + discriminators: [sizeDiscriminatorNode(8)], + name: 'fixedSizeEvent', + }), + ], + name: 'myProgram', + publicKey: '11111111111111111111111111111111', + }); + + const renderMap = visit(node, getRenderMapVisitor()); + const code = getFromRenderMap(renderMap, 'events/my_program_events.rs').content; + + codeContains(code, [ + 'pub fn identify_my_program_event', + 'data.len() == 8', + 'return Some(MyProgramEventKind::FixedSizeEvent)', + 'pub fn try_parse_my_program_event', + ]); +}); + +test('it AND-s multiple discriminators for the same event in identify', () => { + const node = programNode({ + events: [ + eventNode({ + data: structTypeNode([ + structFieldTypeNode({ + defaultValue: numberValueNode(3), + name: 'eventType', + type: numberTypeNode('u8'), + }), + structFieldTypeNode({ name: 'value', type: numberTypeNode('u64') }), + ]), + discriminators: [sizeDiscriminatorNode(9), fieldDiscriminatorNode('eventType')], + name: 'mixedDiscEvent', + }), + ], + name: 'myProgram', + publicKey: '11111111111111111111111111111111', + }); + + const renderMap = visit(node, getRenderMapVisitor()); + const code = getFromRenderMap(renderMap, 'events/my_program_events.rs').content; + + codeContains(code, [ + 'data.len() == 9 && data.get(..1) == Some(&MIXED_DISC_EVENT_EVENT_TYPE.to_le_bytes())', + 'return Some(MyProgramEventKind::MixedDiscEvent)', + ]); +}); + +test('it renders identify for events with byte-array field discriminators', () => { + const node = programNode({ + events: [ + eventNode({ + data: structTypeNode([ + structFieldTypeNode({ + defaultValue: arrayValueNode([numberValueNode(1), numberValueNode(2), numberValueNode(3)]), + name: 'disc', + type: arrayTypeNode(numberTypeNode('u8'), fixedCountNode(3)), + }), + structFieldTypeNode({ name: 'value', type: numberTypeNode('u64') }), + ]), + discriminators: [fieldDiscriminatorNode('disc')], + name: 'arrayDiscEvent', + }), + ], + name: 'myProgram', + publicKey: '11111111111111111111111111111111', + }); + + const renderMap = visit(node, getRenderMapVisitor()); + const code = getFromRenderMap(renderMap, 'events/my_program_events.rs').content; + + codeContains(code, [ + 'pub fn identify_my_program_event', + 'data.get(..ARRAY_DISC_EVENT_DISC.len()) == Some(&ARRAY_DISC_EVENT_DISC[..])', + 'return Some(MyProgramEventKind::ArrayDiscEvent)', + ]); + codeDoesNotContains(code, ['to_le_bytes']); + + const eventCode = getFromRenderMap(renderMap, 'events/array_disc_event.rs').content; + codeContains(eventCode, ['ARRAY_DISC_EVENT_DISC: [u8; 3] = [1, 2, 3]']); +}); + +test('it handles non-zero offset in constant discriminator conditions', () => { + const node = programNode({ + events: [ + eventNode({ + data: structTypeNode([structFieldTypeNode({ name: 'value', type: numberTypeNode('u64') })]), + discriminators: [ + constantDiscriminatorNode( + constantValueNode(fixedSizeTypeNode(bytesTypeNode(), 4), bytesValueNode('base16', 'aabbccdd')), + 8, + ), + ], + name: 'offsetEvent', + }), + ], + name: 'myProgram', + publicKey: '11111111111111111111111111111111', + }); + + const renderMap = visit(node, getRenderMapVisitor()); + const code = getFromRenderMap(renderMap, 'events/my_program_events.rs').content; + + codeContains(code, [ + 'pub fn identify_my_program_event', + 'data.get(8..8 + OFFSET_EVENT_DISCRIMINATOR.len()) == Some(&OFFSET_EVENT_DISCRIMINATOR[..])', + 'return Some(MyProgramEventKind::OffsetEvent)', + 'pub fn try_parse_my_program_event', + 'OffsetEvent::deserialize(&mut data)', + ]); +}); + +test('it handles multiple constant discriminators and excludes events with unresolvable field discriminators', () => { + const disc1 = constantValueNode(fixedSizeTypeNode(bytesTypeNode(), 4), bytesValueNode('base16', 'aabbccdd')); + const disc2 = constantValueNode(fixedSizeTypeNode(bytesTypeNode(), 2), bytesValueNode('base16', 'eeff')); + const node = programNode({ + events: [ + // Event with two constant discriminators — tests _2 suffix naming and AND-ing. + eventNode({ + data: structTypeNode([structFieldTypeNode({ name: 'value', type: numberTypeNode('u64') })]), + discriminators: [constantDiscriminatorNode(disc1, 0), constantDiscriminatorNode(disc2, 4)], + name: 'multiDiscEvent', + }), + // Event with field discriminator that has no defaultValue — should be excluded. + eventNode({ + data: structTypeNode([ + structFieldTypeNode({ name: 'eventType', type: numberTypeNode('u8') }), + structFieldTypeNode({ name: 'value', type: numberTypeNode('u64') }), + ]), + discriminators: [fieldDiscriminatorNode('eventType')], + name: 'noDefaultEvent', + }), + ], + name: 'myProgram', + publicKey: '11111111111111111111111111111111', + }); + + const renderMap = visit(node, getRenderMapVisitor()); + const code = getFromRenderMap(renderMap, 'events/my_program_events.rs').content; + + codeContains(code, [ + 'MULTI_DISC_EVENT_DISCRIMINATOR.len()) == Some(&MULTI_DISC_EVENT_DISCRIMINATOR[..])', + 'MULTI_DISC_EVENT_DISCRIMINATOR2.len()) == Some(&MULTI_DISC_EVENT_DISCRIMINATOR2[..])', + 'return Some(MyProgramEventKind::MultiDiscEvent)', + ]); + codeContains(code, ['pub enum MyProgramEventKind']); + codeDoesNotContains(code, ['NoDefaultEvent']); +}); From 6d29910c1918e19b246800b25c31f0b1fd12dadc Mon Sep 17 00:00:00 2001 From: ioxde <228087182+ioxde@users.noreply.github.com> Date: Fri, 17 Apr 2026 11:04:13 -0700 Subject: [PATCH 05/24] Regenerate Raydium Launchpad fixture with events Generated event codegen output for the Raydium Launchpad e2e fixture after rebasing onto event codegen support. --- .../generated/events/claim_vested_event.rs | 35 ++++++++ .../generated/events/create_vesting_event.rs | 35 ++++++++ .../src/generated/events/mod.rs | 18 ++++ .../src/generated/events/pool_create_event.rs | 41 +++++++++ .../events/raydium_launchpad_events.rs | 83 +++++++++++++++++++ .../src/generated/events/trade_event.rs | 47 +++++++++++ e2e/raydium-launchpad/src/generated/mod.rs | 1 + 7 files changed, 260 insertions(+) create mode 100644 e2e/raydium-launchpad/src/generated/events/claim_vested_event.rs create mode 100644 e2e/raydium-launchpad/src/generated/events/create_vesting_event.rs create mode 100644 e2e/raydium-launchpad/src/generated/events/mod.rs create mode 100644 e2e/raydium-launchpad/src/generated/events/pool_create_event.rs create mode 100644 e2e/raydium-launchpad/src/generated/events/raydium_launchpad_events.rs create mode 100644 e2e/raydium-launchpad/src/generated/events/trade_event.rs diff --git a/e2e/raydium-launchpad/src/generated/events/claim_vested_event.rs b/e2e/raydium-launchpad/src/generated/events/claim_vested_event.rs new file mode 100644 index 0000000..768e284 --- /dev/null +++ b/e2e/raydium-launchpad/src/generated/events/claim_vested_event.rs @@ -0,0 +1,35 @@ +//! This code was AUTOGENERATED using the codama library. +//! Please DO NOT EDIT THIS FILE, instead use visitors +//! to add features, then rerun codama to update it. +//! +//! +//! + +use borsh::BorshDeserialize; +use borsh::BorshSerialize; +use solana_address::Address; + +#[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] +pub struct ClaimVestedEvent { + pub pool_state: Address, + pub beneficiary: Address, + pub claim_amount: u64, +} + +pub const CLAIM_VESTED_EVENT_DISCRIMINATOR: [u8; 8] = [21, 194, 114, 87, 120, 211, 226, 32]; + +impl ClaimVestedEvent { + #[inline(always)] + pub fn from_bytes(data: &[u8]) -> Result { + if data.get(..CLAIM_VESTED_EVENT_DISCRIMINATOR.len()) + != Some(&CLAIM_VESTED_EVENT_DISCRIMINATOR[..]) + { + return Err(std::io::Error::new( + std::io::ErrorKind::InvalidData, + "invalid event discriminator", + )); + } + let mut data = &data[CLAIM_VESTED_EVENT_DISCRIMINATOR.len()..]; + Self::deserialize(&mut data) + } +} diff --git a/e2e/raydium-launchpad/src/generated/events/create_vesting_event.rs b/e2e/raydium-launchpad/src/generated/events/create_vesting_event.rs new file mode 100644 index 0000000..46d04df --- /dev/null +++ b/e2e/raydium-launchpad/src/generated/events/create_vesting_event.rs @@ -0,0 +1,35 @@ +//! This code was AUTOGENERATED using the codama library. +//! Please DO NOT EDIT THIS FILE, instead use visitors +//! to add features, then rerun codama to update it. +//! +//! +//! + +use borsh::BorshDeserialize; +use borsh::BorshSerialize; +use solana_address::Address; + +#[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] +pub struct CreateVestingEvent { + pub pool_state: Address, + pub beneficiary: Address, + pub share_amount: u64, +} + +pub const CREATE_VESTING_EVENT_DISCRIMINATOR: [u8; 8] = [150, 152, 11, 179, 52, 210, 191, 125]; + +impl CreateVestingEvent { + #[inline(always)] + pub fn from_bytes(data: &[u8]) -> Result { + if data.get(..CREATE_VESTING_EVENT_DISCRIMINATOR.len()) + != Some(&CREATE_VESTING_EVENT_DISCRIMINATOR[..]) + { + return Err(std::io::Error::new( + std::io::ErrorKind::InvalidData, + "invalid event discriminator", + )); + } + let mut data = &data[CREATE_VESTING_EVENT_DISCRIMINATOR.len()..]; + Self::deserialize(&mut data) + } +} diff --git a/e2e/raydium-launchpad/src/generated/events/mod.rs b/e2e/raydium-launchpad/src/generated/events/mod.rs new file mode 100644 index 0000000..f6bb9ee --- /dev/null +++ b/e2e/raydium-launchpad/src/generated/events/mod.rs @@ -0,0 +1,18 @@ +//! This code was AUTOGENERATED using the codama library. +//! Please DO NOT EDIT THIS FILE, instead use visitors +//! to add features, then rerun codama to update it. +//! +//! +//! + +pub(crate) mod r#claim_vested_event; +pub(crate) mod r#create_vesting_event; +pub(crate) mod r#pool_create_event; +pub(crate) mod r#raydium_launchpad_events; +pub(crate) mod r#trade_event; + +pub use self::r#claim_vested_event::*; +pub use self::r#create_vesting_event::*; +pub use self::r#pool_create_event::*; +pub use self::r#raydium_launchpad_events::*; +pub use self::r#trade_event::*; diff --git a/e2e/raydium-launchpad/src/generated/events/pool_create_event.rs b/e2e/raydium-launchpad/src/generated/events/pool_create_event.rs new file mode 100644 index 0000000..647bb21 --- /dev/null +++ b/e2e/raydium-launchpad/src/generated/events/pool_create_event.rs @@ -0,0 +1,41 @@ +//! This code was AUTOGENERATED using the codama library. +//! Please DO NOT EDIT THIS FILE, instead use visitors +//! to add features, then rerun codama to update it. +//! +//! +//! + +use crate::generated::types::CurveParams; +use crate::generated::types::MintParams; +use crate::generated::types::VestingParams; +use borsh::BorshDeserialize; +use borsh::BorshSerialize; +use solana_address::Address; + +#[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] +pub struct PoolCreateEvent { + pub pool_state: Address, + pub creator: Address, + pub config: Address, + pub base_mint_param: MintParams, + pub curve_param: CurveParams, + pub vesting_param: VestingParams, +} + +pub const POOL_CREATE_EVENT_DISCRIMINATOR: [u8; 8] = [151, 215, 226, 9, 118, 161, 115, 174]; + +impl PoolCreateEvent { + #[inline(always)] + pub fn from_bytes(data: &[u8]) -> Result { + if data.get(..POOL_CREATE_EVENT_DISCRIMINATOR.len()) + != Some(&POOL_CREATE_EVENT_DISCRIMINATOR[..]) + { + return Err(std::io::Error::new( + std::io::ErrorKind::InvalidData, + "invalid event discriminator", + )); + } + let mut data = &data[POOL_CREATE_EVENT_DISCRIMINATOR.len()..]; + Self::deserialize(&mut data) + } +} diff --git a/e2e/raydium-launchpad/src/generated/events/raydium_launchpad_events.rs b/e2e/raydium-launchpad/src/generated/events/raydium_launchpad_events.rs new file mode 100644 index 0000000..b22f6a3 --- /dev/null +++ b/e2e/raydium-launchpad/src/generated/events/raydium_launchpad_events.rs @@ -0,0 +1,83 @@ +//! This code was AUTOGENERATED using the codama library. +//! Please DO NOT EDIT THIS FILE, instead use visitors +//! to add features, then rerun codama to update it. +//! +//! +//! + +use crate::generated::events::ClaimVestedEvent; +use crate::generated::events::CreateVestingEvent; +use crate::generated::events::PoolCreateEvent; +use crate::generated::events::TradeEvent; +use crate::generated::events::CLAIM_VESTED_EVENT_DISCRIMINATOR; +use crate::generated::events::CREATE_VESTING_EVENT_DISCRIMINATOR; +use crate::generated::events::POOL_CREATE_EVENT_DISCRIMINATOR; +use crate::generated::events::TRADE_EVENT_DISCRIMINATOR; +use borsh::BorshDeserialize; + +/// Event kinds for the `raydium_launchpad` program. +#[derive(Clone, Debug, Eq, PartialEq)] +pub enum RaydiumLaunchpadEventKind { + ClaimVestedEvent, + CreateVestingEvent, + PoolCreateEvent, + TradeEvent, +} + +/// Identifies a `raydium_launchpad` event from the provided data. +pub fn identify_raydium_launchpad_event(data: &[u8]) -> Option { + if data.get(..CLAIM_VESTED_EVENT_DISCRIMINATOR.len()) + == Some(&CLAIM_VESTED_EVENT_DISCRIMINATOR[..]) + { + return Some(RaydiumLaunchpadEventKind::ClaimVestedEvent); + } + if data.get(..CREATE_VESTING_EVENT_DISCRIMINATOR.len()) + == Some(&CREATE_VESTING_EVENT_DISCRIMINATOR[..]) + { + return Some(RaydiumLaunchpadEventKind::CreateVestingEvent); + } + if data.get(..POOL_CREATE_EVENT_DISCRIMINATOR.len()) + == Some(&POOL_CREATE_EVENT_DISCRIMINATOR[..]) + { + return Some(RaydiumLaunchpadEventKind::PoolCreateEvent); + } + if data.get(..TRADE_EVENT_DISCRIMINATOR.len()) == Some(&TRADE_EVENT_DISCRIMINATOR[..]) { + return Some(RaydiumLaunchpadEventKind::TradeEvent); + } + None +} + +/// Parsed event variants for the `raydium_launchpad` program. +#[derive(Clone, Debug, PartialEq)] +pub enum RaydiumLaunchpadEvent { + ClaimVestedEvent(ClaimVestedEvent), + CreateVestingEvent(CreateVestingEvent), + PoolCreateEvent(PoolCreateEvent), + TradeEvent(TradeEvent), +} + +/// Tries to parse a `raydium_launchpad` event from the provided data. +pub fn try_parse_raydium_launchpad_event( + data: &[u8], +) -> Option> { + let event_kind = identify_raydium_launchpad_event(data)?; + Some(match event_kind { + RaydiumLaunchpadEventKind::ClaimVestedEvent => { + let mut data = &data[CLAIM_VESTED_EVENT_DISCRIMINATOR.len()..]; + ClaimVestedEvent::deserialize(&mut data).map(RaydiumLaunchpadEvent::ClaimVestedEvent) + } + RaydiumLaunchpadEventKind::CreateVestingEvent => { + let mut data = &data[CREATE_VESTING_EVENT_DISCRIMINATOR.len()..]; + CreateVestingEvent::deserialize(&mut data) + .map(RaydiumLaunchpadEvent::CreateVestingEvent) + } + RaydiumLaunchpadEventKind::PoolCreateEvent => { + let mut data = &data[POOL_CREATE_EVENT_DISCRIMINATOR.len()..]; + PoolCreateEvent::deserialize(&mut data).map(RaydiumLaunchpadEvent::PoolCreateEvent) + } + RaydiumLaunchpadEventKind::TradeEvent => { + let mut data = &data[TRADE_EVENT_DISCRIMINATOR.len()..]; + TradeEvent::deserialize(&mut data).map(RaydiumLaunchpadEvent::TradeEvent) + } + }) +} diff --git a/e2e/raydium-launchpad/src/generated/events/trade_event.rs b/e2e/raydium-launchpad/src/generated/events/trade_event.rs new file mode 100644 index 0000000..bf5b813 --- /dev/null +++ b/e2e/raydium-launchpad/src/generated/events/trade_event.rs @@ -0,0 +1,47 @@ +//! This code was AUTOGENERATED using the codama library. +//! Please DO NOT EDIT THIS FILE, instead use visitors +//! to add features, then rerun codama to update it. +//! +//! +//! + +use crate::generated::types::PoolStatus; +use crate::generated::types::TradeDirection; +use borsh::BorshDeserialize; +use borsh::BorshSerialize; +use solana_address::Address; + +#[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] +pub struct TradeEvent { + pub pool_state: Address, + pub total_base_sell: u64, + pub virtual_base: u64, + pub virtual_quote: u64, + pub real_base_before: u64, + pub real_quote_before: u64, + pub real_base_after: u64, + pub real_quote_after: u64, + pub amount_in: u64, + pub amount_out: u64, + pub protocol_fee: u64, + pub platform_fee: u64, + pub share_fee: u64, + pub trade_direction: TradeDirection, + pub pool_status: PoolStatus, +} + +pub const TRADE_EVENT_DISCRIMINATOR: [u8; 8] = [189, 219, 127, 211, 78, 230, 97, 238]; + +impl TradeEvent { + #[inline(always)] + pub fn from_bytes(data: &[u8]) -> Result { + if data.get(..TRADE_EVENT_DISCRIMINATOR.len()) != Some(&TRADE_EVENT_DISCRIMINATOR[..]) { + return Err(std::io::Error::new( + std::io::ErrorKind::InvalidData, + "invalid event discriminator", + )); + } + let mut data = &data[TRADE_EVENT_DISCRIMINATOR.len()..]; + Self::deserialize(&mut data) + } +} diff --git a/e2e/raydium-launchpad/src/generated/mod.rs b/e2e/raydium-launchpad/src/generated/mod.rs index e0d740a..f3510ac 100644 --- a/e2e/raydium-launchpad/src/generated/mod.rs +++ b/e2e/raydium-launchpad/src/generated/mod.rs @@ -7,6 +7,7 @@ pub mod accounts; pub mod errors; +pub mod events; pub mod instructions; pub mod programs; pub mod shared; From a7183e523d1007e885ec57633644085a6cc04136 Mon Sep 17 00:00:00 2001 From: ioxde <228087182+ioxde@users.noreply.github.com> Date: Fri, 17 Apr 2026 11:09:24 -0700 Subject: [PATCH 06/24] Pin forked Codama packages to pkg.pr.new tarballs --- pnpm-lock.yaml | 179 +++++++++++++++++++++----------------------- pnpm-workspace.yaml | 14 ++++ 2 files changed, 101 insertions(+), 92 deletions(-) create mode 100644 pnpm-workspace.yaml diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 41dcce3..d6203ee 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -4,22 +4,32 @@ settings: autoInstallPeers: true excludeLinksFromLockfile: false +overrides: + '@codama/errors': https://pkg.pr.new/ioxde/codama/@codama/errors@963c0dbe9c2651348789fd8f583164d9b20619c1 + '@codama/node-types': https://pkg.pr.new/ioxde/codama/@codama/node-types@963c0dbe9c2651348789fd8f583164d9b20619c1 + '@codama/nodes': https://pkg.pr.new/ioxde/codama/@codama/nodes@963c0dbe9c2651348789fd8f583164d9b20619c1 + '@codama/nodes-from-anchor': https://pkg.pr.new/ioxde/codama/@codama/nodes-from-anchor@963c0dbe9c2651348789fd8f583164d9b20619c1 + '@codama/renderers-core': https://pkg.pr.new/ioxde/codama/@codama/renderers-core@963c0dbe9c2651348789fd8f583164d9b20619c1 + '@codama/visitors': https://pkg.pr.new/ioxde/codama/@codama/visitors@963c0dbe9c2651348789fd8f583164d9b20619c1 + '@codama/visitors-core': https://pkg.pr.new/ioxde/codama/@codama/visitors-core@963c0dbe9c2651348789fd8f583164d9b20619c1 + '@codama/validators': https://pkg.pr.new/ioxde/codama/@codama/validators@963c0dbe9c2651348789fd8f583164d9b20619c1 + importers: .: dependencies: '@codama/errors': - specifier: ^1.6.0 - version: 1.6.0 + specifier: https://pkg.pr.new/ioxde/codama/@codama/errors@963c0dbe9c2651348789fd8f583164d9b20619c1 + version: https://pkg.pr.new/ioxde/codama/@codama/errors@963c0dbe9c2651348789fd8f583164d9b20619c1 '@codama/nodes': - specifier: ^1.6.0 - version: 1.6.0 + specifier: https://pkg.pr.new/ioxde/codama/@codama/nodes@963c0dbe9c2651348789fd8f583164d9b20619c1 + version: https://pkg.pr.new/ioxde/codama/@codama/nodes@963c0dbe9c2651348789fd8f583164d9b20619c1 '@codama/renderers-core': - specifier: ^1.3.5 - version: 1.3.5 + specifier: https://pkg.pr.new/ioxde/codama/@codama/renderers-core@963c0dbe9c2651348789fd8f583164d9b20619c1 + version: https://pkg.pr.new/ioxde/codama/@codama/renderers-core@963c0dbe9c2651348789fd8f583164d9b20619c1 '@codama/visitors-core': - specifier: ^1.6.0 - version: 1.6.0 + specifier: https://pkg.pr.new/ioxde/codama/@codama/visitors-core@963c0dbe9c2651348789fd8f583164d9b20619c1 + version: https://pkg.pr.new/ioxde/codama/@codama/visitors-core@963c0dbe9c2651348789fd8f583164d9b20619c1 '@iarna/toml': specifier: ^2.2.5 version: 2.2.5 @@ -40,8 +50,8 @@ importers: specifier: ^2.29.7 version: 2.29.8(@types/node@25.2.3) '@codama/nodes-from-anchor': - specifier: ^1.4.1 - version: 1.4.1(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) + specifier: https://pkg.pr.new/ioxde/codama/@codama/nodes-from-anchor@963c0dbe9c2651348789fd8f583164d9b20619c1 + version: https://pkg.pr.new/ioxde/codama/@codama/nodes-from-anchor@963c0dbe9c2651348789fd8f583164d9b20619c1(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) '@solana/eslint-config-solana': specifier: ^5.0.0 version: 5.0.0(@eslint/js@9.39.1)(@types/eslint__js@8.42.3)(eslint-plugin-jest@29.0.1(@typescript-eslint/eslint-plugin@8.43.0(@typescript-eslint/parser@8.43.0(eslint@9.39.1)(typescript@5.9.3))(eslint@9.39.1)(typescript@5.9.3))(eslint@9.39.1)(jest@30.1.3(@types/node@25.2.3))(typescript@5.9.3))(eslint-plugin-react-hooks@5.2.0(eslint@9.39.1))(eslint-plugin-simple-import-sort@12.1.1(eslint@9.39.1))(eslint-plugin-sort-keys-fix@1.1.2)(eslint-plugin-typescript-sort-keys@3.3.0(@typescript-eslint/parser@8.43.0(eslint@9.39.1)(typescript@5.9.3))(eslint@9.39.1)(typescript@5.9.3))(eslint@9.39.1)(globals@14.0.0)(jest@30.1.3(@types/node@25.2.3))(typescript-eslint@8.43.0(eslint@9.39.1)(typescript@5.9.3))(typescript@5.9.3) @@ -314,40 +324,38 @@ packages: '@changesets/write@0.4.0': resolution: {integrity: sha512-CdTLvIOPiCNuH71pyDu3rA+Q0n65cmAbXnwWH84rKGiFumFzkmHNT8KHTMEchcxN+Kl8I54xGUhJ7l3E7X396Q==} - '@codama/errors@1.5.0': - resolution: {integrity: sha512-i4cS+S7JaZXhofQHFY3cwzt8rqxUVPNaeJND5VOyKUbtcOi933YXJXk52gDG4mc+CpGqHJijsJjfSpr1lJGxzg==} - hasBin: true - - '@codama/errors@1.6.0': - resolution: {integrity: sha512-Evj9wO5lqvxvbjxG856ITY5lhRN7SqoYfRX4tMMBjs8J/kT+pKQ8qL0hz9OynOOv/5mWn9Q/sPCNzQ6CUscibQ==} + '@codama/errors@https://pkg.pr.new/ioxde/codama/@codama/errors@963c0dbe9c2651348789fd8f583164d9b20619c1': + resolution: {tarball: https://pkg.pr.new/ioxde/codama/@codama/errors@963c0dbe9c2651348789fd8f583164d9b20619c1} + version: 1.7.0 hasBin: true - '@codama/node-types@1.5.0': - resolution: {integrity: sha512-Ebz2vOUukmNaFXWdkni1ZihXkAIUnPYtqIMXYxKXOxjMP+TGz2q0lGtRo7sqw1pc2ksFBIkfBp5pZsl5p6gwXA==} - - '@codama/node-types@1.6.0': - resolution: {integrity: sha512-atIJW2/3MjPYey0bNlE86W9Gvq9aq8bud7zT7PMyyhj98mbmLqPwT4wclPdbFua0fROLkq17z3bXaaJy5FqSEw==} + '@codama/fragments@https://pkg.pr.new/ioxde/codama/@codama/fragments@963c0db': + resolution: {tarball: https://pkg.pr.new/ioxde/codama/@codama/fragments@963c0db} + version: 0.1.0 - '@codama/nodes-from-anchor@1.4.1': - resolution: {integrity: sha512-2RuLk/pCn+KXYSZoSA1k/sP1C4VzlbNFtMu2AxiBMXyyR8WYKFkrRghjI4IR+otwhknV7QhdFr8h5tuD+TSQ4g==} + '@codama/node-types@https://pkg.pr.new/ioxde/codama/@codama/node-types@963c0dbe9c2651348789fd8f583164d9b20619c1': + resolution: {tarball: https://pkg.pr.new/ioxde/codama/@codama/node-types@963c0dbe9c2651348789fd8f583164d9b20619c1} + version: 1.7.0 - '@codama/nodes@1.5.0': - resolution: {integrity: sha512-yg+xmorWiMNjS3n19CGIt/FZ/ZCuDIu+HEY45bq6gHu1MN3RtJZY+Q3v0ErnBPA60D8mNWkvkKoeSZXfzcAvfw==} + '@codama/nodes-from-anchor@https://pkg.pr.new/ioxde/codama/@codama/nodes-from-anchor@963c0dbe9c2651348789fd8f583164d9b20619c1': + resolution: {tarball: https://pkg.pr.new/ioxde/codama/@codama/nodes-from-anchor@963c0dbe9c2651348789fd8f583164d9b20619c1} + version: 1.5.0 - '@codama/nodes@1.6.0': - resolution: {integrity: sha512-F6Hy3REfl+Ih5R3jldPqEMjFqaPj871iBWX/LV0EtNK0xn7E4DG/3XCK4wlbHrOT9Z1NsiA70e0M1uChzmIrsw==} + '@codama/nodes@https://pkg.pr.new/ioxde/codama/@codama/nodes@963c0dbe9c2651348789fd8f583164d9b20619c1': + resolution: {tarball: https://pkg.pr.new/ioxde/codama/@codama/nodes@963c0dbe9c2651348789fd8f583164d9b20619c1} + version: 1.7.0 - '@codama/renderers-core@1.3.5': - resolution: {integrity: sha512-MuZLU+3LZPQb1HuZffwZl+v5JHQDe5LYHGhA1wTMNlwRedYIysSxBjogHNciNIHsKP3JjmqyYmLO5LCEp3hjaQ==} + '@codama/renderers-core@https://pkg.pr.new/ioxde/codama/@codama/renderers-core@963c0dbe9c2651348789fd8f583164d9b20619c1': + resolution: {tarball: https://pkg.pr.new/ioxde/codama/@codama/renderers-core@963c0dbe9c2651348789fd8f583164d9b20619c1} + version: 1.3.8 - '@codama/visitors-core@1.5.0': - resolution: {integrity: sha512-3PIAlBX0a06hIxzyPtQMfQcqWGFBgfbwysSwcXBbvHUYbemwhD6xwlBKJuqTwm9DyFj3faStp5fpvcp03Rjxtw==} + '@codama/visitors-core@https://pkg.pr.new/ioxde/codama/@codama/visitors-core@963c0dbe9c2651348789fd8f583164d9b20619c1': + resolution: {tarball: https://pkg.pr.new/ioxde/codama/@codama/visitors-core@963c0dbe9c2651348789fd8f583164d9b20619c1} + version: 1.7.0 - '@codama/visitors-core@1.6.0': - resolution: {integrity: sha512-YG0rExvLbBCDAzXnZX6Imu4KwDoZrZz9NF232/nzs9Dr8uQuEWJ81x4VR9UxIcANHcF0+XwJzHamSwhZroAtjQ==} - - '@codama/visitors@1.6.0': - resolution: {integrity: sha512-11/adC2WiH3+iMWluXkb+ae46sjoDm2xztI+CBEeIcBQd6mm4iuJTTRS0yrGfDwAJE1XzI/nc2MrR0Pvn+Rvvw==} + '@codama/visitors@https://pkg.pr.new/ioxde/codama/@codama/visitors@963c0dbe9c2651348789fd8f583164d9b20619c1': + resolution: {tarball: https://pkg.pr.new/ioxde/codama/@codama/visitors@963c0dbe9c2651348789fd8f583164d9b20619c1} + version: 1.7.0 '@emnapi/core@1.7.1': resolution: {integrity: sha512-o1uhUASyo921r2XtHYOHy7gdkGLge8ghBEQHMWmyJFoXlpU58kIrhhN3w26lpQb6dspetweapMn2CSNwQ8I4wg==} @@ -863,8 +871,8 @@ packages: '@napi-rs/wasm-runtime@0.2.12': resolution: {integrity: sha512-ZVWUcfwY4E/yPitQJl481FjFo3K22D6qF0DuFH6Y/nbnE11GY5uguDxZMGXPQ8WQ0128MXQD7TnfHyK4oWoIJQ==} - '@noble/hashes@2.0.1': - resolution: {integrity: sha512-XlOlEbQcE9fmuXxrVTXCTlG2nlRXa9Rj3rr5Ue/+tX+nmkgbX720YHh0VR3hBF9xDvwnb8D2shVGOwNx+ulArw==} + '@noble/hashes@2.2.0': + resolution: {integrity: sha512-IYqDGiTXab6FniAgnSdZwgWbomxpy9FtYvLKs7wCUs2a8RkITG+DFGO1DM9cr+E3/RgADRpFjrKVaJ1z6sjtEg==} engines: {node: '>= 20.19.0'} '@nodelib/fs.scandir@2.1.5': @@ -1456,6 +1464,7 @@ packages: '@ungap/structured-clone@1.3.0': resolution: {integrity: sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==} + deprecated: Potential CWE-502 - Update to 1.3.1 or higher '@unrs/resolver-binding-android-arm-eabi@1.11.1': resolution: {integrity: sha512-ppLRUgHVaGRWUx0R0Ut06Mjo9gBaBkg3v/8AxusGLhsIotbBLuRk51rAzqLC8gq6NyyAojEXglNjzf6R948DNw==} @@ -1729,8 +1738,8 @@ packages: resolution: {integrity: sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==} engines: {node: '>= 0.4'} - call-bind@1.0.8: - resolution: {integrity: sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww==} + call-bind@1.0.9: + resolution: {integrity: sha512-a/hy+pNsFUTR+Iz8TCJvXudKVLAnz/DyeSUo10I5yvFDQJBFU2s9uqQpoSrJlroHUKoKqzg+epxyP9lqFdzfBQ==} engines: {node: '>= 0.4'} call-bound@1.0.4: @@ -1922,8 +1931,8 @@ packages: es-module-lexer@1.7.0: resolution: {integrity: sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==} - es-object-atoms@1.1.1: - resolution: {integrity: sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==} + es-object-atoms@1.1.2: + resolution: {integrity: sha512-HWcBoN6NileqtSydK2FqHbS/LoDd2pqrnQHLyJzBj4kOp/ky2MWMN694xOfkK8/SnUsW2DH7EfyVlydKCsm1Zw==} engines: {node: '>= 0.4'} esbuild@0.25.12: @@ -2226,8 +2235,8 @@ packages: resolution: {integrity: sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==} engines: {node: '>= 0.4'} - hasown@2.0.2: - resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} + hasown@2.0.4: + resolution: {integrity: sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A==} engines: {node: '>= 0.4'} html-escaper@2.0.2: @@ -3647,66 +3656,52 @@ snapshots: human-id: 4.1.3 prettier: 2.8.8 - '@codama/errors@1.5.0': + '@codama/errors@https://pkg.pr.new/ioxde/codama/@codama/errors@963c0dbe9c2651348789fd8f583164d9b20619c1': dependencies: - '@codama/node-types': 1.5.0 - commander: 14.0.2 - picocolors: 1.1.1 - - '@codama/errors@1.6.0': - dependencies: - '@codama/node-types': 1.6.0 + '@codama/node-types': https://pkg.pr.new/ioxde/codama/@codama/node-types@963c0dbe9c2651348789fd8f583164d9b20619c1 commander: 14.0.3 picocolors: 1.1.1 - '@codama/node-types@1.5.0': {} + '@codama/fragments@https://pkg.pr.new/ioxde/codama/@codama/fragments@963c0db': + dependencies: + '@codama/errors': https://pkg.pr.new/ioxde/codama/@codama/errors@963c0dbe9c2651348789fd8f583164d9b20619c1 - '@codama/node-types@1.6.0': {} + '@codama/node-types@https://pkg.pr.new/ioxde/codama/@codama/node-types@963c0dbe9c2651348789fd8f583164d9b20619c1': {} - '@codama/nodes-from-anchor@1.4.1(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)': + '@codama/nodes-from-anchor@https://pkg.pr.new/ioxde/codama/@codama/nodes-from-anchor@963c0dbe9c2651348789fd8f583164d9b20619c1(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)': dependencies: - '@codama/errors': 1.6.0 - '@codama/nodes': 1.6.0 - '@codama/visitors': 1.6.0 - '@noble/hashes': 2.0.1 + '@codama/errors': https://pkg.pr.new/ioxde/codama/@codama/errors@963c0dbe9c2651348789fd8f583164d9b20619c1 + '@codama/nodes': https://pkg.pr.new/ioxde/codama/@codama/nodes@963c0dbe9c2651348789fd8f583164d9b20619c1 + '@codama/visitors': https://pkg.pr.new/ioxde/codama/@codama/visitors@963c0dbe9c2651348789fd8f583164d9b20619c1 + '@noble/hashes': 2.2.0 '@solana/codecs': 5.5.1(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) transitivePeerDependencies: - fastestsmallesttextencoderdecoder - typescript - '@codama/nodes@1.5.0': - dependencies: - '@codama/errors': 1.5.0 - '@codama/node-types': 1.5.0 - - '@codama/nodes@1.6.0': + '@codama/nodes@https://pkg.pr.new/ioxde/codama/@codama/nodes@963c0dbe9c2651348789fd8f583164d9b20619c1': dependencies: - '@codama/errors': 1.6.0 - '@codama/node-types': 1.6.0 + '@codama/errors': https://pkg.pr.new/ioxde/codama/@codama/errors@963c0dbe9c2651348789fd8f583164d9b20619c1 + '@codama/node-types': https://pkg.pr.new/ioxde/codama/@codama/node-types@963c0dbe9c2651348789fd8f583164d9b20619c1 - '@codama/renderers-core@1.3.5': + '@codama/renderers-core@https://pkg.pr.new/ioxde/codama/@codama/renderers-core@963c0dbe9c2651348789fd8f583164d9b20619c1': dependencies: - '@codama/errors': 1.5.0 - '@codama/nodes': 1.5.0 - '@codama/visitors-core': 1.5.0 - - '@codama/visitors-core@1.5.0': - dependencies: - '@codama/errors': 1.5.0 - '@codama/nodes': 1.5.0 - json-stable-stringify: 1.3.0 + '@codama/errors': https://pkg.pr.new/ioxde/codama/@codama/errors@963c0dbe9c2651348789fd8f583164d9b20619c1 + '@codama/fragments': https://pkg.pr.new/ioxde/codama/@codama/fragments@963c0db + '@codama/nodes': https://pkg.pr.new/ioxde/codama/@codama/nodes@963c0dbe9c2651348789fd8f583164d9b20619c1 + '@codama/visitors-core': https://pkg.pr.new/ioxde/codama/@codama/visitors-core@963c0dbe9c2651348789fd8f583164d9b20619c1 - '@codama/visitors-core@1.6.0': + '@codama/visitors-core@https://pkg.pr.new/ioxde/codama/@codama/visitors-core@963c0dbe9c2651348789fd8f583164d9b20619c1': dependencies: - '@codama/errors': 1.6.0 - '@codama/nodes': 1.6.0 + '@codama/errors': https://pkg.pr.new/ioxde/codama/@codama/errors@963c0dbe9c2651348789fd8f583164d9b20619c1 + '@codama/nodes': https://pkg.pr.new/ioxde/codama/@codama/nodes@963c0dbe9c2651348789fd8f583164d9b20619c1 json-stable-stringify: 1.3.0 - '@codama/visitors@1.6.0': + '@codama/visitors@https://pkg.pr.new/ioxde/codama/@codama/visitors@963c0dbe9c2651348789fd8f583164d9b20619c1': dependencies: - '@codama/errors': 1.6.0 - '@codama/nodes': 1.6.0 - '@codama/visitors-core': 1.6.0 + '@codama/errors': https://pkg.pr.new/ioxde/codama/@codama/errors@963c0dbe9c2651348789fd8f583164d9b20619c1 + '@codama/nodes': https://pkg.pr.new/ioxde/codama/@codama/nodes@963c0dbe9c2651348789fd8f583164d9b20619c1 + '@codama/visitors-core': https://pkg.pr.new/ioxde/codama/@codama/visitors-core@963c0dbe9c2651348789fd8f583164d9b20619c1 '@emnapi/core@1.7.1': dependencies: @@ -4192,7 +4187,7 @@ snapshots: '@tybys/wasm-util': 0.10.1 optional: true - '@noble/hashes@2.0.1': {} + '@noble/hashes@2.2.0': {} '@nodelib/fs.scandir@2.1.5': dependencies: @@ -5006,7 +5001,7 @@ snapshots: es-errors: 1.3.0 function-bind: 1.1.2 - call-bind@1.0.8: + call-bind@1.0.9: dependencies: call-bind-apply-helpers: 1.0.2 es-define-property: 1.0.1 @@ -5146,7 +5141,7 @@ snapshots: es-module-lexer@1.7.0: {} - es-object-atoms@1.1.1: + es-object-atoms@1.1.2: dependencies: es-errors: 1.3.0 @@ -5458,12 +5453,12 @@ snapshots: call-bind-apply-helpers: 1.0.2 es-define-property: 1.0.1 es-errors: 1.3.0 - es-object-atoms: 1.1.1 + es-object-atoms: 1.1.2 function-bind: 1.1.2 get-proto: 1.0.1 gopd: 1.2.0 has-symbols: 1.1.0 - hasown: 2.0.2 + hasown: 2.0.4 math-intrinsics: 1.1.0 get-package-type@0.1.0: {} @@ -5471,7 +5466,7 @@ snapshots: get-proto@1.0.1: dependencies: dunder-proto: 1.0.1 - es-object-atoms: 1.1.1 + es-object-atoms: 1.1.2 get-stream@6.0.1: {} @@ -5538,7 +5533,7 @@ snapshots: has-symbols@1.1.0: {} - hasown@2.0.2: + hasown@2.0.4: dependencies: function-bind: 1.1.2 @@ -5980,7 +5975,7 @@ snapshots: json-stable-stringify@1.3.0: dependencies: - call-bind: 1.0.8 + call-bind: 1.0.9 call-bound: 1.0.4 isarray: 2.0.5 jsonify: 0.0.1 diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml new file mode 100644 index 0000000..f76cf52 --- /dev/null +++ b/pnpm-workspace.yaml @@ -0,0 +1,14 @@ +# Forked codama packages, served as prebuilt tarballs by pkg.pr.new +# (producer: ioxde/codama .github/workflows/main.yml `publish-preview` job). +# Pinned to ioxde/codama@963c0db (main). workspace:* deps are rewritten by +# pkg.pr.new at publish time, so installing these resolves the whole fork set. +# These are overrides only — not part of the published @codama/renderers-rust. +overrides: + '@codama/errors': 'https://pkg.pr.new/ioxde/codama/@codama/errors@963c0dbe9c2651348789fd8f583164d9b20619c1' + '@codama/node-types': 'https://pkg.pr.new/ioxde/codama/@codama/node-types@963c0dbe9c2651348789fd8f583164d9b20619c1' + '@codama/nodes': 'https://pkg.pr.new/ioxde/codama/@codama/nodes@963c0dbe9c2651348789fd8f583164d9b20619c1' + '@codama/nodes-from-anchor': 'https://pkg.pr.new/ioxde/codama/@codama/nodes-from-anchor@963c0dbe9c2651348789fd8f583164d9b20619c1' + '@codama/renderers-core': 'https://pkg.pr.new/ioxde/codama/@codama/renderers-core@963c0dbe9c2651348789fd8f583164d9b20619c1' + '@codama/visitors': 'https://pkg.pr.new/ioxde/codama/@codama/visitors@963c0dbe9c2651348789fd8f583164d9b20619c1' + '@codama/visitors-core': 'https://pkg.pr.new/ioxde/codama/@codama/visitors-core@963c0dbe9c2651348789fd8f583164d9b20619c1' + '@codama/validators': 'https://pkg.pr.new/ioxde/codama/@codama/validators@963c0dbe9c2651348789fd8f583164d9b20619c1' From 354a913794edf194ca42ac2e2ccf093373f76d7e Mon Sep 17 00:00:00 2001 From: ioxde <228087182+ioxde@users.noreply.github.com> Date: Wed, 29 Apr 2026 15:36:24 -0700 Subject: [PATCH 07/24] Support Anchor CPI event framing in event codegen --- .changeset/anchor-cpi-event-framing.md | 5 + public/templates/programEventsPage.njk | 6 + src/getRenderMapVisitor.ts | 136 +++++++++++++++-- test/eventsPage.test.ts | 197 ++++++++++++++++++++++++- 4 files changed, 329 insertions(+), 15 deletions(-) create mode 100644 .changeset/anchor-cpi-event-framing.md diff --git a/.changeset/anchor-cpi-event-framing.md b/.changeset/anchor-cpi-event-framing.md new file mode 100644 index 0000000..92d976d --- /dev/null +++ b/.changeset/anchor-cpi-event-framing.md @@ -0,0 +1,5 @@ +--- +'@codama/renderers-rust': minor +--- + +Support Anchor CPI event framing in event codegen diff --git a/public/templates/programEventsPage.njk b/public/templates/programEventsPage.njk index 71a15fa..99d8bc6 100644 --- a/public/templates/programEventsPage.njk +++ b/public/templates/programEventsPage.njk @@ -4,6 +4,12 @@ {{ imports }} +{% if eventFramingBytes and eventFramingName %} +/// Shared event-framing tag prepended to every framed event emitted by the +/// `{{ program.name | snakeCase }}` program. +pub const {{ eventFramingName }}: [u8; {{ eventFramingBytes.len }}] = {{ eventFramingBytes.literal }}; + +{% endif %} /// Event kinds for the `{{ program.name | snakeCase }}` program. #[derive(Clone, Debug, Eq, PartialEq)] pub enum {{ program.name | pascalCase }}EventKind { diff --git a/src/getRenderMapVisitor.ts b/src/getRenderMapVisitor.ts index 21c6a3e..0373655 100644 --- a/src/getRenderMapVisitor.ts +++ b/src/getRenderMapVisitor.ts @@ -1,6 +1,8 @@ import { logWarn } from '@codama/errors'; import { + ConstantValueNode, definedTypeNode, + EventFraming, EventNode, getAllAccounts, getAllDefinedTypes, @@ -60,6 +62,7 @@ export function getRenderMapVisitor(options: GetRenderMapOptions = {}) { const linkables = new LinkableDictionary(); const stack = new NodeStack(); let program: ProgramNode | null = null; + let programEventFraming: ResolvedProgramEventFraming | undefined = undefined; const programsWithEventEnum = new Set(); const renderParentInstructions = options.renderParentInstructions ?? false; @@ -156,7 +159,13 @@ export function getRenderMapVisitor(options: GetRenderMapOptions = {}) { }, visitEvent(node) { - const discriminators = node.discriminators ?? []; + const allDiscriminators = node.discriminators ?? []; + const isCpiFramed = isEventCpiFramed(node, programEventFraming); + const framingConstantName = isCpiFramed + ? snakeCase(programEventFraming!.framing.sharedConstantName).toUpperCase() + : null; + // Strip the hoisted framing constant so per-event _DISCRIMINATOR matches IDL events[].discriminator bytes. + const discriminators = isCpiFramed ? allDiscriminators.slice(1) : allDiscriminators; const innerType = resolveNestedTypeNode(node.data); // Wrap as definedTypeNode so typeManifestVisitor generates the struct with derives. const syntheticType = definedTypeNode({ @@ -166,7 +175,7 @@ export function getRenderMapVisitor(options: GetRenderMapOptions = {}) { }); const typeManifest = visit(syntheticType, typeManifestVisitor); - // Discriminator constants. + // Discriminator constants (excluding the hoisted framing one for CPI-framed events). const fields = isNode(innerType, 'structTypeNode') ? innerType.fields : []; const discriminatorConstants = getDiscriminatorConstants({ discriminatorNodes: discriminators, @@ -177,7 +186,7 @@ export function getRenderMapVisitor(options: GetRenderMapOptions = {}) { }); const hasFromBytes = eventHasFromBytes(node); - const allConstantDiscriminators = hasFromBytes + const perEventConstantDiscriminators = hasFromBytes ? discriminators .filter(isNodeFilter('constantDiscriminatorNode')) .map(d => ({ @@ -189,8 +198,15 @@ export function getRenderMapVisitor(options: GetRenderMapOptions = {}) { .sort((a, b) => a.offset - b.offset) : []; + const allConstantDiscriminators = + isCpiFramed && framingConstantName + ? [{ name: framingConstantName, offset: 0 }, ...perEventConstantDiscriminators] + : perEventConstantDiscriminators; + const hiddenPrefixSkipResult = hasFromBytes - ? getHiddenPrefixSkip(node, allConstantDiscriminators) + ? isCpiFramed + ? getCpiFramedSkip(allConstantDiscriminators) + : getHiddenPrefixSkip(node, allConstantDiscriminators) : null; const generateFromBytes = hasFromBytes && hiddenPrefixSkipResult !== null; const hiddenPrefixSkip = hiddenPrefixSkipResult ?? '0'; @@ -200,6 +216,9 @@ export function getRenderMapVisitor(options: GetRenderMapOptions = {}) { .mergeWithManifest(typeManifest) .mergeWith(discriminatorConstants.imports) .remove(`generatedEvents::${pascalCase(node.name)}`); + if (framingConstantName) { + imports.add(`generatedEvents::${framingConstantName}`); + } return createRenderMap(`events/${snakeCase(node.name)}.rs`, { content: render('eventsPage.njk', { @@ -323,6 +342,7 @@ export function getRenderMapVisitor(options: GetRenderMapOptions = {}) { visitProgram(node, { self }) { program = node; + programEventFraming = deriveProgramEventFraming(node); let renders = mergeRenderMaps([ ...node.accounts.map(account => visit(account, self)), ...node.definedTypes.map(type => visit(type, self)), @@ -348,6 +368,7 @@ export function getRenderMapVisitor(options: GetRenderMapOptions = {}) { const programEventsRender = buildProgramEventsRender( node.events ?? [], node, + programEventFraming, getImportFrom, typeManifestVisitor, dependencyMap, @@ -362,6 +383,7 @@ export function getRenderMapVisitor(options: GetRenderMapOptions = {}) { } program = null; + programEventFraming = undefined; return renders; }, @@ -470,9 +492,65 @@ function getHiddenPrefixSkip( return String(prefixSize); } +/** Resolved program-level framing: the hoisted prefix constant + its source EventFraming. */ +type ResolvedProgramEventFraming = { constant: ConstantValueNode; framing: EventFraming }; + +function deriveProgramEventFraming(programNode: ProgramNode | null): ResolvedProgramEventFraming | undefined { + if (!programNode) return undefined; + let resolved: ResolvedProgramEventFraming | undefined; + for (const event of programNode.events ?? []) { + if (!event.framing) continue; + if (!isNode(event.data, 'hiddenPrefixTypeNode')) continue; + if (event.data.prefix.length === 0) continue; + if (!resolved) { + resolved = { constant: event.data.prefix[0], framing: event.framing }; + continue; + } + if (resolved.framing.sharedConstantName !== event.framing.sharedConstantName) { + logWarn( + `[Rust] Program [${programNode.name}] has events with conflicting event framings ` + + `('${resolved.framing.sharedConstantName}' vs '${event.framing.sharedConstantName}'). ` + + `Only the first will be hoisted.`, + ); + break; + } + } + return resolved; +} + +function isEventCpiFramed(event: EventNode, programEventFraming: ResolvedProgramEventFraming | undefined): boolean { + if (programEventFraming === undefined) return false; + if (!event.framing) return false; + if (event.framing.sharedConstantName !== programEventFraming.framing.sharedConstantName) return false; + if (!isNode(event.data, 'hiddenPrefixTypeNode')) return false; + return event.data.prefix.length > 0; +} + +function getCpiFramedSkip(constantDiscriminators: { name: string; offset: number }[]): string { + // Sorted by offset; skip past every leading constant discriminator. + return constantDiscriminators.map(d => `${d.name}.len()`).join(' + '); +} + +/** Renders a fixed-size bytes ConstantValueNode as a Rust `[u8; N] = [b0, b1, ...]` array literal. */ +function renderConstantBytesArray(constant: ConstantValueNode): { len: number; literal: string } | null { + if (!isNode(constant.type, 'fixedSizeTypeNode')) return null; + if (!isNode(constant.value, 'bytesValueNode')) return null; + const size = constant.type.size; + const bytes: number[] = []; + const hex = constant.value.encoding === 'base16' ? constant.value.data.toLowerCase() : null; + if (hex === null || hex.length !== size * 2) return null; + for (let i = 0; i < size; i++) { + const byte = parseInt(hex.slice(i * 2, i * 2 + 2), 16); + if (Number.isNaN(byte)) return null; + bytes.push(byte); + } + return { len: size, literal: `[${bytes.join(', ')}]` }; +} + function buildProgramEventsRender( events: EventNode[], programNode: ProgramNode, + programEventFraming: ResolvedProgramEventFraming | undefined, getImportFrom: GetImportFromFunction, typeManifestVisitor: ReturnType, dependencyMap: Record, @@ -482,28 +560,50 @@ function buildProgramEventsRender( } const imports = new ImportMap(); + const framingConstantName = programEventFraming + ? snakeCase(programEventFraming.framing.sharedConstantName).toUpperCase() + : null; const eventsWithDiscriminators = events .filter(event => (event.discriminators ?? []).length > 0) .flatMap(event => { + const isCpiFramed = isEventCpiFramed(event, programEventFraming); + const allDiscriminators = event.discriminators ?? []; + // For CPI-framed events, strip the leading framing discriminator — it's hoisted to the + // program-level shared constant and prepended manually below. + const perEventDiscriminators = isCpiFramed ? allDiscriminators.slice(1) : allDiscriminators; const innerType = resolveNestedTypeNode(event.data); const fields = isNode(innerType, 'structTypeNode') ? innerType.fields : []; - const { conditions, imports: condImports } = getDiscriminatorConditions({ - discriminatorNodes: event.discriminators ?? [], + const { conditions: perEventConditions, imports: condImports } = getDiscriminatorConditions({ + discriminatorNodes: perEventDiscriminators, fields, getImportFrom, importPrefix: 'generatedEvents', prefix: event.name, typeManifestVisitor, }); - const discriminators = event.discriminators ?? []; - const eventConstantDiscs = discriminators.filter(isNodeFilter('constantDiscriminatorNode')).map(d => ({ - name: snakeCase(constantDiscriminatorName(event.name, d, discriminators)).toUpperCase(), - offset: d.offset, - })); - const hiddenPrefixSkipResult = isNode(event.data, 'hiddenPrefixTypeNode') - ? getHiddenPrefixSkip(event, eventConstantDiscs) - : '0'; + const perEventConstantDiscs = perEventDiscriminators + .filter(isNodeFilter('constantDiscriminatorNode')) + .map(d => ({ + name: snakeCase(constantDiscriminatorName(event.name, d, perEventDiscriminators)).toUpperCase(), + offset: d.offset, + })); + + let conditions: string[]; + let hiddenPrefixSkipResult: string | null; + if (isCpiFramed && framingConstantName) { + conditions = [ + `data.get(..${framingConstantName}.len()) == Some(&${framingConstantName}[..])`, + ...perEventConditions, + ]; + const allConstantDiscs = [{ name: framingConstantName, offset: 0 }, ...perEventConstantDiscs]; + hiddenPrefixSkipResult = getCpiFramedSkip(allConstantDiscs); + } else { + conditions = perEventConditions; + hiddenPrefixSkipResult = isNode(event.data, 'hiddenPrefixTypeNode') + ? getHiddenPrefixSkip(event, perEventConstantDiscs) + : '0'; + } if (hiddenPrefixSkipResult === null || conditions.length === 0) { return []; @@ -522,8 +622,16 @@ function buildProgramEventsRender( imports.add(`generatedEvents::${pascalCase(event.name)}`); }); + const anyCpiFramed = eventsWithDiscriminators.some(event => isEventCpiFramed(event, programEventFraming)); + const eventFramingBytes = + anyCpiFramed && programEventFraming !== undefined + ? renderConstantBytesArray(programEventFraming.constant) + : null; + return { content: render('programEventsPage.njk', { + eventFramingBytes, + eventFramingName: anyCpiFramed ? framingConstantName : null, eventsWithDiscriminators, imports: imports.toString(dependencyMap), program: programNode, diff --git a/test/eventsPage.test.ts b/test/eventsPage.test.ts index 0de92bd..6dc916d 100644 --- a/test/eventsPage.test.ts +++ b/test/eventsPage.test.ts @@ -3,6 +3,7 @@ import { arrayValueNode, bytesTypeNode, bytesValueNode, + CamelCaseString, constantDiscriminatorNode, constantValueNode, eventNode, @@ -20,7 +21,7 @@ import { } from '@codama/nodes'; import { getFromRenderMap } from '@codama/renderers-core'; import { visit } from '@codama/visitors-core'; -import { expect, test } from 'vitest'; +import { expect, test, vi } from 'vitest'; import { getRenderMapVisitor } from '../src'; import { codeContains, codeDoesNotContains } from './_setup'; @@ -800,3 +801,197 @@ test('it handles multiple constant discriminators and excludes events with unres codeContains(code, ['pub enum MyProgramEventKind']); codeDoesNotContains(code, ['NoDefaultEvent']); }); + +// --- Event framing (CPI-framed) tests --- + +const cpiFraming = { kind: 'anchorEventCpi', sharedConstantName: 'eventCpiPrefix' as CamelCaseString }; +const framingPrefix = constantValueNode( + fixedSizeTypeNode(bytesTypeNode(), 8), + bytesValueNode('base16', 'aabbccdd11223344'), +); +const tradeDisc = constantValueNode( + fixedSizeTypeNode(bytesTypeNode(), 8), + bytesValueNode('base16', '1122334455667788'), +); +const settleDisc = constantValueNode( + fixedSizeTypeNode(bytesTypeNode(), 8), + bytesValueNode('base16', '99aabbccddeeff00'), +); + +function framedEvent(name: string, eventDisc: ReturnType) { + return eventNode({ + data: hiddenPrefixTypeNode( + structTypeNode([structFieldTypeNode({ name: 'amount', type: numberTypeNode('u64') })]), + [framingPrefix, eventDisc], + ), + discriminators: [constantDiscriminatorNode(framingPrefix, 0), constantDiscriminatorNode(eventDisc, 8)], + framing: cpiFraming, + name, + }); +} + +test('it hoists the shared framing constant to the program-events file', () => { + const node = programNode({ + events: [framedEvent('tradeEvent', tradeDisc), framedEvent('settleEvent', settleDisc)], + name: 'myProgram', + publicKey: '11111111111111111111111111111111', + }); + + const renderMap = visit(node, getRenderMapVisitor()); + const programEventsCode = getFromRenderMap(renderMap, 'events/my_program_events.rs').content; + + codeContains(programEventsCode, [ + 'pub const EVENT_CPI_PREFIX: [u8; 8] = [170, 187, 204, 221, 17, 34, 51, 68];', + 'data.get(..EVENT_CPI_PREFIX.len()) == Some(&EVENT_CPI_PREFIX[..])', + 'return Some(MyProgramEventKind::TradeEvent)', + 'return Some(MyProgramEventKind::SettleEvent)', + ]); + expect(programEventsCode.match(/pub const EVENT_CPI_PREFIX/g)).toHaveLength(1); +}); + +test('it renders per-event _DISCRIMINATOR with IDL bytes, not framing bytes', () => { + const node = programNode({ + events: [framedEvent('tradeEvent', tradeDisc)], + name: 'myProgram', + publicKey: '11111111111111111111111111111111', + }); + + const renderMap = visit(node, getRenderMapVisitor()); + const tradeEventCode = getFromRenderMap(renderMap, 'events/trade_event.rs').content; + + codeContains(tradeEventCode, ['TRADE_EVENT_DISCRIMINATOR: [u8; 8] = [17, 34, 51, 68, 85, 102, 119, 136]']); + codeDoesNotContains(tradeEventCode, ['[170, 187, 204, 221, 17, 34, 51, 68]', 'pub const EVENT_CPI_PREFIX']); +}); + +test('it generates from_bytes that validates both the framing prefix and the event-specific discriminator', () => { + const node = programNode({ + events: [framedEvent('tradeEvent', tradeDisc)], + name: 'myProgram', + publicKey: '11111111111111111111111111111111', + }); + + const renderMap = visit(node, getRenderMapVisitor()); + const tradeEventCode = getFromRenderMap(renderMap, 'events/trade_event.rs').content; + + codeContains(tradeEventCode, [ + 'pub fn from_bytes', + 'data.get(..EVENT_CPI_PREFIX.len()) != Some(&EVENT_CPI_PREFIX[..])', + 'data.get(8..8 + TRADE_EVENT_DISCRIMINATOR.len()) != Some(&TRADE_EVENT_DISCRIMINATOR[..])', + 'let mut data = &data[EVENT_CPI_PREFIX.len() + TRADE_EVENT_DISCRIMINATOR.len()..];', + 'Self::deserialize(&mut data)', + ]); +}); + +test('it references the hoisted framing constant in identify and try_parse', () => { + const node = programNode({ + events: [framedEvent('tradeEvent', tradeDisc), framedEvent('settleEvent', settleDisc)], + name: 'myProgram', + publicKey: '11111111111111111111111111111111', + }); + + const renderMap = visit(node, getRenderMapVisitor()); + const programEventsCode = getFromRenderMap(renderMap, 'events/my_program_events.rs').content; + + codeContains(programEventsCode, [ + 'pub fn identify_my_program_event', + 'data.get(..EVENT_CPI_PREFIX.len()) == Some(&EVENT_CPI_PREFIX[..])', + '&& data.get(8..8 + TRADE_EVENT_DISCRIMINATOR.len()) == Some(&TRADE_EVENT_DISCRIMINATOR[..])', + '&& data.get(8..8 + SETTLE_EVENT_DISCRIMINATOR.len()) == Some(&SETTLE_EVENT_DISCRIMINATOR[..])', + 'pub fn try_parse_my_program_event', + 'let mut data = &data[EVENT_CPI_PREFIX.len() + TRADE_EVENT_DISCRIMINATOR.len()..]', + 'let mut data = &data[EVENT_CPI_PREFIX.len() + SETTLE_EVENT_DISCRIMINATOR.len()..]', + ]); +}); + +test('it does not hoist a shared constant when no event has framing', () => { + const node = programNode({ + events: [ + eventNode({ + data: hiddenPrefixTypeNode( + structTypeNode([structFieldTypeNode({ name: 'amount', type: numberTypeNode('u64') })]), + [framingPrefix], + ), + discriminators: [constantDiscriminatorNode(framingPrefix, 0)], + name: 'plainEvent', + }), + ], + name: 'myProgram', + publicKey: '11111111111111111111111111111111', + }); + + const renderMap = visit(node, getRenderMapVisitor()); + const programEventsCode = getFromRenderMap(renderMap, 'events/my_program_events.rs').content; + const plainEventCode = getFromRenderMap(renderMap, 'events/plain_event.rs').content; + + codeDoesNotContains(programEventsCode, ['EVENT_CPI_PREFIX']); + codeDoesNotContains(plainEventCode, ['EVENT_CPI_PREFIX']); + codeContains(plainEventCode, ['PLAIN_EVENT_DISCRIMINATOR: [u8; 8] = [170, 187, 204, 221, 17, 34, 51, 68]']); +}); + +test('it renders framed and non-framed events side-by-side without cross-contamination', () => { + const node = programNode({ + events: [ + framedEvent('tradeEvent', tradeDisc), + eventNode({ + data: structTypeNode([structFieldTypeNode({ name: 'value', type: numberTypeNode('u32') })]), + discriminators: [constantDiscriminatorNode(settleDisc, 0)], + name: 'plainEvent', + }), + ], + name: 'myProgram', + publicKey: '11111111111111111111111111111111', + }); + + const renderMap = visit(node, getRenderMapVisitor()); + const tradeEventCode = getFromRenderMap(renderMap, 'events/trade_event.rs').content; + const plainEventCode = getFromRenderMap(renderMap, 'events/plain_event.rs').content; + const programEventsCode = getFromRenderMap(renderMap, 'events/my_program_events.rs').content; + + codeContains(tradeEventCode, [ + 'use crate::generated::events::EVENT_CPI_PREFIX;', + 'data.get(..EVENT_CPI_PREFIX.len()) != Some(&EVENT_CPI_PREFIX[..])', + ]); + codeDoesNotContains(plainEventCode, ['EVENT_CPI_PREFIX']); + codeContains(programEventsCode, [ + 'pub const EVENT_CPI_PREFIX: [u8; 8] = [170, 187, 204, 221, 17, 34, 51, 68];', + 'return Some(MyProgramEventKind::TradeEvent)', + 'return Some(MyProgramEventKind::PlainEvent)', + ]); +}); + +test('it warns and hoists only the first framing when events have conflicting sharedConstantName', () => { + const warnSpy = vi.spyOn(console, 'warn').mockImplementation(() => {}); + try { + const altFraming = { kind: 'anchorEventCpi', sharedConstantName: 'altPrefix' as CamelCaseString }; + const altPrefix = constantValueNode( + fixedSizeTypeNode(bytesTypeNode(), 8), + bytesValueNode('base16', 'deadbeefcafebabe'), + ); + const altEvent = eventNode({ + data: hiddenPrefixTypeNode( + structTypeNode([structFieldTypeNode({ name: 'amount', type: numberTypeNode('u64') })]), + [altPrefix, settleDisc], + ), + discriminators: [constantDiscriminatorNode(altPrefix, 0), constantDiscriminatorNode(settleDisc, 8)], + framing: altFraming, + name: 'settleEvent', + }); + + const node = programNode({ + events: [framedEvent('tradeEvent', tradeDisc), altEvent], + name: 'myProgram', + publicKey: '11111111111111111111111111111111', + }); + + const renderMap = visit(node, getRenderMapVisitor()); + const programEventsCode = getFromRenderMap(renderMap, 'events/my_program_events.rs').content; + + expect(warnSpy).toHaveBeenCalledTimes(1); + expect(warnSpy.mock.calls[0][0]).toMatch(/conflicting event framings.*'eventCpiPrefix' vs 'altPrefix'/); + + codeContains(programEventsCode, ['pub const EVENT_CPI_PREFIX']); + codeDoesNotContains(programEventsCode, ['pub const ALT_PREFIX']); + } finally { + warnSpy.mockRestore(); + } +}); From 77472d5556ad49d260b79152ee1de45b820176f6 Mon Sep 17 00:00:00 2001 From: ioxde <228087182+ioxde@users.noreply.github.com> Date: Tue, 2 Jun 2026 16:05:52 -0700 Subject: [PATCH 08/24] Regenerate Raydium Launchpad events with Anchor CPI framing Generated event parsers now validate the shared Anchor event CPI discriminator before the per-event discriminator, matching how the program actually emits framed events. --- .../generated/events/claim_vested_event.rs | 14 ++++++-- .../generated/events/create_vesting_event.rs | 14 ++++++-- .../src/generated/events/pool_create_event.rs | 14 ++++++-- .../events/raydium_launchpad_events.rs | 35 +++++++++++++------ .../src/generated/events/trade_event.rs | 15 ++++++-- 5 files changed, 73 insertions(+), 19 deletions(-) diff --git a/e2e/raydium-launchpad/src/generated/events/claim_vested_event.rs b/e2e/raydium-launchpad/src/generated/events/claim_vested_event.rs index 768e284..f20b280 100644 --- a/e2e/raydium-launchpad/src/generated/events/claim_vested_event.rs +++ b/e2e/raydium-launchpad/src/generated/events/claim_vested_event.rs @@ -5,6 +5,7 @@ //! //! +use crate::generated::events::ANCHOR_EVENT_CPI_DISCRIMINATOR; use borsh::BorshDeserialize; use borsh::BorshSerialize; use solana_address::Address; @@ -21,7 +22,15 @@ pub const CLAIM_VESTED_EVENT_DISCRIMINATOR: [u8; 8] = [21, 194, 114, 87, 120, 21 impl ClaimVestedEvent { #[inline(always)] pub fn from_bytes(data: &[u8]) -> Result { - if data.get(..CLAIM_VESTED_EVENT_DISCRIMINATOR.len()) + if data.get(..ANCHOR_EVENT_CPI_DISCRIMINATOR.len()) + != Some(&ANCHOR_EVENT_CPI_DISCRIMINATOR[..]) + { + return Err(std::io::Error::new( + std::io::ErrorKind::InvalidData, + "invalid event discriminator", + )); + } + if data.get(8..8 + CLAIM_VESTED_EVENT_DISCRIMINATOR.len()) != Some(&CLAIM_VESTED_EVENT_DISCRIMINATOR[..]) { return Err(std::io::Error::new( @@ -29,7 +38,8 @@ impl ClaimVestedEvent { "invalid event discriminator", )); } - let mut data = &data[CLAIM_VESTED_EVENT_DISCRIMINATOR.len()..]; + let mut data = + &data[ANCHOR_EVENT_CPI_DISCRIMINATOR.len() + CLAIM_VESTED_EVENT_DISCRIMINATOR.len()..]; Self::deserialize(&mut data) } } diff --git a/e2e/raydium-launchpad/src/generated/events/create_vesting_event.rs b/e2e/raydium-launchpad/src/generated/events/create_vesting_event.rs index 46d04df..3336aca 100644 --- a/e2e/raydium-launchpad/src/generated/events/create_vesting_event.rs +++ b/e2e/raydium-launchpad/src/generated/events/create_vesting_event.rs @@ -5,6 +5,7 @@ //! //! +use crate::generated::events::ANCHOR_EVENT_CPI_DISCRIMINATOR; use borsh::BorshDeserialize; use borsh::BorshSerialize; use solana_address::Address; @@ -21,7 +22,15 @@ pub const CREATE_VESTING_EVENT_DISCRIMINATOR: [u8; 8] = [150, 152, 11, 179, 52, impl CreateVestingEvent { #[inline(always)] pub fn from_bytes(data: &[u8]) -> Result { - if data.get(..CREATE_VESTING_EVENT_DISCRIMINATOR.len()) + if data.get(..ANCHOR_EVENT_CPI_DISCRIMINATOR.len()) + != Some(&ANCHOR_EVENT_CPI_DISCRIMINATOR[..]) + { + return Err(std::io::Error::new( + std::io::ErrorKind::InvalidData, + "invalid event discriminator", + )); + } + if data.get(8..8 + CREATE_VESTING_EVENT_DISCRIMINATOR.len()) != Some(&CREATE_VESTING_EVENT_DISCRIMINATOR[..]) { return Err(std::io::Error::new( @@ -29,7 +38,8 @@ impl CreateVestingEvent { "invalid event discriminator", )); } - let mut data = &data[CREATE_VESTING_EVENT_DISCRIMINATOR.len()..]; + let mut data = &data + [ANCHOR_EVENT_CPI_DISCRIMINATOR.len() + CREATE_VESTING_EVENT_DISCRIMINATOR.len()..]; Self::deserialize(&mut data) } } diff --git a/e2e/raydium-launchpad/src/generated/events/pool_create_event.rs b/e2e/raydium-launchpad/src/generated/events/pool_create_event.rs index 647bb21..b967e61 100644 --- a/e2e/raydium-launchpad/src/generated/events/pool_create_event.rs +++ b/e2e/raydium-launchpad/src/generated/events/pool_create_event.rs @@ -5,6 +5,7 @@ //! //! +use crate::generated::events::ANCHOR_EVENT_CPI_DISCRIMINATOR; use crate::generated::types::CurveParams; use crate::generated::types::MintParams; use crate::generated::types::VestingParams; @@ -27,7 +28,15 @@ pub const POOL_CREATE_EVENT_DISCRIMINATOR: [u8; 8] = [151, 215, 226, 9, 118, 161 impl PoolCreateEvent { #[inline(always)] pub fn from_bytes(data: &[u8]) -> Result { - if data.get(..POOL_CREATE_EVENT_DISCRIMINATOR.len()) + if data.get(..ANCHOR_EVENT_CPI_DISCRIMINATOR.len()) + != Some(&ANCHOR_EVENT_CPI_DISCRIMINATOR[..]) + { + return Err(std::io::Error::new( + std::io::ErrorKind::InvalidData, + "invalid event discriminator", + )); + } + if data.get(8..8 + POOL_CREATE_EVENT_DISCRIMINATOR.len()) != Some(&POOL_CREATE_EVENT_DISCRIMINATOR[..]) { return Err(std::io::Error::new( @@ -35,7 +44,8 @@ impl PoolCreateEvent { "invalid event discriminator", )); } - let mut data = &data[POOL_CREATE_EVENT_DISCRIMINATOR.len()..]; + let mut data = + &data[ANCHOR_EVENT_CPI_DISCRIMINATOR.len() + POOL_CREATE_EVENT_DISCRIMINATOR.len()..]; Self::deserialize(&mut data) } } diff --git a/e2e/raydium-launchpad/src/generated/events/raydium_launchpad_events.rs b/e2e/raydium-launchpad/src/generated/events/raydium_launchpad_events.rs index b22f6a3..9368b5c 100644 --- a/e2e/raydium-launchpad/src/generated/events/raydium_launchpad_events.rs +++ b/e2e/raydium-launchpad/src/generated/events/raydium_launchpad_events.rs @@ -15,6 +15,10 @@ use crate::generated::events::POOL_CREATE_EVENT_DISCRIMINATOR; use crate::generated::events::TRADE_EVENT_DISCRIMINATOR; use borsh::BorshDeserialize; +/// Shared event-framing tag prepended to every framed event emitted by the +/// `raydium_launchpad` program. +pub const ANCHOR_EVENT_CPI_DISCRIMINATOR: [u8; 8] = [228, 69, 165, 46, 81, 203, 154, 29]; + /// Event kinds for the `raydium_launchpad` program. #[derive(Clone, Debug, Eq, PartialEq)] pub enum RaydiumLaunchpadEventKind { @@ -26,22 +30,27 @@ pub enum RaydiumLaunchpadEventKind { /// Identifies a `raydium_launchpad` event from the provided data. pub fn identify_raydium_launchpad_event(data: &[u8]) -> Option { - if data.get(..CLAIM_VESTED_EVENT_DISCRIMINATOR.len()) - == Some(&CLAIM_VESTED_EVENT_DISCRIMINATOR[..]) + if data.get(..ANCHOR_EVENT_CPI_DISCRIMINATOR.len()) == Some(&ANCHOR_EVENT_CPI_DISCRIMINATOR[..]) + && data.get(8..8 + CLAIM_VESTED_EVENT_DISCRIMINATOR.len()) + == Some(&CLAIM_VESTED_EVENT_DISCRIMINATOR[..]) { return Some(RaydiumLaunchpadEventKind::ClaimVestedEvent); } - if data.get(..CREATE_VESTING_EVENT_DISCRIMINATOR.len()) - == Some(&CREATE_VESTING_EVENT_DISCRIMINATOR[..]) + if data.get(..ANCHOR_EVENT_CPI_DISCRIMINATOR.len()) == Some(&ANCHOR_EVENT_CPI_DISCRIMINATOR[..]) + && data.get(8..8 + CREATE_VESTING_EVENT_DISCRIMINATOR.len()) + == Some(&CREATE_VESTING_EVENT_DISCRIMINATOR[..]) { return Some(RaydiumLaunchpadEventKind::CreateVestingEvent); } - if data.get(..POOL_CREATE_EVENT_DISCRIMINATOR.len()) - == Some(&POOL_CREATE_EVENT_DISCRIMINATOR[..]) + if data.get(..ANCHOR_EVENT_CPI_DISCRIMINATOR.len()) == Some(&ANCHOR_EVENT_CPI_DISCRIMINATOR[..]) + && data.get(8..8 + POOL_CREATE_EVENT_DISCRIMINATOR.len()) + == Some(&POOL_CREATE_EVENT_DISCRIMINATOR[..]) { return Some(RaydiumLaunchpadEventKind::PoolCreateEvent); } - if data.get(..TRADE_EVENT_DISCRIMINATOR.len()) == Some(&TRADE_EVENT_DISCRIMINATOR[..]) { + if data.get(..ANCHOR_EVENT_CPI_DISCRIMINATOR.len()) == Some(&ANCHOR_EVENT_CPI_DISCRIMINATOR[..]) + && data.get(8..8 + TRADE_EVENT_DISCRIMINATOR.len()) == Some(&TRADE_EVENT_DISCRIMINATOR[..]) + { return Some(RaydiumLaunchpadEventKind::TradeEvent); } None @@ -63,20 +72,24 @@ pub fn try_parse_raydium_launchpad_event( let event_kind = identify_raydium_launchpad_event(data)?; Some(match event_kind { RaydiumLaunchpadEventKind::ClaimVestedEvent => { - let mut data = &data[CLAIM_VESTED_EVENT_DISCRIMINATOR.len()..]; + let mut data = &data + [ANCHOR_EVENT_CPI_DISCRIMINATOR.len() + CLAIM_VESTED_EVENT_DISCRIMINATOR.len()..]; ClaimVestedEvent::deserialize(&mut data).map(RaydiumLaunchpadEvent::ClaimVestedEvent) } RaydiumLaunchpadEventKind::CreateVestingEvent => { - let mut data = &data[CREATE_VESTING_EVENT_DISCRIMINATOR.len()..]; + let mut data = &data + [ANCHOR_EVENT_CPI_DISCRIMINATOR.len() + CREATE_VESTING_EVENT_DISCRIMINATOR.len()..]; CreateVestingEvent::deserialize(&mut data) .map(RaydiumLaunchpadEvent::CreateVestingEvent) } RaydiumLaunchpadEventKind::PoolCreateEvent => { - let mut data = &data[POOL_CREATE_EVENT_DISCRIMINATOR.len()..]; + let mut data = &data + [ANCHOR_EVENT_CPI_DISCRIMINATOR.len() + POOL_CREATE_EVENT_DISCRIMINATOR.len()..]; PoolCreateEvent::deserialize(&mut data).map(RaydiumLaunchpadEvent::PoolCreateEvent) } RaydiumLaunchpadEventKind::TradeEvent => { - let mut data = &data[TRADE_EVENT_DISCRIMINATOR.len()..]; + let mut data = + &data[ANCHOR_EVENT_CPI_DISCRIMINATOR.len() + TRADE_EVENT_DISCRIMINATOR.len()..]; TradeEvent::deserialize(&mut data).map(RaydiumLaunchpadEvent::TradeEvent) } }) diff --git a/e2e/raydium-launchpad/src/generated/events/trade_event.rs b/e2e/raydium-launchpad/src/generated/events/trade_event.rs index bf5b813..2865ee4 100644 --- a/e2e/raydium-launchpad/src/generated/events/trade_event.rs +++ b/e2e/raydium-launchpad/src/generated/events/trade_event.rs @@ -5,6 +5,7 @@ //! //! +use crate::generated::events::ANCHOR_EVENT_CPI_DISCRIMINATOR; use crate::generated::types::PoolStatus; use crate::generated::types::TradeDirection; use borsh::BorshDeserialize; @@ -35,13 +36,23 @@ pub const TRADE_EVENT_DISCRIMINATOR: [u8; 8] = [189, 219, 127, 211, 78, 230, 97, impl TradeEvent { #[inline(always)] pub fn from_bytes(data: &[u8]) -> Result { - if data.get(..TRADE_EVENT_DISCRIMINATOR.len()) != Some(&TRADE_EVENT_DISCRIMINATOR[..]) { + if data.get(..ANCHOR_EVENT_CPI_DISCRIMINATOR.len()) + != Some(&ANCHOR_EVENT_CPI_DISCRIMINATOR[..]) + { return Err(std::io::Error::new( std::io::ErrorKind::InvalidData, "invalid event discriminator", )); } - let mut data = &data[TRADE_EVENT_DISCRIMINATOR.len()..]; + if data.get(8..8 + TRADE_EVENT_DISCRIMINATOR.len()) != Some(&TRADE_EVENT_DISCRIMINATOR[..]) + { + return Err(std::io::Error::new( + std::io::ErrorKind::InvalidData, + "invalid event discriminator", + )); + } + let mut data = + &data[ANCHOR_EVENT_CPI_DISCRIMINATOR.len() + TRADE_EVENT_DISCRIMINATOR.len()..]; Self::deserialize(&mut data) } } From d04358685535c71fcd564a31f0edc13e1f1f13a6 Mon Sep 17 00:00:00 2001 From: Ian Macalinao Date: Thu, 9 Oct 2025 11:51:50 +0800 Subject: [PATCH 09/24] pdas mod/page template --- public/templates/pdasMod.njk | 7 +++ public/templates/pdasPage.njk | 103 ++++++++++++++++++++++++++++++++++ public/templates/rootMod.njk | 3 + 3 files changed, 113 insertions(+) create mode 100644 public/templates/pdasMod.njk create mode 100644 public/templates/pdasPage.njk diff --git a/public/templates/pdasMod.njk b/public/templates/pdasMod.njk new file mode 100644 index 0000000..1bfe479 --- /dev/null +++ b/public/templates/pdasMod.njk @@ -0,0 +1,7 @@ +{% for pda in pdasToExport %} +pub mod {{ pda.name | snakeCase }}; +{% endfor %} + +{% for pda in pdasToExport %} +pub use self::{{ pda.name | snakeCase }}::*; +{% endfor %} \ No newline at end of file diff --git a/public/templates/pdasPage.njk b/public/templates/pdasPage.njk new file mode 100644 index 0000000..aaf1ba3 --- /dev/null +++ b/public/templates/pdasPage.njk @@ -0,0 +1,103 @@ +{% extends "layout.njk" %} +{% import "macros.njk" as macros %} + +{% block main %} + +{% if program %} +use crate::{{ program.name | snakeCase | upper }}_ID; +{% endif %} + +{# Generate SEED constants for constant seeds #} +{% set constantIndex = 0 %} +{% for seed in seeds %} + {% if seed.kind === 'constantPdaSeedNode' and seed.value.kind !== 'programIdValueNode' %} +pub const {{ pda.name | snakeCase | upper }}_SEED{% if constantSeeds.length > 1 %}_{{ constantIndex }}{% endif %}: &'static [u8] = b{{ seed.valueManifest.render }}; + {% set constantIndex = constantIndex + 1 %} + {% endif %} +{% endfor %} + +pub fn create_{{ pda.name | snakeCase }}_pda( + {% if hasVariableSeeds %} + {% for seed in seeds %} + {% if seed.kind === 'variablePdaSeedNode' %} + {% if seed.resolvedType.kind == 'publicKeyTypeNode' %} + {{ seed.name | snakeCase }}: solana_pubkey::Pubkey, + {% else %} + {{ seed.name | snakeCase }}: {{ seed.typeManifest.type }}, + {% endif %} + {% endif %} + {% endfor %} + {% endif %} + bump: u8, +) -> Result { + solana_pubkey::Pubkey::create_program_address( + &[ + {% set constantUsageIndex = 0 %} + {% for seed in seeds %} + {% if seed.kind === 'constantPdaSeedNode' and seed.value.kind === 'programIdValueNode' %} + {% if program %} + crate::{{ program.name | snakeCase | upper }}_ID.as_ref(), + {% endif %} + {% elif seed.kind === 'constantPdaSeedNode' %} + {{ pda.name | snakeCase | upper }}_SEED{% if constantSeeds.length > 1 %}_{{ constantUsageIndex }}{% endif %}, + {% set constantUsageIndex = constantUsageIndex + 1 %} + {% elif seed.kind == 'variablePdaSeedNode' and seed.resolvedType.kind == 'publicKeyTypeNode' %} + {{ seed.name | snakeCase }}.as_ref(), + {% elif seed.kind == 'variablePdaSeedNode' and seed.resolvedType.kind == 'bytesTypeNode' %} + &{{ seed.name | snakeCase }}, + {% else %} + {{ seed.name | snakeCase }}.to_string().as_ref(), + {% endif %} + {% endfor %} + &[bump], + ], + {% if program %} + &{{ program.name | snakeCase | upper }}_ID, + {% else %} + // Program ID not available + {% endif %} + ) +} + +pub fn find_{{ pda.name | snakeCase }}_pda( +{% if hasVariableSeeds %} + {% for seed in seeds %} + {% if seed.kind == 'variablePdaSeedNode' %} + {% if seed.resolvedType.kind == 'publicKeyTypeNode' %} + {{ seed.name | snakeCase }}: &solana_pubkey::Pubkey, + {% else %} + {{ seed.name | snakeCase }}: {{ seed.typeManifest.type }}, + {% endif %} + {% endif %} + {% endfor %} +{% endif %} +) -> (solana_pubkey::Pubkey, u8) { + solana_pubkey::Pubkey::find_program_address( + &[ + {% set constantUsageIndex2 = 0 %} + {% for seed in seeds %} + {% if seed.kind === 'constantPdaSeedNode' and seed.value.kind === 'programIdValueNode' %} + {% if program %} + crate::{{ program.name | snakeCase | upper }}_ID.as_ref(), + {% endif %} + {% elif seed.kind === 'constantPdaSeedNode' %} + {{ pda.name | snakeCase | upper }}_SEED{% if constantSeeds.length > 1 %}_{{ constantUsageIndex2 }}{% endif %}, + {% set constantUsageIndex2 = constantUsageIndex2 + 1 %} + {% elif seed.kind == 'variablePdaSeedNode' and seed.resolvedType.kind == 'publicKeyTypeNode' %} + {{ seed.name | snakeCase }}.as_ref(), + {% elif seed.kind == 'variablePdaSeedNode' and seed.resolvedType.kind == 'bytesTypeNode' %} + &{{ seed.name | snakeCase }}, + {% else %} + {{ seed.name | snakeCase }}.to_string().as_ref(), + {% endif %} + {% endfor %} + ], + {% if program %} + &{{ program.name | snakeCase | upper }}_ID, + {% else %} + // Program ID not available + {% endif %} + ) +} + +{% endblock %} \ No newline at end of file diff --git a/public/templates/rootMod.njk b/public/templates/rootMod.njk index d792bcb..6c9f256 100644 --- a/public/templates/rootMod.njk +++ b/public/templates/rootMod.njk @@ -12,6 +12,9 @@ {% if instructionsToExport.length > 0 %} pub mod instructions; {% endif %} + {% if pdasToExport.length > 0 %} + pub mod pdas; + {% endif %} {% if programsToExport.length > 0 %} pub mod programs; {% endif %} From 66343c9a2faed8f250f91ac11baf3a0f3f21b70a Mon Sep 17 00:00:00 2001 From: Ian Macalinao Date: Thu, 9 Oct 2025 12:33:30 +0800 Subject: [PATCH 10/24] add example for pda generation --- Cargo.lock | 25 + e2e/governance/Cargo.toml | 33 + e2e/governance/idl.json | 8758 +++++++++++++++++ .../src/generated/accounts/governance_v1.rs | 178 + .../src/generated/accounts/governance_v2.rs | 182 + .../accounts/legacy_token_owner_record.rs | 197 + e2e/governance/src/generated/accounts/mod.rs | 46 + .../generated/accounts/program_metadata.rs | 133 + .../generated/accounts/proposal_deposit.rs | 177 + .../accounts/proposal_instruction_v1.rs | 187 + .../accounts/proposal_transaction_v2.rs | 189 + .../src/generated/accounts/proposal_v1.rs | 213 + .../src/generated/accounts/proposal_v2.rs | 220 + .../accounts/realm_config_account.rs | 164 + .../src/generated/accounts/realm_v1.rs | 166 + .../src/generated/accounts/realm_v2.rs | 168 + .../generated/accounts/required_signatory.rs | 176 + .../generated/accounts/signatory_record_v1.rs | 176 + .../generated/accounts/signatory_record_v2.rs | 177 + .../accounts/token_owner_record_v1.rs | 194 + .../accounts/token_owner_record_v2.rs | 196 + .../src/generated/accounts/vote_record_v1.rs | 178 + .../src/generated/accounts/vote_record_v2.rs | 180 + e2e/governance/src/generated/errors/mod.rs | 10 + .../src/generated/errors/spl_governance.rs | 394 + .../instructions/add_required_signatory.rs | 454 + .../generated/instructions/add_signatory.rs | 541 + .../generated/instructions/cancel_proposal.rs | 447 + .../src/generated/instructions/cast_vote.rs | 896 ++ .../instructions/complete_proposal.rs | 365 + .../instructions/create_governance.rs | 689 ++ .../instructions/create_mint_governance.rs | 794 ++ .../instructions/create_native_treasury.rs | 407 + .../instructions/create_program_governance.rs | 845 ++ .../generated/instructions/create_proposal.rs | 905 ++ .../generated/instructions/create_realm.rs | 1051 ++ .../instructions/create_token_governance.rs | 805 ++ .../instructions/create_token_owner_record.rs | 488 + .../instructions/deposit_governing_tokens.rs | 716 ++ .../instructions/execute_transaction.rs | 365 + .../generated/instructions/finalize_vote.rs | 547 + .../instructions/flag_transaction_error.rs | 416 + .../instructions/insert_transaction.rs | 675 ++ .../src/generated/instructions/legacy1.rs | 225 + .../src/generated/instructions/mod.rs | 70 + .../instructions/refund_proposal_deposit.rs | 372 + .../generated/instructions/relinquish_vote.rs | 617 ++ .../instructions/remove_required_signatory.rs | 369 + .../instructions/remove_transaction.rs | 458 + .../instructions/revoke_governing_tokens.rs | 599 ++ .../instructions/set_governance_config.rs | 329 + .../instructions/set_governance_delegate.rs | 376 + .../instructions/set_realm_authority.rs | 423 + .../instructions/set_realm_config.rs | 919 ++ .../instructions/sign_off_proposal.rs | 454 + .../instructions/update_program_metadata.rs | 363 + .../instructions/withdraw_governing_tokens.rs | 552 ++ e2e/governance/src/generated/mod.rs | 15 + .../generated/pdas/community_token_holding.rs | 42 + .../generated/pdas/council_token_holding.rs | 42 + .../src/generated/pdas/governance.rs | 42 + .../generated/pdas/governing_token_holding.rs | 42 + e2e/governance/src/generated/pdas/mod.rs | 1 + .../src/generated/pdas/native_treasury.rs | 38 + e2e/governance/src/generated/pdas/proposal.rs | 46 + .../src/generated/pdas/proposal_deposit.rs | 42 + .../generated/pdas/proposal_transaction.rs | 46 + e2e/governance/src/generated/pdas/realm.rs | 38 + .../src/generated/pdas/realm_config.rs | 38 + .../src/generated/pdas/required_signatory.rs | 42 + .../src/generated/pdas/signatory_record.rs | 42 + .../src/generated/pdas/token_owner_record.rs | 46 + .../src/generated/pdas/vote_record.rs | 42 + e2e/governance/src/generated/programs.rs | 11 + e2e/governance/src/generated/shared.rs | 21 + .../src/generated/types/account_meta_data.rs | 22 + .../types/governance_account_type.rs | 51 + .../src/generated/types/governance_config.rs | 28 + .../types/governance_instruction_v1.rs | 22 + .../generated/types/governing_token_config.rs | 20 + .../governing_token_config_account_args.rs | 19 + .../types/governing_token_config_params.rs | 18 + .../generated/types/governing_token_type.rs | 29 + .../src/generated/types/instruction_data.rs | 23 + .../types/instruction_execution_flags.rs | 29 + .../types/mint_max_voter_weight_source.rs | 16 + e2e/governance/src/generated/types/mod.rs | 72 + .../src/generated/types/multi_choice_type.rs | 28 + .../src/generated/types/native_treasury.rs | 13 + .../src/generated/types/option_vote_result.rs | 29 + .../src/generated/types/proposal_option.rs | 21 + .../src/generated/types/proposal_state.rs | 36 + .../src/generated/types/realm_config.rs | 22 + .../generated/types/realm_config_params.rs | 21 + .../generated/types/realm_config_params_v1.rs | 18 + .../src/generated/types/reserved110.rs | 18 + .../src/generated/types/reserved119.rs | 18 + .../types/set_realm_authority_action.rs | 29 + e2e/governance/src/generated/types/slot.rs | 8 + .../types/transaction_execution_status.rs | 29 + .../src/generated/types/unix_timestamp.rs | 8 + e2e/governance/src/generated/types/vote.rs | 19 + .../src/generated/types/vote_choice.rs | 16 + .../src/generated/types/vote_kind.rs | 28 + .../src/generated/types/vote_threshold.rs | 17 + .../src/generated/types/vote_tipping.rs | 29 + .../src/generated/types/vote_type.rs | 22 + .../src/generated/types/vote_weight_v1.rs | 16 + e2e/governance/src/lib.rs | 4 + src/getRenderMapVisitor.ts | 72 +- src/utils/render.ts | 2 +- test/pdasPage.test.ts | 163 + 112 files changed, 31914 insertions(+), 6 deletions(-) create mode 100644 e2e/governance/Cargo.toml create mode 100644 e2e/governance/idl.json create mode 100644 e2e/governance/src/generated/accounts/governance_v1.rs create mode 100644 e2e/governance/src/generated/accounts/governance_v2.rs create mode 100644 e2e/governance/src/generated/accounts/legacy_token_owner_record.rs create mode 100644 e2e/governance/src/generated/accounts/mod.rs create mode 100644 e2e/governance/src/generated/accounts/program_metadata.rs create mode 100644 e2e/governance/src/generated/accounts/proposal_deposit.rs create mode 100644 e2e/governance/src/generated/accounts/proposal_instruction_v1.rs create mode 100644 e2e/governance/src/generated/accounts/proposal_transaction_v2.rs create mode 100644 e2e/governance/src/generated/accounts/proposal_v1.rs create mode 100644 e2e/governance/src/generated/accounts/proposal_v2.rs create mode 100644 e2e/governance/src/generated/accounts/realm_config_account.rs create mode 100644 e2e/governance/src/generated/accounts/realm_v1.rs create mode 100644 e2e/governance/src/generated/accounts/realm_v2.rs create mode 100644 e2e/governance/src/generated/accounts/required_signatory.rs create mode 100644 e2e/governance/src/generated/accounts/signatory_record_v1.rs create mode 100644 e2e/governance/src/generated/accounts/signatory_record_v2.rs create mode 100644 e2e/governance/src/generated/accounts/token_owner_record_v1.rs create mode 100644 e2e/governance/src/generated/accounts/token_owner_record_v2.rs create mode 100644 e2e/governance/src/generated/accounts/vote_record_v1.rs create mode 100644 e2e/governance/src/generated/accounts/vote_record_v2.rs create mode 100644 e2e/governance/src/generated/errors/mod.rs create mode 100644 e2e/governance/src/generated/errors/spl_governance.rs create mode 100644 e2e/governance/src/generated/instructions/add_required_signatory.rs create mode 100644 e2e/governance/src/generated/instructions/add_signatory.rs create mode 100644 e2e/governance/src/generated/instructions/cancel_proposal.rs create mode 100644 e2e/governance/src/generated/instructions/cast_vote.rs create mode 100644 e2e/governance/src/generated/instructions/complete_proposal.rs create mode 100644 e2e/governance/src/generated/instructions/create_governance.rs create mode 100644 e2e/governance/src/generated/instructions/create_mint_governance.rs create mode 100644 e2e/governance/src/generated/instructions/create_native_treasury.rs create mode 100644 e2e/governance/src/generated/instructions/create_program_governance.rs create mode 100644 e2e/governance/src/generated/instructions/create_proposal.rs create mode 100644 e2e/governance/src/generated/instructions/create_realm.rs create mode 100644 e2e/governance/src/generated/instructions/create_token_governance.rs create mode 100644 e2e/governance/src/generated/instructions/create_token_owner_record.rs create mode 100644 e2e/governance/src/generated/instructions/deposit_governing_tokens.rs create mode 100644 e2e/governance/src/generated/instructions/execute_transaction.rs create mode 100644 e2e/governance/src/generated/instructions/finalize_vote.rs create mode 100644 e2e/governance/src/generated/instructions/flag_transaction_error.rs create mode 100644 e2e/governance/src/generated/instructions/insert_transaction.rs create mode 100644 e2e/governance/src/generated/instructions/legacy1.rs create mode 100644 e2e/governance/src/generated/instructions/mod.rs create mode 100644 e2e/governance/src/generated/instructions/refund_proposal_deposit.rs create mode 100644 e2e/governance/src/generated/instructions/relinquish_vote.rs create mode 100644 e2e/governance/src/generated/instructions/remove_required_signatory.rs create mode 100644 e2e/governance/src/generated/instructions/remove_transaction.rs create mode 100644 e2e/governance/src/generated/instructions/revoke_governing_tokens.rs create mode 100644 e2e/governance/src/generated/instructions/set_governance_config.rs create mode 100644 e2e/governance/src/generated/instructions/set_governance_delegate.rs create mode 100644 e2e/governance/src/generated/instructions/set_realm_authority.rs create mode 100644 e2e/governance/src/generated/instructions/set_realm_config.rs create mode 100644 e2e/governance/src/generated/instructions/sign_off_proposal.rs create mode 100644 e2e/governance/src/generated/instructions/update_program_metadata.rs create mode 100644 e2e/governance/src/generated/instructions/withdraw_governing_tokens.rs create mode 100644 e2e/governance/src/generated/mod.rs create mode 100644 e2e/governance/src/generated/pdas/community_token_holding.rs create mode 100644 e2e/governance/src/generated/pdas/council_token_holding.rs create mode 100644 e2e/governance/src/generated/pdas/governance.rs create mode 100644 e2e/governance/src/generated/pdas/governing_token_holding.rs create mode 100644 e2e/governance/src/generated/pdas/mod.rs create mode 100644 e2e/governance/src/generated/pdas/native_treasury.rs create mode 100644 e2e/governance/src/generated/pdas/proposal.rs create mode 100644 e2e/governance/src/generated/pdas/proposal_deposit.rs create mode 100644 e2e/governance/src/generated/pdas/proposal_transaction.rs create mode 100644 e2e/governance/src/generated/pdas/realm.rs create mode 100644 e2e/governance/src/generated/pdas/realm_config.rs create mode 100644 e2e/governance/src/generated/pdas/required_signatory.rs create mode 100644 e2e/governance/src/generated/pdas/signatory_record.rs create mode 100644 e2e/governance/src/generated/pdas/token_owner_record.rs create mode 100644 e2e/governance/src/generated/pdas/vote_record.rs create mode 100644 e2e/governance/src/generated/programs.rs create mode 100644 e2e/governance/src/generated/shared.rs create mode 100644 e2e/governance/src/generated/types/account_meta_data.rs create mode 100644 e2e/governance/src/generated/types/governance_account_type.rs create mode 100644 e2e/governance/src/generated/types/governance_config.rs create mode 100644 e2e/governance/src/generated/types/governance_instruction_v1.rs create mode 100644 e2e/governance/src/generated/types/governing_token_config.rs create mode 100644 e2e/governance/src/generated/types/governing_token_config_account_args.rs create mode 100644 e2e/governance/src/generated/types/governing_token_config_params.rs create mode 100644 e2e/governance/src/generated/types/governing_token_type.rs create mode 100644 e2e/governance/src/generated/types/instruction_data.rs create mode 100644 e2e/governance/src/generated/types/instruction_execution_flags.rs create mode 100644 e2e/governance/src/generated/types/mint_max_voter_weight_source.rs create mode 100644 e2e/governance/src/generated/types/mod.rs create mode 100644 e2e/governance/src/generated/types/multi_choice_type.rs create mode 100644 e2e/governance/src/generated/types/native_treasury.rs create mode 100644 e2e/governance/src/generated/types/option_vote_result.rs create mode 100644 e2e/governance/src/generated/types/proposal_option.rs create mode 100644 e2e/governance/src/generated/types/proposal_state.rs create mode 100644 e2e/governance/src/generated/types/realm_config.rs create mode 100644 e2e/governance/src/generated/types/realm_config_params.rs create mode 100644 e2e/governance/src/generated/types/realm_config_params_v1.rs create mode 100644 e2e/governance/src/generated/types/reserved110.rs create mode 100644 e2e/governance/src/generated/types/reserved119.rs create mode 100644 e2e/governance/src/generated/types/set_realm_authority_action.rs create mode 100644 e2e/governance/src/generated/types/slot.rs create mode 100644 e2e/governance/src/generated/types/transaction_execution_status.rs create mode 100644 e2e/governance/src/generated/types/unix_timestamp.rs create mode 100644 e2e/governance/src/generated/types/vote.rs create mode 100644 e2e/governance/src/generated/types/vote_choice.rs create mode 100644 e2e/governance/src/generated/types/vote_kind.rs create mode 100644 e2e/governance/src/generated/types/vote_threshold.rs create mode 100644 e2e/governance/src/generated/types/vote_tipping.rs create mode 100644 e2e/governance/src/generated/types/vote_type.rs create mode 100644 e2e/governance/src/generated/types/vote_weight_v1.rs create mode 100644 e2e/governance/src/lib.rs create mode 100644 test/pdasPage.test.ts diff --git a/Cargo.lock b/Cargo.lock index 0931114..e6d5885 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -605,6 +605,31 @@ dependencies = [ "solana-program-error 3.0.0", ] +[[package]] +name = "codama-renderers-rust-e2e-governance" +version = "0.0.0" +dependencies = [ + "anchor-lang", + "assert_matches", + "borsh 0.10.4", + "kaigan", + "num-derive", + "num-traits", + "serde", + "serde-big-array", + "serde_with", + "solana-account", + "solana-account-info", + "solana-client", + "solana-cpi", + "solana-decode-error", + "solana-instruction", + "solana-program-error", + "solana-pubkey", + "solana-sdk", + "thiserror 1.0.69", +] + [[package]] name = "codama-renderers-rust-e2e-memo" version = "0.0.0" diff --git a/e2e/governance/Cargo.toml b/e2e/governance/Cargo.toml new file mode 100644 index 0000000..5a04d0e --- /dev/null +++ b/e2e/governance/Cargo.toml @@ -0,0 +1,33 @@ +[package] +name = "codama-renderers-rust-e2e-governance" +version = "0.0.0" +edition = "2021" + +[features] +anchor = ["dep:anchor-lang"] +anchor-idl-build = ["anchor", "anchor-lang?/idl-build"] +serde = ["dep:serde", "dep:serde_with", "dep:serde-big-array"] +test-sbf = [] + +[dependencies] +anchor-lang = { workspace = true, optional = true } +borsh = { workspace = true } +kaigan = { workspace = true } +num-derive = { workspace = true } +num-traits = { workspace = true } +serde = { workspace = true, features = ["derive"], optional = true } +serde-big-array = { workspace = true, optional = true } +serde_with = { workspace = true, optional = true } +solana-account = { workspace = true } +solana-account-info = { workspace = true } +solana-client = { workspace = true, optional = true } +solana-cpi = { workspace = true } +solana-decode-error = { workspace = true } +solana-instruction = { workspace = true } +solana-program-error = { workspace = true } +solana-pubkey = { workspace = true, features = ["curve25519", "borsh"] } +thiserror = { workspace = true } + +[dev-dependencies] +assert_matches = { workspace = true } +solana-sdk = { workspace = true } diff --git a/e2e/governance/idl.json b/e2e/governance/idl.json new file mode 100644 index 0000000..ca7f9df --- /dev/null +++ b/e2e/governance/idl.json @@ -0,0 +1,8758 @@ +{ + "kind": "rootNode", + "standard": "codama", + "version": "1.3.7", + "program": { + "kind": "programNode", + "name": "splGovernance", + "publicKey": "GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw", + "version": "3.1.1", + "origin": "shank", + "docs": [], + "accounts": [ + { + "kind": "accountNode", + "name": "governanceV2", + "docs": [], + "data": { + "kind": "structTypeNode", + "fields": [ + { + "kind": "structFieldTypeNode", + "name": "accountType", + "docs": [], + "type": { + "kind": "definedTypeLinkNode", + "name": "governanceAccountType" + } + }, + { + "kind": "structFieldTypeNode", + "name": "realm", + "docs": [], + "type": { + "kind": "publicKeyTypeNode" + } + }, + { + "kind": "structFieldTypeNode", + "name": "governedAccount", + "docs": [], + "type": { + "kind": "publicKeyTypeNode" + } + }, + { + "kind": "structFieldTypeNode", + "name": "reserved1", + "docs": [], + "type": { + "kind": "numberTypeNode", + "format": "u32", + "endian": "le" + } + }, + { + "kind": "structFieldTypeNode", + "name": "config", + "docs": [], + "type": { + "kind": "definedTypeLinkNode", + "name": "governanceConfig" + } + }, + { + "kind": "structFieldTypeNode", + "name": "reservedV2", + "docs": [], + "type": { + "kind": "definedTypeLinkNode", + "name": "reserved119" + } + }, + { + "kind": "structFieldTypeNode", + "name": "requiredSignatoriesCount", + "docs": [], + "type": { + "kind": "numberTypeNode", + "format": "u8", + "endian": "le" + } + }, + { + "kind": "structFieldTypeNode", + "name": "activeProposalCount", + "docs": [], + "type": { + "kind": "numberTypeNode", + "format": "u64", + "endian": "le" + } + } + ] + }, + "pda": { + "kind": "pdaLinkNode", + "name": "governance" + } + }, + { + "kind": "accountNode", + "name": "realmV1", + "docs": [], + "data": { + "kind": "structTypeNode", + "fields": [ + { + "kind": "structFieldTypeNode", + "name": "accountType", + "docs": [], + "type": { + "kind": "definedTypeLinkNode", + "name": "governanceAccountType" + } + }, + { + "kind": "structFieldTypeNode", + "name": "communityMint", + "docs": [], + "type": { + "kind": "publicKeyTypeNode" + } + }, + { + "kind": "structFieldTypeNode", + "name": "config", + "docs": [], + "type": { + "kind": "definedTypeLinkNode", + "name": "realmConfig" + } + }, + { + "kind": "structFieldTypeNode", + "name": "reserved", + "docs": [], + "type": { + "kind": "arrayTypeNode", + "item": { + "kind": "numberTypeNode", + "format": "u8", + "endian": "le" + }, + "count": { + "kind": "fixedCountNode", + "value": 6 + } + } + }, + { + "kind": "structFieldTypeNode", + "name": "votingProposalCount", + "docs": [], + "type": { + "kind": "numberTypeNode", + "format": "u16", + "endian": "le" + } + }, + { + "kind": "structFieldTypeNode", + "name": "authority", + "docs": [], + "type": { + "kind": "optionTypeNode", + "fixed": false, + "item": { + "kind": "publicKeyTypeNode" + }, + "prefix": { + "kind": "numberTypeNode", + "format": "u8", + "endian": "le" + } + } + }, + { + "kind": "structFieldTypeNode", + "name": "name", + "docs": [], + "type": { + "kind": "sizePrefixTypeNode", + "type": { + "kind": "stringTypeNode", + "encoding": "utf8" + }, + "prefix": { + "kind": "numberTypeNode", + "format": "u32", + "endian": "le" + } + } + } + ] + }, + "pda": { + "kind": "pdaLinkNode", + "name": "realm" + } + }, + { + "kind": "accountNode", + "name": "tokenOwnerRecordV1", + "docs": [], + "data": { + "kind": "structTypeNode", + "fields": [ + { + "kind": "structFieldTypeNode", + "name": "accountType", + "docs": [], + "type": { + "kind": "definedTypeLinkNode", + "name": "governanceAccountType" + } + }, + { + "kind": "structFieldTypeNode", + "name": "realm", + "docs": [], + "type": { + "kind": "publicKeyTypeNode" + } + }, + { + "kind": "structFieldTypeNode", + "name": "governingTokenMint", + "docs": [], + "type": { + "kind": "publicKeyTypeNode" + } + }, + { + "kind": "structFieldTypeNode", + "name": "governingTokenOwner", + "docs": [], + "type": { + "kind": "publicKeyTypeNode" + } + }, + { + "kind": "structFieldTypeNode", + "name": "governingTokenDepositAmount", + "docs": [], + "type": { + "kind": "numberTypeNode", + "format": "u64", + "endian": "le" + } + }, + { + "kind": "structFieldTypeNode", + "name": "unrelinquishedVotesCount", + "docs": [], + "type": { + "kind": "numberTypeNode", + "format": "u64", + "endian": "le" + } + }, + { + "kind": "structFieldTypeNode", + "name": "outstandingProposalCount", + "docs": [], + "type": { + "kind": "numberTypeNode", + "format": "u8", + "endian": "le" + } + }, + { + "kind": "structFieldTypeNode", + "name": "version", + "docs": [], + "type": { + "kind": "numberTypeNode", + "format": "u8", + "endian": "le" + } + }, + { + "kind": "structFieldTypeNode", + "name": "reserved", + "docs": [], + "type": { + "kind": "arrayTypeNode", + "item": { + "kind": "numberTypeNode", + "format": "u8", + "endian": "le" + }, + "count": { + "kind": "fixedCountNode", + "value": 6 + } + } + }, + { + "kind": "structFieldTypeNode", + "name": "governanceDelegate", + "docs": [], + "type": { + "kind": "optionTypeNode", + "fixed": false, + "item": { + "kind": "publicKeyTypeNode" + }, + "prefix": { + "kind": "numberTypeNode", + "format": "u8", + "endian": "le" + } + } + } + ] + }, + "pda": { + "kind": "pdaLinkNode", + "name": "tokenOwnerRecord" + } + }, + { + "kind": "accountNode", + "name": "governanceV1", + "docs": [], + "data": { + "kind": "structTypeNode", + "fields": [ + { + "kind": "structFieldTypeNode", + "name": "accountType", + "docs": [], + "type": { + "kind": "definedTypeLinkNode", + "name": "governanceAccountType" + } + }, + { + "kind": "structFieldTypeNode", + "name": "realm", + "docs": [], + "type": { + "kind": "publicKeyTypeNode" + } + }, + { + "kind": "structFieldTypeNode", + "name": "governedAccount", + "docs": [], + "type": { + "kind": "publicKeyTypeNode" + } + }, + { + "kind": "structFieldTypeNode", + "name": "proposalsCount", + "docs": [], + "type": { + "kind": "numberTypeNode", + "format": "u32", + "endian": "le" + } + }, + { + "kind": "structFieldTypeNode", + "name": "config", + "docs": [], + "type": { + "kind": "definedTypeLinkNode", + "name": "governanceConfig" + } + } + ] + }, + "pda": { + "kind": "pdaLinkNode", + "name": "governance" + } + }, + { + "kind": "accountNode", + "name": "proposalV1", + "docs": [], + "data": { + "kind": "structTypeNode", + "fields": [ + { + "kind": "structFieldTypeNode", + "name": "accountType", + "docs": [], + "type": { + "kind": "definedTypeLinkNode", + "name": "governanceAccountType" + } + }, + { + "kind": "structFieldTypeNode", + "name": "governance", + "docs": [], + "type": { + "kind": "publicKeyTypeNode" + } + }, + { + "kind": "structFieldTypeNode", + "name": "governingTokenMint", + "docs": [], + "type": { + "kind": "publicKeyTypeNode" + } + }, + { + "kind": "structFieldTypeNode", + "name": "state", + "docs": [], + "type": { + "kind": "definedTypeLinkNode", + "name": "proposalState" + } + }, + { + "kind": "structFieldTypeNode", + "name": "tokenOwnerRecord", + "docs": [], + "type": { + "kind": "publicKeyTypeNode" + } + }, + { + "kind": "structFieldTypeNode", + "name": "signatoriesCount", + "docs": [], + "type": { + "kind": "numberTypeNode", + "format": "u8", + "endian": "le" + } + }, + { + "kind": "structFieldTypeNode", + "name": "signatoriesSignedOffCount", + "docs": [], + "type": { + "kind": "numberTypeNode", + "format": "u8", + "endian": "le" + } + }, + { + "kind": "structFieldTypeNode", + "name": "yesVotesCount", + "docs": [], + "type": { + "kind": "numberTypeNode", + "format": "u64", + "endian": "le" + } + }, + { + "kind": "structFieldTypeNode", + "name": "noVotesCount", + "docs": [], + "type": { + "kind": "numberTypeNode", + "format": "u64", + "endian": "le" + } + }, + { + "kind": "structFieldTypeNode", + "name": "instructionsExecutedCount", + "docs": [], + "type": { + "kind": "numberTypeNode", + "format": "u16", + "endian": "le" + } + }, + { + "kind": "structFieldTypeNode", + "name": "instructionsCount", + "docs": [], + "type": { + "kind": "numberTypeNode", + "format": "u16", + "endian": "le" + } + }, + { + "kind": "structFieldTypeNode", + "name": "instructionsNextIndex", + "docs": [], + "type": { + "kind": "numberTypeNode", + "format": "u16", + "endian": "le" + } + }, + { + "kind": "structFieldTypeNode", + "name": "draftAt", + "docs": [], + "type": { + "kind": "definedTypeLinkNode", + "name": "unixTimestamp" + } + }, + { + "kind": "structFieldTypeNode", + "name": "signingOffAt", + "docs": [], + "type": { + "kind": "optionTypeNode", + "fixed": false, + "item": { + "kind": "definedTypeLinkNode", + "name": "unixTimestamp" + }, + "prefix": { + "kind": "numberTypeNode", + "format": "u8", + "endian": "le" + } + } + }, + { + "kind": "structFieldTypeNode", + "name": "votingAt", + "docs": [], + "type": { + "kind": "optionTypeNode", + "fixed": false, + "item": { + "kind": "definedTypeLinkNode", + "name": "unixTimestamp" + }, + "prefix": { + "kind": "numberTypeNode", + "format": "u8", + "endian": "le" + } + } + }, + { + "kind": "structFieldTypeNode", + "name": "votingAtSlot", + "docs": [], + "type": { + "kind": "optionTypeNode", + "fixed": false, + "item": { + "kind": "definedTypeLinkNode", + "name": "slot" + }, + "prefix": { + "kind": "numberTypeNode", + "format": "u8", + "endian": "le" + } + } + }, + { + "kind": "structFieldTypeNode", + "name": "votingCompletedAt", + "docs": [], + "type": { + "kind": "optionTypeNode", + "fixed": false, + "item": { + "kind": "definedTypeLinkNode", + "name": "unixTimestamp" + }, + "prefix": { + "kind": "numberTypeNode", + "format": "u8", + "endian": "le" + } + } + }, + { + "kind": "structFieldTypeNode", + "name": "executingAt", + "docs": [], + "type": { + "kind": "optionTypeNode", + "fixed": false, + "item": { + "kind": "definedTypeLinkNode", + "name": "unixTimestamp" + }, + "prefix": { + "kind": "numberTypeNode", + "format": "u8", + "endian": "le" + } + } + }, + { + "kind": "structFieldTypeNode", + "name": "closedAt", + "docs": [], + "type": { + "kind": "optionTypeNode", + "fixed": false, + "item": { + "kind": "definedTypeLinkNode", + "name": "unixTimestamp" + }, + "prefix": { + "kind": "numberTypeNode", + "format": "u8", + "endian": "le" + } + } + }, + { + "kind": "structFieldTypeNode", + "name": "executionFlags", + "docs": [], + "type": { + "kind": "definedTypeLinkNode", + "name": "instructionExecutionFlags" + } + }, + { + "kind": "structFieldTypeNode", + "name": "maxVoteWeight", + "docs": [], + "type": { + "kind": "optionTypeNode", + "fixed": false, + "item": { + "kind": "numberTypeNode", + "format": "u64", + "endian": "le" + }, + "prefix": { + "kind": "numberTypeNode", + "format": "u8", + "endian": "le" + } + } + }, + { + "kind": "structFieldTypeNode", + "name": "voteThreshold", + "docs": [], + "type": { + "kind": "optionTypeNode", + "fixed": false, + "item": { + "kind": "definedTypeLinkNode", + "name": "voteThreshold" + }, + "prefix": { + "kind": "numberTypeNode", + "format": "u8", + "endian": "le" + } + } + }, + { + "kind": "structFieldTypeNode", + "name": "name", + "docs": [], + "type": { + "kind": "sizePrefixTypeNode", + "type": { + "kind": "stringTypeNode", + "encoding": "utf8" + }, + "prefix": { + "kind": "numberTypeNode", + "format": "u32", + "endian": "le" + } + } + }, + { + "kind": "structFieldTypeNode", + "name": "descriptionLink", + "docs": [], + "type": { + "kind": "sizePrefixTypeNode", + "type": { + "kind": "stringTypeNode", + "encoding": "utf8" + }, + "prefix": { + "kind": "numberTypeNode", + "format": "u32", + "endian": "le" + } + } + } + ] + }, + "pda": { + "kind": "pdaLinkNode", + "name": "proposal" + } + }, + { + "kind": "accountNode", + "name": "signatoryRecordV1", + "docs": [], + "data": { + "kind": "structTypeNode", + "fields": [ + { + "kind": "structFieldTypeNode", + "name": "accountType", + "docs": [], + "type": { + "kind": "definedTypeLinkNode", + "name": "governanceAccountType" + } + }, + { + "kind": "structFieldTypeNode", + "name": "proposal", + "docs": [], + "type": { + "kind": "publicKeyTypeNode" + } + }, + { + "kind": "structFieldTypeNode", + "name": "signatory", + "docs": [], + "type": { + "kind": "publicKeyTypeNode" + } + }, + { + "kind": "structFieldTypeNode", + "name": "signedOff", + "docs": [], + "type": { + "kind": "booleanTypeNode", + "size": { + "kind": "numberTypeNode", + "format": "u8", + "endian": "le" + } + } + } + ] + }, + "pda": { + "kind": "pdaLinkNode", + "name": "signatoryRecord" + } + }, + { + "kind": "accountNode", + "name": "proposalInstructionV1", + "docs": [], + "data": { + "kind": "structTypeNode", + "fields": [ + { + "kind": "structFieldTypeNode", + "name": "accountType", + "docs": [], + "type": { + "kind": "definedTypeLinkNode", + "name": "governanceAccountType" + } + }, + { + "kind": "structFieldTypeNode", + "name": "proposal", + "docs": [], + "type": { + "kind": "publicKeyTypeNode" + } + }, + { + "kind": "structFieldTypeNode", + "name": "instructionIndex", + "docs": [], + "type": { + "kind": "numberTypeNode", + "format": "u16", + "endian": "le" + } + }, + { + "kind": "structFieldTypeNode", + "name": "holdUpTime", + "docs": [], + "type": { + "kind": "numberTypeNode", + "format": "u32", + "endian": "le" + } + }, + { + "kind": "structFieldTypeNode", + "name": "instruction", + "docs": [], + "type": { + "kind": "definedTypeLinkNode", + "name": "instructionData" + } + }, + { + "kind": "structFieldTypeNode", + "name": "executedAt", + "docs": [], + "type": { + "kind": "optionTypeNode", + "fixed": false, + "item": { + "kind": "definedTypeLinkNode", + "name": "unixTimestamp" + }, + "prefix": { + "kind": "numberTypeNode", + "format": "u8", + "endian": "le" + } + } + }, + { + "kind": "structFieldTypeNode", + "name": "executionStatus", + "docs": [], + "type": { + "kind": "definedTypeLinkNode", + "name": "transactionExecutionStatus" + } + } + ] + }, + "pda": { + "kind": "pdaLinkNode", + "name": "proposalTransaction" + } + }, + { + "kind": "accountNode", + "name": "voteRecordV1", + "docs": [], + "data": { + "kind": "structTypeNode", + "fields": [ + { + "kind": "structFieldTypeNode", + "name": "accountType", + "docs": [], + "type": { + "kind": "definedTypeLinkNode", + "name": "governanceAccountType" + } + }, + { + "kind": "structFieldTypeNode", + "name": "proposal", + "docs": [], + "type": { + "kind": "publicKeyTypeNode" + } + }, + { + "kind": "structFieldTypeNode", + "name": "governingTokenOwner", + "docs": [], + "type": { + "kind": "publicKeyTypeNode" + } + }, + { + "kind": "structFieldTypeNode", + "name": "isRelinquished", + "docs": [], + "type": { + "kind": "booleanTypeNode", + "size": { + "kind": "numberTypeNode", + "format": "u8", + "endian": "le" + } + } + }, + { + "kind": "structFieldTypeNode", + "name": "voteWeight", + "docs": [], + "type": { + "kind": "definedTypeLinkNode", + "name": "voteWeightV1" + } + } + ] + }, + "pda": { + "kind": "pdaLinkNode", + "name": "voteRecord" + } + }, + { + "kind": "accountNode", + "name": "programMetadata", + "docs": [], + "data": { + "kind": "structTypeNode", + "fields": [ + { + "kind": "structFieldTypeNode", + "name": "accountType", + "docs": [], + "type": { + "kind": "definedTypeLinkNode", + "name": "governanceAccountType" + } + }, + { + "kind": "structFieldTypeNode", + "name": "updatedAt", + "docs": [], + "type": { + "kind": "definedTypeLinkNode", + "name": "slot" + } + }, + { + "kind": "structFieldTypeNode", + "name": "version", + "docs": [], + "type": { + "kind": "sizePrefixTypeNode", + "type": { + "kind": "stringTypeNode", + "encoding": "utf8" + }, + "prefix": { + "kind": "numberTypeNode", + "format": "u32", + "endian": "le" + } + } + }, + { + "kind": "structFieldTypeNode", + "name": "reserved", + "docs": [], + "type": { + "kind": "arrayTypeNode", + "item": { + "kind": "numberTypeNode", + "format": "u8", + "endian": "le" + }, + "count": { + "kind": "fixedCountNode", + "value": 64 + } + } + } + ] + } + }, + { + "kind": "accountNode", + "name": "proposalV2", + "docs": [], + "data": { + "kind": "structTypeNode", + "fields": [ + { + "kind": "structFieldTypeNode", + "name": "accountType", + "docs": [], + "type": { + "kind": "definedTypeLinkNode", + "name": "governanceAccountType" + } + }, + { + "kind": "structFieldTypeNode", + "name": "governance", + "docs": [], + "type": { + "kind": "publicKeyTypeNode" + } + }, + { + "kind": "structFieldTypeNode", + "name": "governingTokenMint", + "docs": [], + "type": { + "kind": "publicKeyTypeNode" + } + }, + { + "kind": "structFieldTypeNode", + "name": "state", + "docs": [], + "type": { + "kind": "definedTypeLinkNode", + "name": "proposalState" + } + }, + { + "kind": "structFieldTypeNode", + "name": "tokenOwnerRecord", + "docs": [], + "type": { + "kind": "publicKeyTypeNode" + } + }, + { + "kind": "structFieldTypeNode", + "name": "signatoriesCount", + "docs": [], + "type": { + "kind": "numberTypeNode", + "format": "u8", + "endian": "le" + } + }, + { + "kind": "structFieldTypeNode", + "name": "signatoriesSignedOffCount", + "docs": [], + "type": { + "kind": "numberTypeNode", + "format": "u8", + "endian": "le" + } + }, + { + "kind": "structFieldTypeNode", + "name": "voteType", + "docs": [], + "type": { + "kind": "definedTypeLinkNode", + "name": "voteType" + } + }, + { + "kind": "structFieldTypeNode", + "name": "options", + "docs": [], + "type": { + "kind": "arrayTypeNode", + "item": { + "kind": "definedTypeLinkNode", + "name": "proposalOption" + }, + "count": { + "kind": "prefixedCountNode", + "prefix": { + "kind": "numberTypeNode", + "format": "u32", + "endian": "le" + } + } + } + }, + { + "kind": "structFieldTypeNode", + "name": "denyVoteWeight", + "docs": [], + "type": { + "kind": "optionTypeNode", + "fixed": false, + "item": { + "kind": "numberTypeNode", + "format": "u64", + "endian": "le" + }, + "prefix": { + "kind": "numberTypeNode", + "format": "u8", + "endian": "le" + } + } + }, + { + "kind": "structFieldTypeNode", + "name": "reserved1", + "docs": [], + "type": { + "kind": "numberTypeNode", + "format": "u8", + "endian": "le" + } + }, + { + "kind": "structFieldTypeNode", + "name": "abstainVoteWeight", + "docs": [], + "type": { + "kind": "optionTypeNode", + "fixed": false, + "item": { + "kind": "numberTypeNode", + "format": "u64", + "endian": "le" + }, + "prefix": { + "kind": "numberTypeNode", + "format": "u8", + "endian": "le" + } + } + }, + { + "kind": "structFieldTypeNode", + "name": "startVotingAt", + "docs": [], + "type": { + "kind": "optionTypeNode", + "fixed": false, + "item": { + "kind": "definedTypeLinkNode", + "name": "unixTimestamp" + }, + "prefix": { + "kind": "numberTypeNode", + "format": "u8", + "endian": "le" + } + } + }, + { + "kind": "structFieldTypeNode", + "name": "draftAt", + "docs": [], + "type": { + "kind": "definedTypeLinkNode", + "name": "unixTimestamp" + } + }, + { + "kind": "structFieldTypeNode", + "name": "signingOffAt", + "docs": [], + "type": { + "kind": "optionTypeNode", + "fixed": false, + "item": { + "kind": "definedTypeLinkNode", + "name": "unixTimestamp" + }, + "prefix": { + "kind": "numberTypeNode", + "format": "u8", + "endian": "le" + } + } + }, + { + "kind": "structFieldTypeNode", + "name": "votingAt", + "docs": [], + "type": { + "kind": "optionTypeNode", + "fixed": false, + "item": { + "kind": "definedTypeLinkNode", + "name": "unixTimestamp" + }, + "prefix": { + "kind": "numberTypeNode", + "format": "u8", + "endian": "le" + } + } + }, + { + "kind": "structFieldTypeNode", + "name": "votingAtSlot", + "docs": [], + "type": { + "kind": "optionTypeNode", + "fixed": false, + "item": { + "kind": "definedTypeLinkNode", + "name": "slot" + }, + "prefix": { + "kind": "numberTypeNode", + "format": "u8", + "endian": "le" + } + } + }, + { + "kind": "structFieldTypeNode", + "name": "votingCompletedAt", + "docs": [], + "type": { + "kind": "optionTypeNode", + "fixed": false, + "item": { + "kind": "definedTypeLinkNode", + "name": "unixTimestamp" + }, + "prefix": { + "kind": "numberTypeNode", + "format": "u8", + "endian": "le" + } + } + }, + { + "kind": "structFieldTypeNode", + "name": "executingAt", + "docs": [], + "type": { + "kind": "optionTypeNode", + "fixed": false, + "item": { + "kind": "definedTypeLinkNode", + "name": "unixTimestamp" + }, + "prefix": { + "kind": "numberTypeNode", + "format": "u8", + "endian": "le" + } + } + }, + { + "kind": "structFieldTypeNode", + "name": "closedAt", + "docs": [], + "type": { + "kind": "optionTypeNode", + "fixed": false, + "item": { + "kind": "definedTypeLinkNode", + "name": "unixTimestamp" + }, + "prefix": { + "kind": "numberTypeNode", + "format": "u8", + "endian": "le" + } + } + }, + { + "kind": "structFieldTypeNode", + "name": "executionFlags", + "docs": [], + "type": { + "kind": "definedTypeLinkNode", + "name": "instructionExecutionFlags" + } + }, + { + "kind": "structFieldTypeNode", + "name": "maxVoteWeight", + "docs": [], + "type": { + "kind": "optionTypeNode", + "fixed": false, + "item": { + "kind": "numberTypeNode", + "format": "u64", + "endian": "le" + }, + "prefix": { + "kind": "numberTypeNode", + "format": "u8", + "endian": "le" + } + } + }, + { + "kind": "structFieldTypeNode", + "name": "maxVotingTime", + "docs": [], + "type": { + "kind": "optionTypeNode", + "fixed": false, + "item": { + "kind": "numberTypeNode", + "format": "u32", + "endian": "le" + }, + "prefix": { + "kind": "numberTypeNode", + "format": "u8", + "endian": "le" + } + } + }, + { + "kind": "structFieldTypeNode", + "name": "voteThreshold", + "docs": [], + "type": { + "kind": "optionTypeNode", + "fixed": false, + "item": { + "kind": "definedTypeLinkNode", + "name": "voteThreshold" + }, + "prefix": { + "kind": "numberTypeNode", + "format": "u8", + "endian": "le" + } + } + }, + { + "kind": "structFieldTypeNode", + "name": "reserved", + "docs": [], + "type": { + "kind": "arrayTypeNode", + "item": { + "kind": "numberTypeNode", + "format": "u8", + "endian": "le" + }, + "count": { + "kind": "fixedCountNode", + "value": 64 + } + } + }, + { + "kind": "structFieldTypeNode", + "name": "name", + "docs": [], + "type": { + "kind": "sizePrefixTypeNode", + "type": { + "kind": "stringTypeNode", + "encoding": "utf8" + }, + "prefix": { + "kind": "numberTypeNode", + "format": "u32", + "endian": "le" + } + } + }, + { + "kind": "structFieldTypeNode", + "name": "descriptionLink", + "docs": [], + "type": { + "kind": "sizePrefixTypeNode", + "type": { + "kind": "stringTypeNode", + "encoding": "utf8" + }, + "prefix": { + "kind": "numberTypeNode", + "format": "u32", + "endian": "le" + } + } + }, + { + "kind": "structFieldTypeNode", + "name": "vetoVoteWeight", + "docs": [], + "type": { + "kind": "numberTypeNode", + "format": "u64", + "endian": "le" + } + } + ] + }, + "pda": { + "kind": "pdaLinkNode", + "name": "proposal" + } + }, + { + "kind": "accountNode", + "name": "proposalDeposit", + "docs": [], + "data": { + "kind": "structTypeNode", + "fields": [ + { + "kind": "structFieldTypeNode", + "name": "accountType", + "docs": [], + "type": { + "kind": "definedTypeLinkNode", + "name": "governanceAccountType" + } + }, + { + "kind": "structFieldTypeNode", + "name": "proposal", + "docs": [], + "type": { + "kind": "publicKeyTypeNode" + } + }, + { + "kind": "structFieldTypeNode", + "name": "depositPayer", + "docs": [], + "type": { + "kind": "publicKeyTypeNode" + } + }, + { + "kind": "structFieldTypeNode", + "name": "reserved", + "docs": [], + "type": { + "kind": "arrayTypeNode", + "item": { + "kind": "numberTypeNode", + "format": "u8", + "endian": "le" + }, + "count": { + "kind": "fixedCountNode", + "value": 64 + } + } + } + ] + }, + "pda": { + "kind": "pdaLinkNode", + "name": "proposalDeposit" + } + }, + { + "kind": "accountNode", + "name": "proposalTransactionV2", + "docs": [], + "data": { + "kind": "structTypeNode", + "fields": [ + { + "kind": "structFieldTypeNode", + "name": "accountType", + "docs": [], + "type": { + "kind": "definedTypeLinkNode", + "name": "governanceAccountType" + } + }, + { + "kind": "structFieldTypeNode", + "name": "proposal", + "docs": [], + "type": { + "kind": "publicKeyTypeNode" + } + }, + { + "kind": "structFieldTypeNode", + "name": "optionIndex", + "docs": [], + "type": { + "kind": "numberTypeNode", + "format": "u8", + "endian": "le" + } + }, + { + "kind": "structFieldTypeNode", + "name": "transactionIndex", + "docs": [], + "type": { + "kind": "numberTypeNode", + "format": "u16", + "endian": "le" + } + }, + { + "kind": "structFieldTypeNode", + "name": "holdUpTime", + "docs": [], + "type": { + "kind": "numberTypeNode", + "format": "u32", + "endian": "le" + } + }, + { + "kind": "structFieldTypeNode", + "name": "instructions", + "docs": [], + "type": { + "kind": "arrayTypeNode", + "item": { + "kind": "definedTypeLinkNode", + "name": "instructionData" + }, + "count": { + "kind": "prefixedCountNode", + "prefix": { + "kind": "numberTypeNode", + "format": "u32", + "endian": "le" + } + } + } + }, + { + "kind": "structFieldTypeNode", + "name": "executedAt", + "docs": [], + "type": { + "kind": "optionTypeNode", + "fixed": false, + "item": { + "kind": "definedTypeLinkNode", + "name": "unixTimestamp" + }, + "prefix": { + "kind": "numberTypeNode", + "format": "u8", + "endian": "le" + } + } + }, + { + "kind": "structFieldTypeNode", + "name": "executionStatus", + "docs": [], + "type": { + "kind": "definedTypeLinkNode", + "name": "transactionExecutionStatus" + } + }, + { + "kind": "structFieldTypeNode", + "name": "reservedV2", + "docs": [], + "type": { + "kind": "arrayTypeNode", + "item": { + "kind": "numberTypeNode", + "format": "u8", + "endian": "le" + }, + "count": { + "kind": "fixedCountNode", + "value": 8 + } + } + } + ] + }, + "pda": { + "kind": "pdaLinkNode", + "name": "proposalTransaction" + } + }, + { + "kind": "accountNode", + "name": "realmV2", + "docs": [], + "data": { + "kind": "structTypeNode", + "fields": [ + { + "kind": "structFieldTypeNode", + "name": "accountType", + "docs": [], + "type": { + "kind": "definedTypeLinkNode", + "name": "governanceAccountType" + } + }, + { + "kind": "structFieldTypeNode", + "name": "communityMint", + "docs": [], + "type": { + "kind": "publicKeyTypeNode" + } + }, + { + "kind": "structFieldTypeNode", + "name": "config", + "docs": [], + "type": { + "kind": "definedTypeLinkNode", + "name": "realmConfig" + } + }, + { + "kind": "structFieldTypeNode", + "name": "reserved", + "docs": [], + "type": { + "kind": "arrayTypeNode", + "item": { + "kind": "numberTypeNode", + "format": "u8", + "endian": "le" + }, + "count": { + "kind": "fixedCountNode", + "value": 6 + } + } + }, + { + "kind": "structFieldTypeNode", + "name": "legacy1", + "docs": [], + "type": { + "kind": "numberTypeNode", + "format": "u16", + "endian": "le" + } + }, + { + "kind": "structFieldTypeNode", + "name": "authority", + "docs": [], + "type": { + "kind": "optionTypeNode", + "fixed": false, + "item": { + "kind": "publicKeyTypeNode" + }, + "prefix": { + "kind": "numberTypeNode", + "format": "u8", + "endian": "le" + } + } + }, + { + "kind": "structFieldTypeNode", + "name": "name", + "docs": [], + "type": { + "kind": "sizePrefixTypeNode", + "type": { + "kind": "stringTypeNode", + "encoding": "utf8" + }, + "prefix": { + "kind": "numberTypeNode", + "format": "u32", + "endian": "le" + } + } + }, + { + "kind": "structFieldTypeNode", + "name": "reservedV2", + "docs": [], + "type": { + "kind": "arrayTypeNode", + "item": { + "kind": "numberTypeNode", + "format": "u8", + "endian": "le" + }, + "count": { + "kind": "fixedCountNode", + "value": 128 + } + } + } + ] + }, + "pda": { + "kind": "pdaLinkNode", + "name": "realm" + } + }, + { + "kind": "accountNode", + "name": "realmConfigAccount", + "docs": [], + "data": { + "kind": "structTypeNode", + "fields": [ + { + "kind": "structFieldTypeNode", + "name": "accountType", + "docs": [], + "type": { + "kind": "definedTypeLinkNode", + "name": "governanceAccountType" + } + }, + { + "kind": "structFieldTypeNode", + "name": "realm", + "docs": [], + "type": { + "kind": "publicKeyTypeNode" + } + }, + { + "kind": "structFieldTypeNode", + "name": "communityTokenConfig", + "docs": [], + "type": { + "kind": "definedTypeLinkNode", + "name": "governingTokenConfig" + } + }, + { + "kind": "structFieldTypeNode", + "name": "councilTokenConfig", + "docs": [], + "type": { + "kind": "definedTypeLinkNode", + "name": "governingTokenConfig" + } + }, + { + "kind": "structFieldTypeNode", + "name": "reserved", + "docs": [], + "type": { + "kind": "definedTypeLinkNode", + "name": "reserved110" + } + } + ] + }, + "pda": { + "kind": "pdaLinkNode", + "name": "realmConfig" + } + }, + { + "kind": "accountNode", + "name": "requiredSignatory", + "docs": [], + "data": { + "kind": "structTypeNode", + "fields": [ + { + "kind": "structFieldTypeNode", + "name": "accountType", + "docs": [], + "type": { + "kind": "definedTypeLinkNode", + "name": "governanceAccountType" + } + }, + { + "kind": "structFieldTypeNode", + "name": "accountVersion", + "docs": [], + "type": { + "kind": "numberTypeNode", + "format": "u8", + "endian": "le" + } + }, + { + "kind": "structFieldTypeNode", + "name": "governance", + "docs": [], + "type": { + "kind": "publicKeyTypeNode" + } + }, + { + "kind": "structFieldTypeNode", + "name": "signatory", + "docs": [], + "type": { + "kind": "publicKeyTypeNode" + } + } + ] + }, + "pda": { + "kind": "pdaLinkNode", + "name": "requiredSignatory" + } + }, + { + "kind": "accountNode", + "name": "signatoryRecordV2", + "docs": [], + "data": { + "kind": "structTypeNode", + "fields": [ + { + "kind": "structFieldTypeNode", + "name": "accountType", + "docs": [], + "type": { + "kind": "definedTypeLinkNode", + "name": "governanceAccountType" + } + }, + { + "kind": "structFieldTypeNode", + "name": "proposal", + "docs": [], + "type": { + "kind": "publicKeyTypeNode" + } + }, + { + "kind": "structFieldTypeNode", + "name": "signatory", + "docs": [], + "type": { + "kind": "publicKeyTypeNode" + } + }, + { + "kind": "structFieldTypeNode", + "name": "signedOff", + "docs": [], + "type": { + "kind": "booleanTypeNode", + "size": { + "kind": "numberTypeNode", + "format": "u8", + "endian": "le" + } + } + }, + { + "kind": "structFieldTypeNode", + "name": "reservedV2", + "docs": [], + "type": { + "kind": "arrayTypeNode", + "item": { + "kind": "numberTypeNode", + "format": "u8", + "endian": "le" + }, + "count": { + "kind": "fixedCountNode", + "value": 8 + } + } + } + ] + }, + "pda": { + "kind": "pdaLinkNode", + "name": "signatoryRecord" + } + }, + { + "kind": "accountNode", + "name": "tokenOwnerRecordV2", + "docs": [], + "data": { + "kind": "structTypeNode", + "fields": [ + { + "kind": "structFieldTypeNode", + "name": "accountType", + "docs": [], + "type": { + "kind": "definedTypeLinkNode", + "name": "governanceAccountType" + } + }, + { + "kind": "structFieldTypeNode", + "name": "realm", + "docs": [], + "type": { + "kind": "publicKeyTypeNode" + } + }, + { + "kind": "structFieldTypeNode", + "name": "governingTokenMint", + "docs": [], + "type": { + "kind": "publicKeyTypeNode" + } + }, + { + "kind": "structFieldTypeNode", + "name": "governingTokenOwner", + "docs": [], + "type": { + "kind": "publicKeyTypeNode" + } + }, + { + "kind": "structFieldTypeNode", + "name": "governingTokenDepositAmount", + "docs": [], + "type": { + "kind": "numberTypeNode", + "format": "u64", + "endian": "le" + } + }, + { + "kind": "structFieldTypeNode", + "name": "unrelinquishedVotesCount", + "docs": [], + "type": { + "kind": "numberTypeNode", + "format": "u64", + "endian": "le" + } + }, + { + "kind": "structFieldTypeNode", + "name": "outstandingProposalCount", + "docs": [], + "type": { + "kind": "numberTypeNode", + "format": "u8", + "endian": "le" + } + }, + { + "kind": "structFieldTypeNode", + "name": "version", + "docs": [], + "type": { + "kind": "numberTypeNode", + "format": "u8", + "endian": "le" + } + }, + { + "kind": "structFieldTypeNode", + "name": "reserved", + "docs": [], + "type": { + "kind": "arrayTypeNode", + "item": { + "kind": "numberTypeNode", + "format": "u8", + "endian": "le" + }, + "count": { + "kind": "fixedCountNode", + "value": 6 + } + } + }, + { + "kind": "structFieldTypeNode", + "name": "governanceDelegate", + "docs": [], + "type": { + "kind": "optionTypeNode", + "fixed": false, + "item": { + "kind": "publicKeyTypeNode" + }, + "prefix": { + "kind": "numberTypeNode", + "format": "u8", + "endian": "le" + } + } + }, + { + "kind": "structFieldTypeNode", + "name": "reservedV2", + "docs": [], + "type": { + "kind": "arrayTypeNode", + "item": { + "kind": "numberTypeNode", + "format": "u8", + "endian": "le" + }, + "count": { + "kind": "fixedCountNode", + "value": 128 + } + } + } + ] + }, + "pda": { + "kind": "pdaLinkNode", + "name": "tokenOwnerRecord" + } + }, + { + "kind": "accountNode", + "name": "legacyTokenOwnerRecord", + "docs": [], + "data": { + "kind": "structTypeNode", + "fields": [ + { + "kind": "structFieldTypeNode", + "name": "accountType", + "docs": [], + "type": { + "kind": "definedTypeLinkNode", + "name": "governanceAccountType" + } + }, + { + "kind": "structFieldTypeNode", + "name": "realm", + "docs": [], + "type": { + "kind": "publicKeyTypeNode" + } + }, + { + "kind": "structFieldTypeNode", + "name": "governingTokenMint", + "docs": [], + "type": { + "kind": "publicKeyTypeNode" + } + }, + { + "kind": "structFieldTypeNode", + "name": "governingTokenOwner", + "docs": [], + "type": { + "kind": "publicKeyTypeNode" + } + }, + { + "kind": "structFieldTypeNode", + "name": "governingTokenDepositAmount", + "docs": [], + "type": { + "kind": "numberTypeNode", + "format": "u64", + "endian": "le" + } + }, + { + "kind": "structFieldTypeNode", + "name": "unrelinquishedVotesCount", + "docs": [], + "type": { + "kind": "numberTypeNode", + "format": "u32", + "endian": "le" + } + }, + { + "kind": "structFieldTypeNode", + "name": "totalVotesCount", + "docs": [], + "type": { + "kind": "numberTypeNode", + "format": "u32", + "endian": "le" + } + }, + { + "kind": "structFieldTypeNode", + "name": "outstandingProposalCount", + "docs": [], + "type": { + "kind": "numberTypeNode", + "format": "u8", + "endian": "le" + } + }, + { + "kind": "structFieldTypeNode", + "name": "reserved", + "docs": [], + "type": { + "kind": "arrayTypeNode", + "item": { + "kind": "numberTypeNode", + "format": "u8", + "endian": "le" + }, + "count": { + "kind": "fixedCountNode", + "value": 7 + } + } + }, + { + "kind": "structFieldTypeNode", + "name": "governanceDelegate", + "docs": [], + "type": { + "kind": "optionTypeNode", + "fixed": false, + "item": { + "kind": "publicKeyTypeNode" + }, + "prefix": { + "kind": "numberTypeNode", + "format": "u8", + "endian": "le" + } + } + }, + { + "kind": "structFieldTypeNode", + "name": "reservedV2", + "docs": [], + "type": { + "kind": "arrayTypeNode", + "item": { + "kind": "numberTypeNode", + "format": "u8", + "endian": "le" + }, + "count": { + "kind": "fixedCountNode", + "value": 128 + } + } + } + ] + }, + "pda": { + "kind": "pdaLinkNode", + "name": "tokenOwnerRecord" + } + }, + { + "kind": "accountNode", + "name": "voteRecordV2", + "docs": [], + "data": { + "kind": "structTypeNode", + "fields": [ + { + "kind": "structFieldTypeNode", + "name": "accountType", + "docs": [], + "type": { + "kind": "definedTypeLinkNode", + "name": "governanceAccountType" + } + }, + { + "kind": "structFieldTypeNode", + "name": "proposal", + "docs": [], + "type": { + "kind": "publicKeyTypeNode" + } + }, + { + "kind": "structFieldTypeNode", + "name": "governingTokenOwner", + "docs": [], + "type": { + "kind": "publicKeyTypeNode" + } + }, + { + "kind": "structFieldTypeNode", + "name": "isRelinquished", + "docs": [], + "type": { + "kind": "booleanTypeNode", + "size": { + "kind": "numberTypeNode", + "format": "u8", + "endian": "le" + } + } + }, + { + "kind": "structFieldTypeNode", + "name": "voterWeight", + "docs": [], + "type": { + "kind": "numberTypeNode", + "format": "u64", + "endian": "le" + } + }, + { + "kind": "structFieldTypeNode", + "name": "vote", + "docs": [], + "type": { + "kind": "definedTypeLinkNode", + "name": "vote" + } + }, + { + "kind": "structFieldTypeNode", + "name": "reservedV2", + "docs": [], + "type": { + "kind": "arrayTypeNode", + "item": { + "kind": "numberTypeNode", + "format": "u8", + "endian": "le" + }, + "count": { + "kind": "fixedCountNode", + "value": 8 + } + } + } + ] + }, + "pda": { + "kind": "pdaLinkNode", + "name": "voteRecord" + } + } + ], + "instructions": [ + { + "kind": "instructionNode", + "name": "createRealm", + "docs": [], + "optionalAccountStrategy": "programId", + "accounts": [ + { + "kind": "instructionAccountNode", + "name": "realmAccount", + "isWritable": true, + "isSigner": false, + "isOptional": false, + "docs": [ + "Governance Realm account" + ] + }, + { + "kind": "instructionAccountNode", + "name": "realmAuthority", + "isWritable": false, + "isSigner": false, + "isOptional": false, + "docs": [ + "The authority of the Realm" + ] + }, + { + "kind": "instructionAccountNode", + "name": "communityTokenMint", + "isWritable": false, + "isSigner": false, + "isOptional": false, + "docs": [ + "The mint address of the token to be used as the community mint" + ] + }, + { + "kind": "instructionAccountNode", + "name": "communityTokenHoldingAccount", + "isWritable": true, + "isSigner": false, + "isOptional": false, + "docs": [ + "The account to hold the community tokens.", + " PDA seeds=['governance', realm, community_mint]" + ] + }, + { + "kind": "instructionAccountNode", + "name": "payer", + "isWritable": true, + "isSigner": true, + "isOptional": false, + "docs": [ + "the payer of this transaction" + ], + "defaultValue": { + "kind": "payerValueNode" + } + }, + { + "kind": "instructionAccountNode", + "name": "systemProgram", + "isWritable": false, + "isSigner": false, + "isOptional": false, + "docs": [ + "System Program" + ], + "defaultValue": { + "kind": "publicKeyValueNode", + "publicKey": "11111111111111111111111111111111", + "identifier": "systemProgram" + } + }, + { + "kind": "instructionAccountNode", + "name": "tokenProgram", + "isWritable": false, + "isSigner": false, + "isOptional": false, + "docs": [ + "SPL Token Program" + ], + "defaultValue": { + "kind": "publicKeyValueNode", + "publicKey": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA", + "identifier": "splToken" + } + }, + { + "kind": "instructionAccountNode", + "name": "rent", + "isWritable": false, + "isSigner": false, + "isOptional": false, + "docs": [ + "SysVar Rent" + ], + "defaultValue": { + "kind": "publicKeyValueNode", + "publicKey": "SysvarRent111111111111111111111111111111111" + } + }, + { + "kind": "instructionAccountNode", + "name": "councilTokenMint", + "isWritable": false, + "isSigner": false, + "isOptional": true, + "docs": [ + "The mint address of the token to be used as the council mint" + ] + }, + { + "kind": "instructionAccountNode", + "name": "councilTokenHoldingAccount", + "isWritable": true, + "isSigner": false, + "isOptional": true, + "docs": [ + "The account to hold the council tokens.", + " PDA seeds: ['governance',realm,council_mint]", + " " + ] + }, + { + "kind": "instructionAccountNode", + "name": "realmConfig", + "isWritable": true, + "isSigner": false, + "isOptional": false, + "docs": [ + "Realm Config account" + ] + }, + { + "kind": "instructionAccountNode", + "name": "communityVoterWeightAddin", + "isWritable": false, + "isSigner": false, + "isOptional": true, + "docs": [ + "Optional Community Voter Weight Addin Program Id" + ] + }, + { + "kind": "instructionAccountNode", + "name": "maxCommunityVoterWeightAddin", + "isWritable": false, + "isSigner": false, + "isOptional": true, + "docs": [ + "Optional Max Community Voter Weight Addin Program Id" + ] + }, + { + "kind": "instructionAccountNode", + "name": "councilVoterWeightAddin", + "isWritable": false, + "isSigner": false, + "isOptional": true, + "docs": [ + "Optional Council Voter Weight Addin Program Id" + ] + }, + { + "kind": "instructionAccountNode", + "name": "maxCouncilVoterWeightAddin", + "isWritable": false, + "isSigner": false, + "isOptional": true, + "docs": [ + "Optional Max Council Voter Weight Addin Program Id" + ] + } + ], + "arguments": [ + { + "kind": "instructionArgumentNode", + "name": "discriminator", + "defaultValueStrategy": "omitted", + "docs": [], + "type": { + "kind": "numberTypeNode", + "format": "u8", + "endian": "le" + }, + "defaultValue": { + "kind": "numberValueNode", + "number": 0 + } + }, + { + "kind": "instructionArgumentNode", + "name": "name", + "docs": [], + "type": { + "kind": "sizePrefixTypeNode", + "type": { + "kind": "stringTypeNode", + "encoding": "utf8" + }, + "prefix": { + "kind": "numberTypeNode", + "format": "u32", + "endian": "le" + } + } + }, + { + "kind": "instructionArgumentNode", + "name": "configArgs", + "docs": [], + "type": { + "kind": "definedTypeLinkNode", + "name": "realmConfigParams" + } + } + ], + "discriminators": [ + { + "kind": "fieldDiscriminatorNode", + "name": "discriminator", + "offset": 0 + } + ] + }, + { + "kind": "instructionNode", + "name": "depositGoverningTokens", + "docs": [], + "optionalAccountStrategy": "programId", + "accounts": [ + { + "kind": "instructionAccountNode", + "name": "realmAccount", + "isWritable": false, + "isSigner": false, + "isOptional": false, + "docs": [] + }, + { + "kind": "instructionAccountNode", + "name": "governingTokenHoldingAccount", + "isWritable": true, + "isSigner": false, + "isOptional": false, + "docs": [ + "seeds=['governance', realm, governing_token_mint]" + ] + }, + { + "kind": "instructionAccountNode", + "name": "governingTokenSourceAccount", + "isWritable": true, + "isSigner": false, + "isOptional": false, + "docs": [ + "It can either be spl-token TokenAccount or MintAccount. Tokens will be transferred or minted to the holding account" + ] + }, + { + "kind": "instructionAccountNode", + "name": "governingTokenOwnerAccount", + "isWritable": false, + "isSigner": true, + "isOptional": false, + "docs": [] + }, + { + "kind": "instructionAccountNode", + "name": "governingTokenSourceAccountAuthority", + "isWritable": false, + "isSigner": true, + "isOptional": false, + "docs": [ + "It should be owner for TokenAccount and mint_authority for MintAccount" + ] + }, + { + "kind": "instructionAccountNode", + "name": "tokenOwnerRecord", + "isWritable": true, + "isSigner": false, + "isOptional": false, + "docs": [ + "seeds=['governance', realm, governing_token_mint, governing_token_owner]" + ] + }, + { + "kind": "instructionAccountNode", + "name": "payer", + "isWritable": true, + "isSigner": true, + "isOptional": false, + "docs": [], + "defaultValue": { + "kind": "payerValueNode" + } + }, + { + "kind": "instructionAccountNode", + "name": "systemProgram", + "isWritable": false, + "isSigner": false, + "isOptional": false, + "docs": [], + "defaultValue": { + "kind": "publicKeyValueNode", + "publicKey": "11111111111111111111111111111111", + "identifier": "systemProgram" + } + }, + { + "kind": "instructionAccountNode", + "name": "tokenProgram", + "isWritable": false, + "isSigner": false, + "isOptional": false, + "docs": [], + "defaultValue": { + "kind": "publicKeyValueNode", + "publicKey": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA", + "identifier": "splToken" + } + }, + { + "kind": "instructionAccountNode", + "name": "realmConfigAccount", + "isWritable": false, + "isSigner": false, + "isOptional": false, + "docs": [ + "seeds=['realm-config', realm]" + ] + } + ], + "arguments": [ + { + "kind": "instructionArgumentNode", + "name": "discriminator", + "defaultValueStrategy": "omitted", + "docs": [], + "type": { + "kind": "numberTypeNode", + "format": "u8", + "endian": "le" + }, + "defaultValue": { + "kind": "numberValueNode", + "number": 1 + } + }, + { + "kind": "instructionArgumentNode", + "name": "amount", + "docs": [], + "type": { + "kind": "numberTypeNode", + "format": "u64", + "endian": "le" + } + } + ], + "discriminators": [ + { + "kind": "fieldDiscriminatorNode", + "name": "discriminator", + "offset": 0 + } + ] + }, + { + "kind": "instructionNode", + "name": "withdrawGoverningTokens", + "docs": [], + "optionalAccountStrategy": "programId", + "accounts": [ + { + "kind": "instructionAccountNode", + "name": "realmAccount", + "isWritable": false, + "isSigner": false, + "isOptional": false, + "docs": [] + }, + { + "kind": "instructionAccountNode", + "name": "governingTokenHoldingAccount", + "isWritable": true, + "isSigner": false, + "isOptional": false, + "docs": [ + "seeds=['governance', realm, governing_token_mint]" + ] + }, + { + "kind": "instructionAccountNode", + "name": "governingTokenDestinationAccount", + "isWritable": true, + "isSigner": false, + "isOptional": false, + "docs": [ + "All tokens will be transferred to this account" + ] + }, + { + "kind": "instructionAccountNode", + "name": "governingTokenOwnerAccount", + "isWritable": false, + "isSigner": true, + "isOptional": false, + "docs": [] + }, + { + "kind": "instructionAccountNode", + "name": "tokenOwnerRecord", + "isWritable": true, + "isSigner": false, + "isOptional": false, + "docs": [ + "seeds=['governance',realm, governing_token_mint, governing_token_owner]" + ] + }, + { + "kind": "instructionAccountNode", + "name": "tokenProgram", + "isWritable": false, + "isSigner": false, + "isOptional": false, + "docs": [], + "defaultValue": { + "kind": "publicKeyValueNode", + "publicKey": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA", + "identifier": "splToken" + } + }, + { + "kind": "instructionAccountNode", + "name": "realmConfigAccount", + "isWritable": false, + "isSigner": false, + "isOptional": false, + "docs": [ + "seeds=['realm-config', realm]" + ] + } + ], + "arguments": [ + { + "kind": "instructionArgumentNode", + "name": "discriminator", + "defaultValueStrategy": "omitted", + "docs": [], + "type": { + "kind": "numberTypeNode", + "format": "u8", + "endian": "le" + }, + "defaultValue": { + "kind": "numberValueNode", + "number": 2 + } + } + ], + "discriminators": [ + { + "kind": "fieldDiscriminatorNode", + "name": "discriminator", + "offset": 0 + } + ] + }, + { + "kind": "instructionNode", + "name": "setGovernanceDelegate", + "docs": [], + "optionalAccountStrategy": "programId", + "accounts": [ + { + "kind": "instructionAccountNode", + "name": "currentDelegateOrOwner", + "isWritable": false, + "isSigner": true, + "isOptional": false, + "docs": [ + "Current governance delegate or governing token owner" + ] + }, + { + "kind": "instructionAccountNode", + "name": "tokenOwnerRecord", + "isWritable": true, + "isSigner": false, + "isOptional": false, + "docs": [] + } + ], + "arguments": [ + { + "kind": "instructionArgumentNode", + "name": "discriminator", + "defaultValueStrategy": "omitted", + "docs": [], + "type": { + "kind": "numberTypeNode", + "format": "u8", + "endian": "le" + }, + "defaultValue": { + "kind": "numberValueNode", + "number": 3 + } + }, + { + "kind": "instructionArgumentNode", + "name": "newGovernanceDelegate", + "docs": [], + "type": { + "kind": "optionTypeNode", + "fixed": false, + "item": { + "kind": "publicKeyTypeNode" + }, + "prefix": { + "kind": "numberTypeNode", + "format": "u8", + "endian": "le" + } + } + } + ], + "discriminators": [ + { + "kind": "fieldDiscriminatorNode", + "name": "discriminator", + "offset": 0 + } + ] + }, + { + "kind": "instructionNode", + "name": "createGovernance", + "docs": [], + "optionalAccountStrategy": "programId", + "accounts": [ + { + "kind": "instructionAccountNode", + "name": "realmAccount", + "isWritable": false, + "isSigner": false, + "isOptional": false, + "docs": [ + "Realm account the created governance belongs to" + ] + }, + { + "kind": "instructionAccountNode", + "name": "governanceAccount", + "isWritable": true, + "isSigner": false, + "isOptional": false, + "docs": [ + "seeds=['account-governance', realm, governed_account]" + ] + }, + { + "kind": "instructionAccountNode", + "name": "governedAccount", + "isWritable": false, + "isSigner": false, + "isOptional": false, + "docs": [ + "Account governed by this Governance (governing_account). ", + " Note: the account doesn't have to exist and can be used only as a unique identified for the Governance account" + ] + }, + { + "kind": "instructionAccountNode", + "name": "governingTokenOwnerRecord", + "isWritable": false, + "isSigner": false, + "isOptional": false, + "docs": [ + "Used only if not signed by RealmAuthority" + ] + }, + { + "kind": "instructionAccountNode", + "name": "payer", + "isWritable": false, + "isSigner": true, + "isOptional": false, + "docs": [], + "defaultValue": { + "kind": "payerValueNode" + } + }, + { + "kind": "instructionAccountNode", + "name": "systemProgram", + "isWritable": false, + "isSigner": false, + "isOptional": false, + "docs": [], + "defaultValue": { + "kind": "publicKeyValueNode", + "publicKey": "11111111111111111111111111111111", + "identifier": "systemProgram" + } + }, + { + "kind": "instructionAccountNode", + "name": "governanceAuthority", + "isWritable": false, + "isSigner": true, + "isOptional": false, + "docs": [] + }, + { + "kind": "instructionAccountNode", + "name": "realmConfigAccount", + "isWritable": false, + "isSigner": false, + "isOptional": false, + "docs": [ + "seeds=['realm-config', realm]" + ] + }, + { + "kind": "instructionAccountNode", + "name": "voterWeightRecord", + "isWritable": false, + "isSigner": false, + "isOptional": true, + "docs": [ + "Optional Voter Weight Record" + ] + } + ], + "arguments": [ + { + "kind": "instructionArgumentNode", + "name": "discriminator", + "defaultValueStrategy": "omitted", + "docs": [], + "type": { + "kind": "numberTypeNode", + "format": "u8", + "endian": "le" + }, + "defaultValue": { + "kind": "numberValueNode", + "number": 4 + } + }, + { + "kind": "instructionArgumentNode", + "name": "config", + "docs": [], + "type": { + "kind": "definedTypeLinkNode", + "name": "governanceConfig" + } + } + ], + "discriminators": [ + { + "kind": "fieldDiscriminatorNode", + "name": "discriminator", + "offset": 0 + } + ] + }, + { + "kind": "instructionNode", + "name": "createProgramGovernance", + "docs": [], + "optionalAccountStrategy": "programId", + "accounts": [ + { + "kind": "instructionAccountNode", + "name": "realmAccount", + "isWritable": false, + "isSigner": false, + "isOptional": false, + "docs": [ + "Realm account the created Governance belongs to" + ] + }, + { + "kind": "instructionAccountNode", + "name": "programGovernanceAccount", + "isWritable": true, + "isSigner": false, + "isOptional": false, + "docs": [ + "Program Governance account. seeds: ['program-governance', realm, governed_program]" + ] + }, + { + "kind": "instructionAccountNode", + "name": "governedProgram", + "isWritable": false, + "isSigner": false, + "isOptional": false, + "docs": [ + "Program governed by this Governance account" + ] + }, + { + "kind": "instructionAccountNode", + "name": "programData", + "isWritable": true, + "isSigner": false, + "isOptional": false, + "docs": [ + "Program Data account of the Program governed by this Governance account" + ] + }, + { + "kind": "instructionAccountNode", + "name": "currentUpgradeAuthority", + "isWritable": false, + "isSigner": true, + "isOptional": false, + "docs": [ + "Current Upgrade Authority account of the Program governed by this Governance account" + ] + }, + { + "kind": "instructionAccountNode", + "name": "governingTokenOwnerRecord", + "isWritable": false, + "isSigner": false, + "isOptional": false, + "docs": [ + "Governing TokenOwnerRecord account (Used only if not signed by RealmAuthority)" + ] + }, + { + "kind": "instructionAccountNode", + "name": "payer", + "isWritable": false, + "isSigner": true, + "isOptional": false, + "docs": [], + "defaultValue": { + "kind": "payerValueNode" + } + }, + { + "kind": "instructionAccountNode", + "name": "bpfUpgradeableLoaderProgram", + "isWritable": false, + "isSigner": false, + "isOptional": false, + "docs": [ + "bpf_upgradeable_loader_program program" + ] + }, + { + "kind": "instructionAccountNode", + "name": "systemProgram", + "isWritable": false, + "isSigner": false, + "isOptional": false, + "docs": [], + "defaultValue": { + "kind": "publicKeyValueNode", + "publicKey": "11111111111111111111111111111111", + "identifier": "systemProgram" + } + }, + { + "kind": "instructionAccountNode", + "name": "governanceAuthority", + "isWritable": false, + "isSigner": true, + "isOptional": false, + "docs": [] + }, + { + "kind": "instructionAccountNode", + "name": "realmConfig", + "isWritable": false, + "isSigner": false, + "isOptional": false, + "docs": [ + "RealmConfig account. seeds=['realm-config', realm]" + ] + }, + { + "kind": "instructionAccountNode", + "name": "voterWeightRecord", + "isWritable": false, + "isSigner": false, + "isOptional": true, + "docs": [ + "Optional Voter Weight Record" + ] + } + ], + "arguments": [ + { + "kind": "instructionArgumentNode", + "name": "discriminator", + "defaultValueStrategy": "omitted", + "docs": [], + "type": { + "kind": "numberTypeNode", + "format": "u8", + "endian": "le" + }, + "defaultValue": { + "kind": "numberValueNode", + "number": 5 + } + }, + { + "kind": "instructionArgumentNode", + "name": "config", + "docs": [], + "type": { + "kind": "definedTypeLinkNode", + "name": "governanceConfig" + } + }, + { + "kind": "instructionArgumentNode", + "name": "transferUpgradeAuthority", + "docs": [], + "type": { + "kind": "booleanTypeNode", + "size": { + "kind": "numberTypeNode", + "format": "u8", + "endian": "le" + } + } + } + ], + "discriminators": [ + { + "kind": "fieldDiscriminatorNode", + "name": "discriminator", + "offset": 0 + } + ] + }, + { + "kind": "instructionNode", + "name": "createProposal", + "docs": [], + "optionalAccountStrategy": "programId", + "accounts": [ + { + "kind": "instructionAccountNode", + "name": "realmAccount", + "isWritable": false, + "isSigner": false, + "isOptional": false, + "docs": [ + "Realm account the created Proposal belongs to" + ] + }, + { + "kind": "instructionAccountNode", + "name": "proposalAccount", + "isWritable": true, + "isSigner": false, + "isOptional": false, + "docs": [ + "Proposal account. PDA seeds ['governance',governance, governing_token_mint, proposal_index]" + ] + }, + { + "kind": "instructionAccountNode", + "name": "governanceAccount", + "isWritable": true, + "isSigner": false, + "isOptional": false, + "docs": [ + "Governance account" + ] + }, + { + "kind": "instructionAccountNode", + "name": "tokenOwnerRecord", + "isWritable": true, + "isSigner": false, + "isOptional": false, + "docs": [ + "TokenOwnerRecord account of the Proposal owner" + ] + }, + { + "kind": "instructionAccountNode", + "name": "governingTokenMint", + "isWritable": false, + "isSigner": false, + "isOptional": false, + "docs": [ + "Token Mint the Proposal is created for" + ] + }, + { + "kind": "instructionAccountNode", + "name": "governanceAuthority", + "isWritable": false, + "isSigner": true, + "isOptional": false, + "docs": [ + "Governance Authority (Token Owner or Governance Delegate)" + ] + }, + { + "kind": "instructionAccountNode", + "name": "payer", + "isWritable": false, + "isSigner": true, + "isOptional": false, + "docs": [], + "defaultValue": { + "kind": "payerValueNode" + } + }, + { + "kind": "instructionAccountNode", + "name": "systemProgram", + "isWritable": false, + "isSigner": false, + "isOptional": false, + "docs": [], + "defaultValue": { + "kind": "publicKeyValueNode", + "publicKey": "11111111111111111111111111111111", + "identifier": "systemProgram" + } + }, + { + "kind": "instructionAccountNode", + "name": "realmConfig", + "isWritable": false, + "isSigner": false, + "isOptional": false, + "docs": [ + "RealmConfig account. PDA seeds: ['realm-config', realm]" + ] + }, + { + "kind": "instructionAccountNode", + "name": "voterWeightRecord", + "isWritable": true, + "isSigner": false, + "isOptional": true, + "docs": [ + "Optional Voter Weight Record" + ] + }, + { + "kind": "instructionAccountNode", + "name": "proposalDepositAccount", + "isWritable": false, + "isSigner": false, + "isOptional": true, + "docs": [ + "Optional Proposal deposit is required when there are more active ", + " proposals than the configured deposit exempt amount. ", + " PDA seeds: ['proposal-deposit', proposal, deposit payer]" + ] + } + ], + "arguments": [ + { + "kind": "instructionArgumentNode", + "name": "discriminator", + "defaultValueStrategy": "omitted", + "docs": [], + "type": { + "kind": "numberTypeNode", + "format": "u8", + "endian": "le" + }, + "defaultValue": { + "kind": "numberValueNode", + "number": 6 + } + }, + { + "kind": "instructionArgumentNode", + "name": "name", + "docs": [], + "type": { + "kind": "sizePrefixTypeNode", + "type": { + "kind": "stringTypeNode", + "encoding": "utf8" + }, + "prefix": { + "kind": "numberTypeNode", + "format": "u32", + "endian": "le" + } + } + }, + { + "kind": "instructionArgumentNode", + "name": "descriptionLink", + "docs": [], + "type": { + "kind": "sizePrefixTypeNode", + "type": { + "kind": "stringTypeNode", + "encoding": "utf8" + }, + "prefix": { + "kind": "numberTypeNode", + "format": "u32", + "endian": "le" + } + } + }, + { + "kind": "instructionArgumentNode", + "name": "voteType", + "docs": [], + "type": { + "kind": "definedTypeLinkNode", + "name": "voteType" + } + }, + { + "kind": "instructionArgumentNode", + "name": "options", + "docs": [], + "type": { + "kind": "arrayTypeNode", + "item": { + "kind": "sizePrefixTypeNode", + "type": { + "kind": "stringTypeNode", + "encoding": "utf8" + }, + "prefix": { + "kind": "numberTypeNode", + "format": "u32", + "endian": "le" + } + }, + "count": { + "kind": "prefixedCountNode", + "prefix": { + "kind": "numberTypeNode", + "format": "u32", + "endian": "le" + } + } + } + }, + { + "kind": "instructionArgumentNode", + "name": "useDenyOption", + "docs": [], + "type": { + "kind": "booleanTypeNode", + "size": { + "kind": "numberTypeNode", + "format": "u8", + "endian": "le" + } + } + }, + { + "kind": "instructionArgumentNode", + "name": "proposalSeed", + "docs": [], + "type": { + "kind": "publicKeyTypeNode" + } + } + ], + "discriminators": [ + { + "kind": "fieldDiscriminatorNode", + "name": "discriminator", + "offset": 0 + } + ] + }, + { + "kind": "instructionNode", + "name": "addSignatory", + "docs": [], + "optionalAccountStrategy": "programId", + "accounts": [ + { + "kind": "instructionAccountNode", + "name": "proposalAccount", + "isWritable": true, + "isSigner": false, + "isOptional": false, + "docs": [ + "Proposal Account associated with the governance" + ] + }, + { + "kind": "instructionAccountNode", + "name": "tokenOwnerRecord", + "isWritable": false, + "isSigner": false, + "isOptional": false, + "docs": [ + "TokenOwnerRecord account of the Proposal owner" + ] + }, + { + "kind": "instructionAccountNode", + "name": "governanceAuthority", + "isWritable": false, + "isSigner": true, + "isOptional": false, + "docs": [ + "Governance Authority (Token Owner or Governance Delegate)" + ] + }, + { + "kind": "instructionAccountNode", + "name": "signatoryRecordAccount", + "isWritable": true, + "isSigner": false, + "isOptional": false, + "docs": [ + "Signatory Record Account" + ] + }, + { + "kind": "instructionAccountNode", + "name": "payer", + "isWritable": false, + "isSigner": true, + "isOptional": false, + "docs": [], + "defaultValue": { + "kind": "payerValueNode" + } + }, + { + "kind": "instructionAccountNode", + "name": "systemProgram", + "isWritable": false, + "isSigner": false, + "isOptional": false, + "docs": [], + "defaultValue": { + "kind": "publicKeyValueNode", + "publicKey": "11111111111111111111111111111111", + "identifier": "systemProgram" + } + } + ], + "arguments": [ + { + "kind": "instructionArgumentNode", + "name": "discriminator", + "defaultValueStrategy": "omitted", + "docs": [], + "type": { + "kind": "numberTypeNode", + "format": "u8", + "endian": "le" + }, + "defaultValue": { + "kind": "numberValueNode", + "number": 7 + } + }, + { + "kind": "instructionArgumentNode", + "name": "signatory", + "docs": [], + "type": { + "kind": "publicKeyTypeNode" + } + } + ], + "discriminators": [ + { + "kind": "fieldDiscriminatorNode", + "name": "discriminator", + "offset": 0 + } + ] + }, + { + "kind": "instructionNode", + "name": "legacy1", + "docs": [], + "optionalAccountStrategy": "programId", + "accounts": [], + "arguments": [ + { + "kind": "instructionArgumentNode", + "name": "discriminator", + "defaultValueStrategy": "omitted", + "docs": [], + "type": { + "kind": "numberTypeNode", + "format": "u8", + "endian": "le" + }, + "defaultValue": { + "kind": "numberValueNode", + "number": 8 + } + } + ], + "discriminators": [ + { + "kind": "fieldDiscriminatorNode", + "name": "discriminator", + "offset": 0 + } + ] + }, + { + "kind": "instructionNode", + "name": "insertTransaction", + "docs": [], + "optionalAccountStrategy": "programId", + "accounts": [ + { + "kind": "instructionAccountNode", + "name": "governanceAccount", + "isWritable": false, + "isSigner": false, + "isOptional": false, + "docs": [] + }, + { + "kind": "instructionAccountNode", + "name": "proposalAccount", + "isWritable": true, + "isSigner": false, + "isOptional": false, + "docs": [] + }, + { + "kind": "instructionAccountNode", + "name": "tokenOwnerRecord", + "isWritable": false, + "isSigner": false, + "isOptional": false, + "docs": [ + "TokenOwnerRecord account of the Proposal owner" + ] + }, + { + "kind": "instructionAccountNode", + "name": "governanceAuthority", + "isWritable": false, + "isSigner": true, + "isOptional": false, + "docs": [ + "Governance Authority (Token Owner or Governance Delegate)" + ] + }, + { + "kind": "instructionAccountNode", + "name": "proposalTransactionAccount", + "isWritable": true, + "isSigner": false, + "isOptional": false, + "docs": [ + "ProposalTransaction, account. PDA seeds: ['governance', proposal, option_index, index]" + ] + }, + { + "kind": "instructionAccountNode", + "name": "payer", + "isWritable": false, + "isSigner": true, + "isOptional": false, + "docs": [], + "defaultValue": { + "kind": "payerValueNode" + } + }, + { + "kind": "instructionAccountNode", + "name": "systemProgram", + "isWritable": false, + "isSigner": false, + "isOptional": false, + "docs": [], + "defaultValue": { + "kind": "publicKeyValueNode", + "publicKey": "11111111111111111111111111111111", + "identifier": "systemProgram" + } + }, + { + "kind": "instructionAccountNode", + "name": "rent", + "isWritable": false, + "isSigner": false, + "isOptional": false, + "docs": [], + "defaultValue": { + "kind": "publicKeyValueNode", + "publicKey": "SysvarRent111111111111111111111111111111111" + } + } + ], + "arguments": [ + { + "kind": "instructionArgumentNode", + "name": "discriminator", + "defaultValueStrategy": "omitted", + "docs": [], + "type": { + "kind": "numberTypeNode", + "format": "u8", + "endian": "le" + }, + "defaultValue": { + "kind": "numberValueNode", + "number": 9 + } + }, + { + "kind": "instructionArgumentNode", + "name": "optionIndex", + "docs": [], + "type": { + "kind": "numberTypeNode", + "format": "u8", + "endian": "le" + } + }, + { + "kind": "instructionArgumentNode", + "name": "index", + "docs": [], + "type": { + "kind": "numberTypeNode", + "format": "u16", + "endian": "le" + } + }, + { + "kind": "instructionArgumentNode", + "name": "holdUpTime", + "docs": [], + "type": { + "kind": "numberTypeNode", + "format": "u32", + "endian": "le" + } + }, + { + "kind": "instructionArgumentNode", + "name": "instructions", + "docs": [], + "type": { + "kind": "arrayTypeNode", + "item": { + "kind": "definedTypeLinkNode", + "name": "instructionData" + }, + "count": { + "kind": "prefixedCountNode", + "prefix": { + "kind": "numberTypeNode", + "format": "u32", + "endian": "le" + } + } + } + } + ], + "discriminators": [ + { + "kind": "fieldDiscriminatorNode", + "name": "discriminator", + "offset": 0 + } + ] + }, + { + "kind": "instructionNode", + "name": "removeTransaction", + "docs": [], + "optionalAccountStrategy": "programId", + "accounts": [ + { + "kind": "instructionAccountNode", + "name": "proposalAccount", + "isWritable": true, + "isSigner": false, + "isOptional": false, + "docs": [] + }, + { + "kind": "instructionAccountNode", + "name": "tokenOwnerRecord", + "isWritable": false, + "isSigner": false, + "isOptional": false, + "docs": [ + "TokenOwnerRecord account of the Proposal owner" + ] + }, + { + "kind": "instructionAccountNode", + "name": "governanceAuthority", + "isWritable": false, + "isSigner": true, + "isOptional": false, + "docs": [ + "Governance Authority (Token Owner or Governance Delegate)" + ] + }, + { + "kind": "instructionAccountNode", + "name": "proposalTransactionAccount", + "isWritable": true, + "isSigner": false, + "isOptional": false, + "docs": [] + }, + { + "kind": "instructionAccountNode", + "name": "beneficiaryAccount", + "isWritable": true, + "isSigner": false, + "isOptional": false, + "docs": [ + "Beneficiary Account which would receive lamports from the disposed ProposalTransaction account" + ] + } + ], + "arguments": [ + { + "kind": "instructionArgumentNode", + "name": "discriminator", + "defaultValueStrategy": "omitted", + "docs": [], + "type": { + "kind": "numberTypeNode", + "format": "u8", + "endian": "le" + }, + "defaultValue": { + "kind": "numberValueNode", + "number": 10 + } + } + ], + "discriminators": [ + { + "kind": "fieldDiscriminatorNode", + "name": "discriminator", + "offset": 0 + } + ] + }, + { + "kind": "instructionNode", + "name": "cancelProposal", + "docs": [], + "optionalAccountStrategy": "programId", + "accounts": [ + { + "kind": "instructionAccountNode", + "name": "realmAccount", + "isWritable": true, + "isSigner": false, + "isOptional": false, + "docs": [] + }, + { + "kind": "instructionAccountNode", + "name": "governanceAccount", + "isWritable": true, + "isSigner": false, + "isOptional": false, + "docs": [] + }, + { + "kind": "instructionAccountNode", + "name": "proposalAccount", + "isWritable": true, + "isSigner": false, + "isOptional": false, + "docs": [] + }, + { + "kind": "instructionAccountNode", + "name": "tokenOwnerRecord", + "isWritable": true, + "isSigner": false, + "isOptional": false, + "docs": [ + "TokenOwnerRecord account of the Proposal owner" + ] + }, + { + "kind": "instructionAccountNode", + "name": "governanceAuthority", + "isWritable": false, + "isSigner": true, + "isOptional": false, + "docs": [ + "Governance authority (Token Owner or Governance Delegate)" + ] + } + ], + "arguments": [ + { + "kind": "instructionArgumentNode", + "name": "discriminator", + "defaultValueStrategy": "omitted", + "docs": [], + "type": { + "kind": "numberTypeNode", + "format": "u8", + "endian": "le" + }, + "defaultValue": { + "kind": "numberValueNode", + "number": 11 + } + } + ], + "discriminators": [ + { + "kind": "fieldDiscriminatorNode", + "name": "discriminator", + "offset": 0 + } + ] + }, + { + "kind": "instructionNode", + "name": "signOffProposal", + "docs": [], + "optionalAccountStrategy": "programId", + "accounts": [ + { + "kind": "instructionAccountNode", + "name": "realmAccount", + "isWritable": false, + "isSigner": false, + "isOptional": false, + "docs": [] + }, + { + "kind": "instructionAccountNode", + "name": "governanceAccount", + "isWritable": false, + "isSigner": false, + "isOptional": false, + "docs": [] + }, + { + "kind": "instructionAccountNode", + "name": "proposalAccount", + "isWritable": true, + "isSigner": false, + "isOptional": false, + "docs": [] + }, + { + "kind": "instructionAccountNode", + "name": "signatoryAccount", + "isWritable": false, + "isSigner": true, + "isOptional": false, + "docs": [ + "Signatory account signing off the Proposal.", + " Or Proposal owner if the owner hasn't appointed any signatories" + ] + }, + { + "kind": "instructionAccountNode", + "name": "tokenOwnerRecord", + "isWritable": true, + "isSigner": false, + "isOptional": false, + "docs": [ + "TokenOwnerRecord for the Proposal owner, required when the owner signs off the Proposal.", + " Or `[writable]` SignatoryRecord account, required when non owner signs off the Proposal" + ] + } + ], + "arguments": [ + { + "kind": "instructionArgumentNode", + "name": "discriminator", + "defaultValueStrategy": "omitted", + "docs": [], + "type": { + "kind": "numberTypeNode", + "format": "u8", + "endian": "le" + }, + "defaultValue": { + "kind": "numberValueNode", + "number": 12 + } + } + ], + "discriminators": [ + { + "kind": "fieldDiscriminatorNode", + "name": "discriminator", + "offset": 0 + } + ] + }, + { + "kind": "instructionNode", + "name": "castVote", + "docs": [], + "optionalAccountStrategy": "programId", + "accounts": [ + { + "kind": "instructionAccountNode", + "name": "realmAccount", + "isWritable": false, + "isSigner": false, + "isOptional": false, + "docs": [] + }, + { + "kind": "instructionAccountNode", + "name": "governanceAccount", + "isWritable": true, + "isSigner": false, + "isOptional": false, + "docs": [] + }, + { + "kind": "instructionAccountNode", + "name": "proposalAccount", + "isWritable": true, + "isSigner": false, + "isOptional": false, + "docs": [] + }, + { + "kind": "instructionAccountNode", + "name": "proposalTokenOwnerRecord", + "isWritable": true, + "isSigner": false, + "isOptional": false, + "docs": [ + "TokenOwnerRecord of the Proposal owner" + ] + }, + { + "kind": "instructionAccountNode", + "name": "voterTokenOwnerRecord", + "isWritable": true, + "isSigner": false, + "isOptional": false, + "docs": [ + "TokenOwnerRecord of the voter. PDA seeds: ['governance',realm, vote_governing_token_mint, governing_token_owner]" + ] + }, + { + "kind": "instructionAccountNode", + "name": "governanceAuthority", + "isWritable": false, + "isSigner": true, + "isOptional": false, + "docs": [ + "Governance Authority (Token Owner or Governance Delegate)" + ] + }, + { + "kind": "instructionAccountNode", + "name": "proposalVoteRecord", + "isWritable": true, + "isSigner": false, + "isOptional": false, + "docs": [ + "Proposal VoteRecord account. PDA seeds: ['governance',proposal,token_owner_record]" + ] + }, + { + "kind": "instructionAccountNode", + "name": "governingTokenMint", + "isWritable": false, + "isSigner": false, + "isOptional": false, + "docs": [ + "The Governing Token Mint which is used to cast the vote (vote_governing_token_mint).", + " The voting token mint is the governing_token_mint of the Proposal for Approve, Deny and Abstain votes.", + " For Veto vote the voting token mint is the mint of the opposite voting population.", + " Council mint to veto Community proposals and Community mint to veto Council proposals", + " Note: In the current version only Council veto is supported" + ] + }, + { + "kind": "instructionAccountNode", + "name": "payer", + "isWritable": false, + "isSigner": true, + "isOptional": false, + "docs": [], + "defaultValue": { + "kind": "payerValueNode" + } + }, + { + "kind": "instructionAccountNode", + "name": "systemProgram", + "isWritable": false, + "isSigner": false, + "isOptional": false, + "docs": [], + "defaultValue": { + "kind": "publicKeyValueNode", + "publicKey": "11111111111111111111111111111111", + "identifier": "systemProgram" + } + }, + { + "kind": "instructionAccountNode", + "name": "realmConfigAccount", + "isWritable": false, + "isSigner": false, + "isOptional": false, + "docs": [ + "RealmConfig account. PDA seeds: ['realm-config', realm]" + ] + }, + { + "kind": "instructionAccountNode", + "name": "voterWeightRecord", + "isWritable": false, + "isSigner": false, + "isOptional": true, + "docs": [ + "Optional Voter Weight Record" + ] + }, + { + "kind": "instructionAccountNode", + "name": "maxVoterWeightRecord", + "isWritable": false, + "isSigner": false, + "isOptional": true, + "docs": [ + "Optional Max Voter Weight Record" + ] + } + ], + "arguments": [ + { + "kind": "instructionArgumentNode", + "name": "discriminator", + "defaultValueStrategy": "omitted", + "docs": [], + "type": { + "kind": "numberTypeNode", + "format": "u8", + "endian": "le" + }, + "defaultValue": { + "kind": "numberValueNode", + "number": 13 + } + }, + { + "kind": "instructionArgumentNode", + "name": "vote", + "docs": [], + "type": { + "kind": "definedTypeLinkNode", + "name": "vote" + } + } + ], + "discriminators": [ + { + "kind": "fieldDiscriminatorNode", + "name": "discriminator", + "offset": 0 + } + ] + }, + { + "kind": "instructionNode", + "name": "finalizeVote", + "docs": [], + "optionalAccountStrategy": "programId", + "accounts": [ + { + "kind": "instructionAccountNode", + "name": "realmAccount", + "isWritable": false, + "isSigner": false, + "isOptional": false, + "docs": [] + }, + { + "kind": "instructionAccountNode", + "name": "governanceAccount", + "isWritable": true, + "isSigner": false, + "isOptional": false, + "docs": [] + }, + { + "kind": "instructionAccountNode", + "name": "proposalAccount", + "isWritable": true, + "isSigner": false, + "isOptional": false, + "docs": [] + }, + { + "kind": "instructionAccountNode", + "name": "tokenOwnerRecord", + "isWritable": true, + "isSigner": false, + "isOptional": false, + "docs": [ + "TokenOwnerRecord of the Proposal owner" + ] + }, + { + "kind": "instructionAccountNode", + "name": "governingTokenMint", + "isWritable": false, + "isSigner": false, + "isOptional": false, + "docs": [] + }, + { + "kind": "instructionAccountNode", + "name": "realmConfig", + "isWritable": false, + "isSigner": false, + "isOptional": false, + "docs": [ + "RealmConfig account. PDA seeds: ['realm-config', realm]" + ] + }, + { + "kind": "instructionAccountNode", + "name": "maxVoterWeightRecord", + "isWritable": false, + "isSigner": false, + "isOptional": true, + "docs": [ + "Optional Max Voter Weight Record" + ] + } + ], + "arguments": [ + { + "kind": "instructionArgumentNode", + "name": "discriminator", + "defaultValueStrategy": "omitted", + "docs": [], + "type": { + "kind": "numberTypeNode", + "format": "u8", + "endian": "le" + }, + "defaultValue": { + "kind": "numberValueNode", + "number": 14 + } + } + ], + "discriminators": [ + { + "kind": "fieldDiscriminatorNode", + "name": "discriminator", + "offset": 0 + } + ] + }, + { + "kind": "instructionNode", + "name": "relinquishVote", + "docs": [], + "optionalAccountStrategy": "programId", + "accounts": [ + { + "kind": "instructionAccountNode", + "name": "realmAccount", + "isWritable": false, + "isSigner": false, + "isOptional": false, + "docs": [] + }, + { + "kind": "instructionAccountNode", + "name": "governanceAccount", + "isWritable": false, + "isSigner": false, + "isOptional": false, + "docs": [] + }, + { + "kind": "instructionAccountNode", + "name": "proposalAccount", + "isWritable": true, + "isSigner": false, + "isOptional": false, + "docs": [] + }, + { + "kind": "instructionAccountNode", + "name": "tokenOwnerRecord", + "isWritable": true, + "isSigner": false, + "isOptional": false, + "docs": [ + "TokenOwnerRecord account. PDA seeds: ['governance',realm, vote_governing_token_mint, governing_token_owner]" + ] + }, + { + "kind": "instructionAccountNode", + "name": "proposalVoteRecord", + "isWritable": true, + "isSigner": false, + "isOptional": false, + "docs": [ + "Proposal VoteRecord account. PDA seeds: ['governance',proposal, token_owner_record]" + ] + }, + { + "kind": "instructionAccountNode", + "name": "governingTokenMint", + "isWritable": false, + "isSigner": false, + "isOptional": false, + "docs": [ + "The Governing Token Mint which was used to cast the vote (vote_governing_token_mint)" + ] + }, + { + "kind": "instructionAccountNode", + "name": "governanceAuthority", + "isWritable": false, + "isSigner": true, + "isOptional": true, + "docs": [] + }, + { + "kind": "instructionAccountNode", + "name": "beneficiaryAccount", + "isWritable": true, + "isSigner": false, + "isOptional": true, + "docs": [ + "Optional Beneficiary account which would receive lamports when VoteRecord Account is disposed.", + " It's required only when Proposal is still being voted on" + ] + } + ], + "arguments": [ + { + "kind": "instructionArgumentNode", + "name": "discriminator", + "defaultValueStrategy": "omitted", + "docs": [], + "type": { + "kind": "numberTypeNode", + "format": "u8", + "endian": "le" + }, + "defaultValue": { + "kind": "numberValueNode", + "number": 15 + } + } + ], + "discriminators": [ + { + "kind": "fieldDiscriminatorNode", + "name": "discriminator", + "offset": 0 + } + ] + }, + { + "kind": "instructionNode", + "name": "executeTransaction", + "docs": [], + "optionalAccountStrategy": "programId", + "accounts": [ + { + "kind": "instructionAccountNode", + "name": "governanceAccount", + "isWritable": false, + "isSigner": false, + "isOptional": false, + "docs": [] + }, + { + "kind": "instructionAccountNode", + "name": "proposalAccount", + "isWritable": true, + "isSigner": false, + "isOptional": false, + "docs": [] + }, + { + "kind": "instructionAccountNode", + "name": "proposalTransactionAccount", + "isWritable": true, + "isSigner": false, + "isOptional": false, + "docs": [] + } + ], + "arguments": [ + { + "kind": "instructionArgumentNode", + "name": "discriminator", + "defaultValueStrategy": "omitted", + "docs": [], + "type": { + "kind": "numberTypeNode", + "format": "u8", + "endian": "le" + }, + "defaultValue": { + "kind": "numberValueNode", + "number": 16 + } + } + ], + "discriminators": [ + { + "kind": "fieldDiscriminatorNode", + "name": "discriminator", + "offset": 0 + } + ] + }, + { + "kind": "instructionNode", + "name": "createMintGovernance", + "docs": [], + "optionalAccountStrategy": "programId", + "accounts": [ + { + "kind": "instructionAccountNode", + "name": "realmAccount", + "isWritable": false, + "isSigner": false, + "isOptional": false, + "docs": [ + "Realm account the created Governance belongs to" + ] + }, + { + "kind": "instructionAccountNode", + "name": "mintGovernanceAccount", + "isWritable": true, + "isSigner": false, + "isOptional": false, + "docs": [ + "Mint Governance account. seeds=['mint-governance', realm, governed_mint]" + ] + }, + { + "kind": "instructionAccountNode", + "name": "governedMint", + "isWritable": true, + "isSigner": false, + "isOptional": false, + "docs": [ + "Mint governed by this Governance account" + ] + }, + { + "kind": "instructionAccountNode", + "name": "mintAuthority", + "isWritable": false, + "isSigner": true, + "isOptional": false, + "docs": [ + "Current Mint authority (MintTokens and optionally FreezeAccount)" + ] + }, + { + "kind": "instructionAccountNode", + "name": "governingTokenOwnerRecord", + "isWritable": false, + "isSigner": false, + "isOptional": false, + "docs": [ + "Governing TokenOwnerRecord account (Used only if not signed by RealmAuthority)" + ] + }, + { + "kind": "instructionAccountNode", + "name": "payer", + "isWritable": false, + "isSigner": true, + "isOptional": false, + "docs": [], + "defaultValue": { + "kind": "payerValueNode" + } + }, + { + "kind": "instructionAccountNode", + "name": "tokenProgram", + "isWritable": false, + "isSigner": false, + "isOptional": false, + "docs": [], + "defaultValue": { + "kind": "publicKeyValueNode", + "publicKey": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA", + "identifier": "splToken" + } + }, + { + "kind": "instructionAccountNode", + "name": "systemProgram", + "isWritable": false, + "isSigner": false, + "isOptional": false, + "docs": [], + "defaultValue": { + "kind": "publicKeyValueNode", + "publicKey": "11111111111111111111111111111111", + "identifier": "systemProgram" + } + }, + { + "kind": "instructionAccountNode", + "name": "governanceAuthority", + "isWritable": false, + "isSigner": true, + "isOptional": false, + "docs": [] + }, + { + "kind": "instructionAccountNode", + "name": "realmConfig", + "isWritable": false, + "isSigner": false, + "isOptional": false, + "docs": [ + "RealmConfig account. seeds=['realm-config', realm]" + ] + }, + { + "kind": "instructionAccountNode", + "name": "voterWeightRecord", + "isWritable": false, + "isSigner": false, + "isOptional": true, + "docs": [ + "Optional Voter Weight Record" + ] + } + ], + "arguments": [ + { + "kind": "instructionArgumentNode", + "name": "discriminator", + "defaultValueStrategy": "omitted", + "docs": [], + "type": { + "kind": "numberTypeNode", + "format": "u8", + "endian": "le" + }, + "defaultValue": { + "kind": "numberValueNode", + "number": 17 + } + }, + { + "kind": "instructionArgumentNode", + "name": "config", + "docs": [], + "type": { + "kind": "definedTypeLinkNode", + "name": "governanceConfig" + } + }, + { + "kind": "instructionArgumentNode", + "name": "transferMintAuthorities", + "docs": [], + "type": { + "kind": "booleanTypeNode", + "size": { + "kind": "numberTypeNode", + "format": "u8", + "endian": "le" + } + } + } + ], + "discriminators": [ + { + "kind": "fieldDiscriminatorNode", + "name": "discriminator", + "offset": 0 + } + ] + }, + { + "kind": "instructionNode", + "name": "createTokenGovernance", + "docs": [], + "optionalAccountStrategy": "programId", + "accounts": [ + { + "kind": "instructionAccountNode", + "name": "realmAccount", + "isWritable": false, + "isSigner": false, + "isOptional": false, + "docs": [ + "Realm account the created Governance belongs to" + ] + }, + { + "kind": "instructionAccountNode", + "name": "tokenGovernanceAccount", + "isWritable": true, + "isSigner": false, + "isOptional": false, + "docs": [ + "Token Governance account. seeds=['token-governance', realm, governed_token]" + ] + }, + { + "kind": "instructionAccountNode", + "name": "tokenAccount", + "isWritable": true, + "isSigner": false, + "isOptional": false, + "docs": [ + "Token account governed by this Governance account" + ] + }, + { + "kind": "instructionAccountNode", + "name": "tokenAccountAuthority", + "isWritable": false, + "isSigner": true, + "isOptional": false, + "docs": [ + "Current token account authority (AccountOwner and optionally CloseAccount" + ] + }, + { + "kind": "instructionAccountNode", + "name": "governingTokenOwnerRecord", + "isWritable": false, + "isSigner": false, + "isOptional": false, + "docs": [ + "Governing TokenOwnerRecord account (Used only if not signed by RealmAuthority" + ] + }, + { + "kind": "instructionAccountNode", + "name": "payer", + "isWritable": false, + "isSigner": true, + "isOptional": false, + "docs": [], + "defaultValue": { + "kind": "payerValueNode" + } + }, + { + "kind": "instructionAccountNode", + "name": "tokenProgram", + "isWritable": false, + "isSigner": false, + "isOptional": false, + "docs": [], + "defaultValue": { + "kind": "publicKeyValueNode", + "publicKey": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA", + "identifier": "splToken" + } + }, + { + "kind": "instructionAccountNode", + "name": "systemProgram", + "isWritable": false, + "isSigner": false, + "isOptional": false, + "docs": [], + "defaultValue": { + "kind": "publicKeyValueNode", + "publicKey": "11111111111111111111111111111111", + "identifier": "systemProgram" + } + }, + { + "kind": "instructionAccountNode", + "name": "governanceAuthority", + "isWritable": false, + "isSigner": true, + "isOptional": false, + "docs": [] + }, + { + "kind": "instructionAccountNode", + "name": "realmConfig", + "isWritable": false, + "isSigner": false, + "isOptional": false, + "docs": [ + "seeds=['realm-config', realm]" + ] + }, + { + "kind": "instructionAccountNode", + "name": "voterWeightRecord", + "isWritable": false, + "isSigner": false, + "isOptional": true, + "docs": [ + "Optional Voter Weight Record" + ] + } + ], + "arguments": [ + { + "kind": "instructionArgumentNode", + "name": "discriminator", + "defaultValueStrategy": "omitted", + "docs": [], + "type": { + "kind": "numberTypeNode", + "format": "u8", + "endian": "le" + }, + "defaultValue": { + "kind": "numberValueNode", + "number": 18 + } + }, + { + "kind": "instructionArgumentNode", + "name": "config", + "docs": [], + "type": { + "kind": "definedTypeLinkNode", + "name": "governanceConfig" + } + }, + { + "kind": "instructionArgumentNode", + "name": "transferAccountAuthorities", + "docs": [], + "type": { + "kind": "booleanTypeNode", + "size": { + "kind": "numberTypeNode", + "format": "u8", + "endian": "le" + } + } + } + ], + "discriminators": [ + { + "kind": "fieldDiscriminatorNode", + "name": "discriminator", + "offset": 0 + } + ] + }, + { + "kind": "instructionNode", + "name": "setGovernanceConfig", + "docs": [], + "optionalAccountStrategy": "programId", + "accounts": [ + { + "kind": "instructionAccountNode", + "name": "governanceAccount", + "isWritable": true, + "isSigner": true, + "isOptional": false, + "docs": [ + "The governance account the config is for" + ] + } + ], + "arguments": [ + { + "kind": "instructionArgumentNode", + "name": "discriminator", + "defaultValueStrategy": "omitted", + "docs": [], + "type": { + "kind": "numberTypeNode", + "format": "u8", + "endian": "le" + }, + "defaultValue": { + "kind": "numberValueNode", + "number": 19 + } + }, + { + "kind": "instructionArgumentNode", + "name": "config", + "docs": [], + "type": { + "kind": "definedTypeLinkNode", + "name": "governanceConfig" + } + } + ], + "discriminators": [ + { + "kind": "fieldDiscriminatorNode", + "name": "discriminator", + "offset": 0 + } + ] + }, + { + "kind": "instructionNode", + "name": "flagTransactionError", + "docs": [], + "optionalAccountStrategy": "programId", + "accounts": [ + { + "kind": "instructionAccountNode", + "name": "proposalAccount", + "isWritable": true, + "isSigner": false, + "isOptional": false, + "docs": [] + }, + { + "kind": "instructionAccountNode", + "name": "tokenOwnerRecord", + "isWritable": false, + "isSigner": false, + "isOptional": false, + "docs": [ + "TokenOwnerRecord account of the Proposal owner" + ] + }, + { + "kind": "instructionAccountNode", + "name": "governanceAuthority", + "isWritable": false, + "isSigner": true, + "isOptional": false, + "docs": [ + "Governance Authority (Token Owner or Governance Delegate)" + ] + }, + { + "kind": "instructionAccountNode", + "name": "proposalTransactionAccount", + "isWritable": true, + "isSigner": false, + "isOptional": false, + "docs": [ + "ProposalTransaction account to flag" + ] + } + ], + "arguments": [ + { + "kind": "instructionArgumentNode", + "name": "discriminator", + "defaultValueStrategy": "omitted", + "docs": [], + "type": { + "kind": "numberTypeNode", + "format": "u8", + "endian": "le" + }, + "defaultValue": { + "kind": "numberValueNode", + "number": 20 + } + } + ], + "discriminators": [ + { + "kind": "fieldDiscriminatorNode", + "name": "discriminator", + "offset": 0 + } + ] + }, + { + "kind": "instructionNode", + "name": "setRealmAuthority", + "docs": [], + "optionalAccountStrategy": "programId", + "accounts": [ + { + "kind": "instructionAccountNode", + "name": "realmAccount", + "isWritable": true, + "isSigner": false, + "isOptional": false, + "docs": [] + }, + { + "kind": "instructionAccountNode", + "name": "realmAuthority", + "isWritable": false, + "isSigner": true, + "isOptional": false, + "docs": [] + }, + { + "kind": "instructionAccountNode", + "name": "newRealmAuthority", + "isWritable": false, + "isSigner": false, + "isOptional": true, + "docs": [ + "Must be one of the realm governances when set" + ] + } + ], + "arguments": [ + { + "kind": "instructionArgumentNode", + "name": "discriminator", + "defaultValueStrategy": "omitted", + "docs": [], + "type": { + "kind": "numberTypeNode", + "format": "u8", + "endian": "le" + }, + "defaultValue": { + "kind": "numberValueNode", + "number": 21 + } + }, + { + "kind": "instructionArgumentNode", + "name": "action", + "docs": [], + "type": { + "kind": "definedTypeLinkNode", + "name": "setRealmAuthorityAction" + } + } + ], + "discriminators": [ + { + "kind": "fieldDiscriminatorNode", + "name": "discriminator", + "offset": 0 + } + ] + }, + { + "kind": "instructionNode", + "name": "setRealmConfig", + "docs": [], + "optionalAccountStrategy": "programId", + "accounts": [ + { + "kind": "instructionAccountNode", + "name": "realmAccount", + "isWritable": true, + "isSigner": false, + "isOptional": false, + "docs": [] + }, + { + "kind": "instructionAccountNode", + "name": "realmAuthority", + "isWritable": false, + "isSigner": true, + "isOptional": false, + "docs": [] + }, + { + "kind": "instructionAccountNode", + "name": "councilTokenMint", + "isWritable": false, + "isSigner": false, + "isOptional": true, + "docs": [ + "Council Token Mint - optional. ", + " Note: In the current version it's only possible to remove council mint (set it to None)", + " After setting council to None it won't be possible to withdraw the tokens from the Realm any longer. ", + " If that's required then it must be done before executing this instruction" + ] + }, + { + "kind": "instructionAccountNode", + "name": "councilTokenHoldingAccount", + "isWritable": true, + "isSigner": false, + "isOptional": true, + "docs": [ + "Optional unless council is used. seeds=['governance', realm, council_mint]" + ] + }, + { + "kind": "instructionAccountNode", + "name": "systemProgram", + "isWritable": false, + "isSigner": false, + "isOptional": false, + "docs": [], + "defaultValue": { + "kind": "publicKeyValueNode", + "publicKey": "11111111111111111111111111111111", + "identifier": "systemProgram" + } + }, + { + "kind": "instructionAccountNode", + "name": "realmConfig", + "isWritable": true, + "isSigner": false, + "isOptional": false, + "docs": [ + "RealmConfig account. seeds=['realm-config', realm]" + ] + }, + { + "kind": "instructionAccountNode", + "name": "communityVoterWeightAddinProgramId", + "isWritable": false, + "isSigner": false, + "isOptional": true, + "docs": [ + "Optional Community Voter Weight Addin Program Id" + ] + }, + { + "kind": "instructionAccountNode", + "name": "maxCommunityVoterWeightAddinProgramId", + "isWritable": false, + "isSigner": false, + "isOptional": true, + "docs": [ + "Optional Max Community Voter Weight Addin Program Id" + ] + }, + { + "kind": "instructionAccountNode", + "name": "councilVoterWeightAddinProgramId", + "isWritable": false, + "isSigner": false, + "isOptional": true, + "docs": [ + "Optional Council Voter Weight Adding Program Id" + ] + }, + { + "kind": "instructionAccountNode", + "name": "maxCouncilVoterWeightAddinProgramId", + "isWritable": false, + "isSigner": false, + "isOptional": true, + "docs": [ + "Optional Max Council Voter Weight Addin Program Id" + ] + }, + { + "kind": "instructionAccountNode", + "name": "payer", + "isWritable": false, + "isSigner": true, + "isOptional": true, + "docs": [ + "Optional Payer. Required if RealmConfig doesn't exist and needs to be created" + ] + } + ], + "arguments": [ + { + "kind": "instructionArgumentNode", + "name": "discriminator", + "defaultValueStrategy": "omitted", + "docs": [], + "type": { + "kind": "numberTypeNode", + "format": "u8", + "endian": "le" + }, + "defaultValue": { + "kind": "numberValueNode", + "number": 22 + } + }, + { + "kind": "instructionArgumentNode", + "name": "configArgs", + "docs": [], + "type": { + "kind": "definedTypeLinkNode", + "name": "realmConfigParams" + } + } + ], + "discriminators": [ + { + "kind": "fieldDiscriminatorNode", + "name": "discriminator", + "offset": 0 + } + ] + }, + { + "kind": "instructionNode", + "name": "createTokenOwnerRecord", + "docs": [], + "optionalAccountStrategy": "programId", + "accounts": [ + { + "kind": "instructionAccountNode", + "name": "realmAccount", + "isWritable": false, + "isSigner": false, + "isOptional": false, + "docs": [] + }, + { + "kind": "instructionAccountNode", + "name": "governingTokenOwnerAccount", + "isWritable": false, + "isSigner": false, + "isOptional": false, + "docs": [] + }, + { + "kind": "instructionAccountNode", + "name": "tokenOwnerRecord", + "isWritable": true, + "isSigner": false, + "isOptional": false, + "docs": [ + "seeds=['governance', realm, governing_token_mint, governing_token_owner]" + ], + "defaultValue": { + "kind": "pdaValueNode", + "pda": { + "kind": "pdaLinkNode", + "name": "tokenOwnerRecord" + }, + "seeds": [ + { + "kind": "pdaSeedValueNode", + "name": "realm", + "value": { + "kind": "accountValueNode", + "name": "realmAccount" + } + }, + { + "kind": "pdaSeedValueNode", + "name": "governingTokenMint", + "value": { + "kind": "accountValueNode", + "name": "governingTokenMint" + } + }, + { + "kind": "pdaSeedValueNode", + "name": "governingTokenOwner", + "value": { + "kind": "accountValueNode", + "name": "governingTokenOwnerAccount" + } + } + ] + } + }, + { + "kind": "instructionAccountNode", + "name": "governingTokenMint", + "isWritable": false, + "isSigner": false, + "isOptional": false, + "docs": [] + }, + { + "kind": "instructionAccountNode", + "name": "payer", + "isWritable": false, + "isSigner": true, + "isOptional": false, + "docs": [], + "defaultValue": { + "kind": "payerValueNode" + } + }, + { + "kind": "instructionAccountNode", + "name": "systemProgram", + "isWritable": false, + "isSigner": false, + "isOptional": false, + "docs": [], + "defaultValue": { + "kind": "publicKeyValueNode", + "publicKey": "11111111111111111111111111111111", + "identifier": "systemProgram" + } + } + ], + "arguments": [ + { + "kind": "instructionArgumentNode", + "name": "discriminator", + "defaultValueStrategy": "omitted", + "docs": [], + "type": { + "kind": "numberTypeNode", + "format": "u8", + "endian": "le" + }, + "defaultValue": { + "kind": "numberValueNode", + "number": 23 + } + } + ], + "discriminators": [ + { + "kind": "fieldDiscriminatorNode", + "name": "discriminator", + "offset": 0 + } + ] + }, + { + "kind": "instructionNode", + "name": "updateProgramMetadata", + "docs": [], + "optionalAccountStrategy": "programId", + "accounts": [ + { + "kind": "instructionAccountNode", + "name": "programMetadataAccount", + "isWritable": true, + "isSigner": false, + "isOptional": false, + "docs": [ + "seeds=['metadata']" + ] + }, + { + "kind": "instructionAccountNode", + "name": "payer", + "isWritable": false, + "isSigner": true, + "isOptional": false, + "docs": [], + "defaultValue": { + "kind": "payerValueNode" + } + }, + { + "kind": "instructionAccountNode", + "name": "systemProgram", + "isWritable": false, + "isSigner": false, + "isOptional": false, + "docs": [], + "defaultValue": { + "kind": "publicKeyValueNode", + "publicKey": "11111111111111111111111111111111", + "identifier": "systemProgram" + } + } + ], + "arguments": [ + { + "kind": "instructionArgumentNode", + "name": "discriminator", + "defaultValueStrategy": "omitted", + "docs": [], + "type": { + "kind": "numberTypeNode", + "format": "u8", + "endian": "le" + }, + "defaultValue": { + "kind": "numberValueNode", + "number": 24 + } + } + ], + "discriminators": [ + { + "kind": "fieldDiscriminatorNode", + "name": "discriminator", + "offset": 0 + } + ] + }, + { + "kind": "instructionNode", + "name": "createNativeTreasury", + "docs": [], + "optionalAccountStrategy": "programId", + "accounts": [ + { + "kind": "instructionAccountNode", + "name": "governanceAccount", + "isWritable": false, + "isSigner": false, + "isOptional": false, + "docs": [ + "Governance account the treasury account is for" + ] + }, + { + "kind": "instructionAccountNode", + "name": "nativeTreasuryAccount", + "isWritable": true, + "isSigner": false, + "isOptional": false, + "docs": [ + "seeds=['native-treasury', governance]" + ] + }, + { + "kind": "instructionAccountNode", + "name": "payer", + "isWritable": false, + "isSigner": true, + "isOptional": false, + "docs": [], + "defaultValue": { + "kind": "payerValueNode" + } + }, + { + "kind": "instructionAccountNode", + "name": "systemProgram", + "isWritable": false, + "isSigner": false, + "isOptional": false, + "docs": [], + "defaultValue": { + "kind": "publicKeyValueNode", + "publicKey": "11111111111111111111111111111111", + "identifier": "systemProgram" + } + } + ], + "arguments": [ + { + "kind": "instructionArgumentNode", + "name": "discriminator", + "defaultValueStrategy": "omitted", + "docs": [], + "type": { + "kind": "numberTypeNode", + "format": "u8", + "endian": "le" + }, + "defaultValue": { + "kind": "numberValueNode", + "number": 25 + } + } + ], + "discriminators": [ + { + "kind": "fieldDiscriminatorNode", + "name": "discriminator", + "offset": 0 + } + ] + }, + { + "kind": "instructionNode", + "name": "revokeGoverningTokens", + "docs": [], + "optionalAccountStrategy": "programId", + "accounts": [ + { + "kind": "instructionAccountNode", + "name": "realmAccount", + "isWritable": false, + "isSigner": false, + "isOptional": false, + "docs": [] + }, + { + "kind": "instructionAccountNode", + "name": "governingTokenHoldingAccount", + "isWritable": true, + "isSigner": false, + "isOptional": false, + "docs": [ + "seeds=['governance', realm, governing_token_mint]" + ] + }, + { + "kind": "instructionAccountNode", + "name": "tokenOwnerRecord", + "isWritable": true, + "isSigner": false, + "isOptional": false, + "docs": [ + "seeds=['governance', realm, governing_token_mint, governing_token_owner]" + ] + }, + { + "kind": "instructionAccountNode", + "name": "governingTokenMint", + "isWritable": true, + "isSigner": false, + "isOptional": false, + "docs": [] + }, + { + "kind": "instructionAccountNode", + "name": "governingTokenMintAuthorityOrTokenOwner", + "isWritable": false, + "isSigner": true, + "isOptional": false, + "docs": [ + "GoverningTokenMint mint_authority" + ] + }, + { + "kind": "instructionAccountNode", + "name": "realmConfigAccount", + "isWritable": false, + "isSigner": false, + "isOptional": false, + "docs": [ + "seeds=['realm-config', realm]" + ] + }, + { + "kind": "instructionAccountNode", + "name": "tokenProgram", + "isWritable": false, + "isSigner": false, + "isOptional": false, + "docs": [], + "defaultValue": { + "kind": "publicKeyValueNode", + "publicKey": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA", + "identifier": "splToken" + } + } + ], + "arguments": [ + { + "kind": "instructionArgumentNode", + "name": "discriminator", + "defaultValueStrategy": "omitted", + "docs": [], + "type": { + "kind": "numberTypeNode", + "format": "u8", + "endian": "le" + }, + "defaultValue": { + "kind": "numberValueNode", + "number": 26 + } + }, + { + "kind": "instructionArgumentNode", + "name": "amount", + "docs": [], + "type": { + "kind": "numberTypeNode", + "format": "u64", + "endian": "le" + } + } + ], + "discriminators": [ + { + "kind": "fieldDiscriminatorNode", + "name": "discriminator", + "offset": 0 + } + ] + }, + { + "kind": "instructionNode", + "name": "refundProposalDeposit", + "docs": [], + "optionalAccountStrategy": "programId", + "accounts": [ + { + "kind": "instructionAccountNode", + "name": "proposalAccount", + "isWritable": false, + "isSigner": false, + "isOptional": false, + "docs": [] + }, + { + "kind": "instructionAccountNode", + "name": "proposalDepositAccount", + "isWritable": true, + "isSigner": false, + "isOptional": false, + "docs": [ + "PDA Seeds: ['proposal-deposit', proposal, deposit payer]" + ] + }, + { + "kind": "instructionAccountNode", + "name": "proposalDepositPayer", + "isWritable": true, + "isSigner": false, + "isOptional": false, + "docs": [ + "Proposal Deposit Payer (beneficiary) account" + ] + } + ], + "arguments": [ + { + "kind": "instructionArgumentNode", + "name": "discriminator", + "defaultValueStrategy": "omitted", + "docs": [], + "type": { + "kind": "numberTypeNode", + "format": "u8", + "endian": "le" + }, + "defaultValue": { + "kind": "numberValueNode", + "number": 27 + } + } + ], + "discriminators": [ + { + "kind": "fieldDiscriminatorNode", + "name": "discriminator", + "offset": 0 + } + ] + }, + { + "kind": "instructionNode", + "name": "completeProposal", + "docs": [], + "optionalAccountStrategy": "programId", + "accounts": [ + { + "kind": "instructionAccountNode", + "name": "proposalAccount", + "isWritable": true, + "isSigner": false, + "isOptional": false, + "docs": [] + }, + { + "kind": "instructionAccountNode", + "name": "tokenOwnerRecord", + "isWritable": false, + "isSigner": false, + "isOptional": false, + "docs": [ + "TokenOwnerRecord account of the Proposal owner" + ] + }, + { + "kind": "instructionAccountNode", + "name": "completeProposalAuthority", + "isWritable": false, + "isSigner": true, + "isOptional": false, + "docs": [ + "Token Owner or Delegate" + ] + } + ], + "arguments": [ + { + "kind": "instructionArgumentNode", + "name": "discriminator", + "defaultValueStrategy": "omitted", + "docs": [], + "type": { + "kind": "numberTypeNode", + "format": "u8", + "endian": "le" + }, + "defaultValue": { + "kind": "numberValueNode", + "number": 28 + } + } + ], + "discriminators": [ + { + "kind": "fieldDiscriminatorNode", + "name": "discriminator", + "offset": 0 + } + ] + }, + { + "kind": "instructionNode", + "name": "addRequiredSignatory", + "docs": [], + "optionalAccountStrategy": "programId", + "accounts": [ + { + "kind": "instructionAccountNode", + "name": "governanceAccount", + "isWritable": true, + "isSigner": true, + "isOptional": false, + "docs": [ + "The Governance account the config is for" + ] + }, + { + "kind": "instructionAccountNode", + "name": "requiredSignatoryAccount", + "isWritable": true, + "isSigner": false, + "isOptional": false, + "docs": [] + }, + { + "kind": "instructionAccountNode", + "name": "payer", + "isWritable": false, + "isSigner": true, + "isOptional": false, + "docs": [], + "defaultValue": { + "kind": "payerValueNode" + } + }, + { + "kind": "instructionAccountNode", + "name": "systemProgram", + "isWritable": false, + "isSigner": false, + "isOptional": false, + "docs": [], + "defaultValue": { + "kind": "publicKeyValueNode", + "publicKey": "11111111111111111111111111111111", + "identifier": "systemProgram" + } + } + ], + "arguments": [ + { + "kind": "instructionArgumentNode", + "name": "discriminator", + "defaultValueStrategy": "omitted", + "docs": [], + "type": { + "kind": "numberTypeNode", + "format": "u8", + "endian": "le" + }, + "defaultValue": { + "kind": "numberValueNode", + "number": 29 + } + }, + { + "kind": "instructionArgumentNode", + "name": "signatory", + "docs": [], + "type": { + "kind": "publicKeyTypeNode" + } + } + ], + "discriminators": [ + { + "kind": "fieldDiscriminatorNode", + "name": "discriminator", + "offset": 0 + } + ] + }, + { + "kind": "instructionNode", + "name": "removeRequiredSignatory", + "docs": [], + "optionalAccountStrategy": "programId", + "accounts": [ + { + "kind": "instructionAccountNode", + "name": "governanceAccount", + "isWritable": true, + "isSigner": true, + "isOptional": false, + "docs": [] + }, + { + "kind": "instructionAccountNode", + "name": "requiredSignatoryAccount", + "isWritable": true, + "isSigner": false, + "isOptional": false, + "docs": [] + }, + { + "kind": "instructionAccountNode", + "name": "beneficiaryAccount", + "isWritable": true, + "isSigner": false, + "isOptional": false, + "docs": [ + "Beneficiary Account which would receive lamports from the disposed RequiredSignatory Account" + ] + } + ], + "arguments": [ + { + "kind": "instructionArgumentNode", + "name": "discriminator", + "defaultValueStrategy": "omitted", + "docs": [], + "type": { + "kind": "numberTypeNode", + "format": "u8", + "endian": "le" + }, + "defaultValue": { + "kind": "numberValueNode", + "number": 30 + } + } + ], + "discriminators": [ + { + "kind": "fieldDiscriminatorNode", + "name": "discriminator", + "offset": 0 + } + ] + } + ], + "definedTypes": [ + { + "kind": "definedTypeNode", + "name": "governanceConfig", + "docs": [], + "type": { + "kind": "structTypeNode", + "fields": [ + { + "kind": "structFieldTypeNode", + "name": "communityVoteThreshold", + "docs": [], + "type": { + "kind": "definedTypeLinkNode", + "name": "voteThreshold" + } + }, + { + "kind": "structFieldTypeNode", + "name": "minCommunityWeightToCreateProposal", + "docs": [], + "type": { + "kind": "numberTypeNode", + "format": "u64", + "endian": "le" + } + }, + { + "kind": "structFieldTypeNode", + "name": "minTransactionHoldUpTime", + "docs": [], + "type": { + "kind": "numberTypeNode", + "format": "u32", + "endian": "le" + } + }, + { + "kind": "structFieldTypeNode", + "name": "votingBaseTime", + "docs": [], + "type": { + "kind": "numberTypeNode", + "format": "u32", + "endian": "le" + } + }, + { + "kind": "structFieldTypeNode", + "name": "communityVoteTipping", + "docs": [], + "type": { + "kind": "definedTypeLinkNode", + "name": "voteTipping" + } + }, + { + "kind": "structFieldTypeNode", + "name": "councilVoteThreshold", + "docs": [], + "type": { + "kind": "definedTypeLinkNode", + "name": "voteThreshold" + } + }, + { + "kind": "structFieldTypeNode", + "name": "councilVetoVoteThreshold", + "docs": [], + "type": { + "kind": "definedTypeLinkNode", + "name": "voteThreshold" + } + }, + { + "kind": "structFieldTypeNode", + "name": "minCouncilWeightToCreateProposal", + "docs": [], + "type": { + "kind": "numberTypeNode", + "format": "u64", + "endian": "le" + } + }, + { + "kind": "structFieldTypeNode", + "name": "councilVoteTipping", + "docs": [], + "type": { + "kind": "definedTypeLinkNode", + "name": "voteTipping" + } + }, + { + "kind": "structFieldTypeNode", + "name": "communityVetoVoteThreshold", + "docs": [], + "type": { + "kind": "definedTypeLinkNode", + "name": "voteThreshold" + } + }, + { + "kind": "structFieldTypeNode", + "name": "votingCoolOffTime", + "docs": [], + "type": { + "kind": "numberTypeNode", + "format": "u32", + "endian": "le" + } + }, + { + "kind": "structFieldTypeNode", + "name": "depositExemptProposalCount", + "docs": [], + "type": { + "kind": "numberTypeNode", + "format": "u8", + "endian": "le" + } + } + ] + } + }, + { + "kind": "definedTypeNode", + "name": "nativeTreasury", + "docs": [], + "type": { + "kind": "structTypeNode", + "fields": [] + } + }, + { + "kind": "definedTypeNode", + "name": "proposalOption", + "docs": [], + "type": { + "kind": "structTypeNode", + "fields": [ + { + "kind": "structFieldTypeNode", + "name": "label", + "docs": [], + "type": { + "kind": "sizePrefixTypeNode", + "type": { + "kind": "stringTypeNode", + "encoding": "utf8" + }, + "prefix": { + "kind": "numberTypeNode", + "format": "u32", + "endian": "le" + } + } + }, + { + "kind": "structFieldTypeNode", + "name": "voteWeight", + "docs": [], + "type": { + "kind": "numberTypeNode", + "format": "u64", + "endian": "le" + } + }, + { + "kind": "structFieldTypeNode", + "name": "voteResult", + "docs": [], + "type": { + "kind": "definedTypeLinkNode", + "name": "optionVoteResult" + } + }, + { + "kind": "structFieldTypeNode", + "name": "transactionsExecutedCount", + "docs": [], + "type": { + "kind": "numberTypeNode", + "format": "u16", + "endian": "le" + } + }, + { + "kind": "structFieldTypeNode", + "name": "transactionsCount", + "docs": [], + "type": { + "kind": "numberTypeNode", + "format": "u16", + "endian": "le" + } + }, + { + "kind": "structFieldTypeNode", + "name": "transactionsNextIndex", + "docs": [], + "type": { + "kind": "numberTypeNode", + "format": "u16", + "endian": "le" + } + } + ] + } + }, + { + "kind": "definedTypeNode", + "name": "instructionData", + "docs": [], + "type": { + "kind": "structTypeNode", + "fields": [ + { + "kind": "structFieldTypeNode", + "name": "programId", + "docs": [], + "type": { + "kind": "publicKeyTypeNode" + } + }, + { + "kind": "structFieldTypeNode", + "name": "accounts", + "docs": [], + "type": { + "kind": "arrayTypeNode", + "item": { + "kind": "definedTypeLinkNode", + "name": "accountMetaData" + }, + "count": { + "kind": "prefixedCountNode", + "prefix": { + "kind": "numberTypeNode", + "format": "u32", + "endian": "le" + } + } + } + }, + { + "kind": "structFieldTypeNode", + "name": "data", + "docs": [], + "type": { + "kind": "sizePrefixTypeNode", + "type": { + "kind": "bytesTypeNode" + }, + "prefix": { + "kind": "numberTypeNode", + "format": "u32", + "endian": "le" + } + } + } + ] + } + }, + { + "kind": "definedTypeNode", + "name": "accountMetaData", + "docs": [], + "type": { + "kind": "structTypeNode", + "fields": [ + { + "kind": "structFieldTypeNode", + "name": "pubkey", + "docs": [], + "type": { + "kind": "publicKeyTypeNode" + } + }, + { + "kind": "structFieldTypeNode", + "name": "isSigner", + "docs": [], + "type": { + "kind": "booleanTypeNode", + "size": { + "kind": "numberTypeNode", + "format": "u8", + "endian": "le" + } + } + }, + { + "kind": "structFieldTypeNode", + "name": "isWritable", + "docs": [], + "type": { + "kind": "booleanTypeNode", + "size": { + "kind": "numberTypeNode", + "format": "u8", + "endian": "le" + } + } + } + ] + } + }, + { + "kind": "definedTypeNode", + "name": "realmConfigParams", + "docs": [], + "type": { + "kind": "structTypeNode", + "fields": [ + { + "kind": "structFieldTypeNode", + "name": "useCouncilMint", + "docs": [], + "type": { + "kind": "booleanTypeNode", + "size": { + "kind": "numberTypeNode", + "format": "u8", + "endian": "le" + } + } + }, + { + "kind": "structFieldTypeNode", + "name": "minCommunityWeightToCreateGovernance", + "docs": [], + "type": { + "kind": "numberTypeNode", + "format": "u64", + "endian": "le" + } + }, + { + "kind": "structFieldTypeNode", + "name": "communityMintMaxVoterWeightSource", + "docs": [], + "type": { + "kind": "definedTypeLinkNode", + "name": "mintMaxVoterWeightSource" + } + }, + { + "kind": "structFieldTypeNode", + "name": "communityTokenConfigArgs", + "docs": [], + "type": { + "kind": "definedTypeLinkNode", + "name": "governingTokenConfigParams" + } + }, + { + "kind": "structFieldTypeNode", + "name": "councilTokenConfigArgs", + "docs": [], + "type": { + "kind": "definedTypeLinkNode", + "name": "governingTokenConfigParams" + } + } + ] + } + }, + { + "kind": "definedTypeNode", + "name": "governingTokenConfigParams", + "docs": [], + "type": { + "kind": "structTypeNode", + "fields": [ + { + "kind": "structFieldTypeNode", + "name": "useVoterWeightAddin", + "docs": [], + "type": { + "kind": "booleanTypeNode", + "size": { + "kind": "numberTypeNode", + "format": "u8", + "endian": "le" + } + } + }, + { + "kind": "structFieldTypeNode", + "name": "useMaxVoterWeightAddin", + "docs": [], + "type": { + "kind": "booleanTypeNode", + "size": { + "kind": "numberTypeNode", + "format": "u8", + "endian": "le" + } + } + }, + { + "kind": "structFieldTypeNode", + "name": "tokenType", + "docs": [], + "type": { + "kind": "definedTypeLinkNode", + "name": "governingTokenType" + } + } + ] + } + }, + { + "kind": "definedTypeNode", + "name": "governingTokenConfigAccountArgs", + "docs": [], + "type": { + "kind": "structTypeNode", + "fields": [ + { + "kind": "structFieldTypeNode", + "name": "voterWeightAddin", + "docs": [], + "type": { + "kind": "optionTypeNode", + "fixed": false, + "item": { + "kind": "publicKeyTypeNode" + }, + "prefix": { + "kind": "numberTypeNode", + "format": "u8", + "endian": "le" + } + } + }, + { + "kind": "structFieldTypeNode", + "name": "maxVoterWeightAddin", + "docs": [], + "type": { + "kind": "optionTypeNode", + "fixed": false, + "item": { + "kind": "publicKeyTypeNode" + }, + "prefix": { + "kind": "numberTypeNode", + "format": "u8", + "endian": "le" + } + } + }, + { + "kind": "structFieldTypeNode", + "name": "tokenType", + "docs": [], + "type": { + "kind": "definedTypeLinkNode", + "name": "governingTokenType" + } + } + ] + } + }, + { + "kind": "definedTypeNode", + "name": "realmConfig", + "docs": [], + "type": { + "kind": "structTypeNode", + "fields": [ + { + "kind": "structFieldTypeNode", + "name": "legacy1", + "docs": [], + "type": { + "kind": "numberTypeNode", + "format": "u8", + "endian": "le" + } + }, + { + "kind": "structFieldTypeNode", + "name": "legacy2", + "docs": [], + "type": { + "kind": "numberTypeNode", + "format": "u8", + "endian": "le" + } + }, + { + "kind": "structFieldTypeNode", + "name": "reserved", + "docs": [], + "type": { + "kind": "arrayTypeNode", + "item": { + "kind": "numberTypeNode", + "format": "u8", + "endian": "le" + }, + "count": { + "kind": "fixedCountNode", + "value": 6 + } + } + }, + { + "kind": "structFieldTypeNode", + "name": "minCommunityWeightToCreateGovernance", + "docs": [], + "type": { + "kind": "numberTypeNode", + "format": "u64", + "endian": "le" + } + }, + { + "kind": "structFieldTypeNode", + "name": "communityMintMaxVoterWeightSource", + "docs": [], + "type": { + "kind": "definedTypeLinkNode", + "name": "mintMaxVoterWeightSource" + } + }, + { + "kind": "structFieldTypeNode", + "name": "councilMint", + "docs": [], + "type": { + "kind": "optionTypeNode", + "fixed": false, + "item": { + "kind": "publicKeyTypeNode" + }, + "prefix": { + "kind": "numberTypeNode", + "format": "u8", + "endian": "le" + } + } + } + ] + } + }, + { + "kind": "definedTypeNode", + "name": "realmConfigParamsV1", + "docs": [], + "type": { + "kind": "structTypeNode", + "fields": [ + { + "kind": "structFieldTypeNode", + "name": "useCouncilMint", + "docs": [], + "type": { + "kind": "booleanTypeNode", + "size": { + "kind": "numberTypeNode", + "format": "u8", + "endian": "le" + } + } + }, + { + "kind": "structFieldTypeNode", + "name": "minCommunityWeightToCreateGovernance", + "docs": [], + "type": { + "kind": "numberTypeNode", + "format": "u64", + "endian": "le" + } + }, + { + "kind": "structFieldTypeNode", + "name": "communityMintMaxVoterWeightSource", + "docs": [], + "type": { + "kind": "definedTypeLinkNode", + "name": "mintMaxVoterWeightSource" + } + } + ] + } + }, + { + "kind": "definedTypeNode", + "name": "governingTokenConfig", + "docs": [], + "type": { + "kind": "structTypeNode", + "fields": [ + { + "kind": "structFieldTypeNode", + "name": "voterWeightAddin", + "docs": [], + "type": { + "kind": "optionTypeNode", + "fixed": false, + "item": { + "kind": "publicKeyTypeNode" + }, + "prefix": { + "kind": "numberTypeNode", + "format": "u8", + "endian": "le" + } + } + }, + { + "kind": "structFieldTypeNode", + "name": "maxVoterWeightAddin", + "docs": [], + "type": { + "kind": "optionTypeNode", + "fixed": false, + "item": { + "kind": "publicKeyTypeNode" + }, + "prefix": { + "kind": "numberTypeNode", + "format": "u8", + "endian": "le" + } + } + }, + { + "kind": "structFieldTypeNode", + "name": "tokenType", + "docs": [], + "type": { + "kind": "definedTypeLinkNode", + "name": "governingTokenType" + } + }, + { + "kind": "structFieldTypeNode", + "name": "reserved", + "docs": [], + "type": { + "kind": "arrayTypeNode", + "item": { + "kind": "numberTypeNode", + "format": "u8", + "endian": "le" + }, + "count": { + "kind": "fixedCountNode", + "value": 8 + } + } + } + ] + } + }, + { + "kind": "definedTypeNode", + "name": "voteChoice", + "docs": [], + "type": { + "kind": "structTypeNode", + "fields": [ + { + "kind": "structFieldTypeNode", + "name": "rank", + "docs": [], + "type": { + "kind": "numberTypeNode", + "format": "u8", + "endian": "le" + } + }, + { + "kind": "structFieldTypeNode", + "name": "weightPercentage", + "docs": [], + "type": { + "kind": "numberTypeNode", + "format": "u8", + "endian": "le" + } + } + ] + } + }, + { + "kind": "definedTypeNode", + "name": "reserved110", + "docs": [], + "type": { + "kind": "structTypeNode", + "fields": [ + { + "kind": "structFieldTypeNode", + "name": "reserved64", + "docs": [], + "type": { + "kind": "arrayTypeNode", + "item": { + "kind": "numberTypeNode", + "format": "u8", + "endian": "le" + }, + "count": { + "kind": "fixedCountNode", + "value": 64 + } + } + }, + { + "kind": "structFieldTypeNode", + "name": "reserved32", + "docs": [], + "type": { + "kind": "arrayTypeNode", + "item": { + "kind": "numberTypeNode", + "format": "u8", + "endian": "le" + }, + "count": { + "kind": "fixedCountNode", + "value": 32 + } + } + }, + { + "kind": "structFieldTypeNode", + "name": "reserved14", + "docs": [], + "type": { + "kind": "arrayTypeNode", + "item": { + "kind": "numberTypeNode", + "format": "u8", + "endian": "le" + }, + "count": { + "kind": "fixedCountNode", + "value": 14 + } + } + } + ] + } + }, + { + "kind": "definedTypeNode", + "name": "reserved119", + "docs": [], + "type": { + "kind": "structTypeNode", + "fields": [ + { + "kind": "structFieldTypeNode", + "name": "reserved64", + "docs": [], + "type": { + "kind": "arrayTypeNode", + "item": { + "kind": "numberTypeNode", + "format": "u8", + "endian": "le" + }, + "count": { + "kind": "fixedCountNode", + "value": 64 + } + } + }, + { + "kind": "structFieldTypeNode", + "name": "reserved32", + "docs": [], + "type": { + "kind": "arrayTypeNode", + "item": { + "kind": "numberTypeNode", + "format": "u8", + "endian": "le" + }, + "count": { + "kind": "fixedCountNode", + "value": 32 + } + } + }, + { + "kind": "structFieldTypeNode", + "name": "reserved23", + "docs": [], + "type": { + "kind": "arrayTypeNode", + "item": { + "kind": "numberTypeNode", + "format": "u8", + "endian": "le" + }, + "count": { + "kind": "fixedCountNode", + "value": 23 + } + } + } + ] + } + }, + { + "kind": "definedTypeNode", + "name": "governanceAccountType", + "docs": [], + "type": { + "kind": "enumTypeNode", + "variants": [ + { + "kind": "enumEmptyVariantTypeNode", + "name": "uninitialized" + }, + { + "kind": "enumEmptyVariantTypeNode", + "name": "realmV1" + }, + { + "kind": "enumEmptyVariantTypeNode", + "name": "tokenOwnerRecordV1" + }, + { + "kind": "enumEmptyVariantTypeNode", + "name": "governanceV1" + }, + { + "kind": "enumEmptyVariantTypeNode", + "name": "programGovernanceV1" + }, + { + "kind": "enumEmptyVariantTypeNode", + "name": "proposalV1" + }, + { + "kind": "enumEmptyVariantTypeNode", + "name": "signatoryRecordV1" + }, + { + "kind": "enumEmptyVariantTypeNode", + "name": "voteRecordV1" + }, + { + "kind": "enumEmptyVariantTypeNode", + "name": "proposalInstructionV1" + }, + { + "kind": "enumEmptyVariantTypeNode", + "name": "mintGovernanceV1" + }, + { + "kind": "enumEmptyVariantTypeNode", + "name": "tokenGovernanceV1" + }, + { + "kind": "enumEmptyVariantTypeNode", + "name": "realmConfig" + }, + { + "kind": "enumEmptyVariantTypeNode", + "name": "voteRecordV2" + }, + { + "kind": "enumEmptyVariantTypeNode", + "name": "proposalTransactionV2" + }, + { + "kind": "enumEmptyVariantTypeNode", + "name": "proposalV2" + }, + { + "kind": "enumEmptyVariantTypeNode", + "name": "programMetadata" + }, + { + "kind": "enumEmptyVariantTypeNode", + "name": "realmV2" + }, + { + "kind": "enumEmptyVariantTypeNode", + "name": "tokenOwnerRecordV2" + }, + { + "kind": "enumEmptyVariantTypeNode", + "name": "governanceV2" + }, + { + "kind": "enumEmptyVariantTypeNode", + "name": "programGovernanceV2" + }, + { + "kind": "enumEmptyVariantTypeNode", + "name": "mintGovernanceV2" + }, + { + "kind": "enumEmptyVariantTypeNode", + "name": "tokenGovernanceV2" + }, + { + "kind": "enumEmptyVariantTypeNode", + "name": "signatoryRecordV2" + }, + { + "kind": "enumEmptyVariantTypeNode", + "name": "proposalDeposit" + }, + { + "kind": "enumEmptyVariantTypeNode", + "name": "requiredSignatory" + } + ], + "size": { + "kind": "numberTypeNode", + "format": "u8", + "endian": "le" + } + } + }, + { + "kind": "definedTypeNode", + "name": "proposalState", + "docs": [], + "type": { + "kind": "enumTypeNode", + "variants": [ + { + "kind": "enumEmptyVariantTypeNode", + "name": "draft" + }, + { + "kind": "enumEmptyVariantTypeNode", + "name": "signingOff" + }, + { + "kind": "enumEmptyVariantTypeNode", + "name": "voting" + }, + { + "kind": "enumEmptyVariantTypeNode", + "name": "succeeded" + }, + { + "kind": "enumEmptyVariantTypeNode", + "name": "executing" + }, + { + "kind": "enumEmptyVariantTypeNode", + "name": "completed" + }, + { + "kind": "enumEmptyVariantTypeNode", + "name": "cancelled" + }, + { + "kind": "enumEmptyVariantTypeNode", + "name": "defeated" + }, + { + "kind": "enumEmptyVariantTypeNode", + "name": "executingWithErrors" + }, + { + "kind": "enumEmptyVariantTypeNode", + "name": "vetoed" + } + ], + "size": { + "kind": "numberTypeNode", + "format": "u8", + "endian": "le" + } + } + }, + { + "kind": "definedTypeNode", + "name": "voteThreshold", + "docs": [], + "type": { + "kind": "enumTypeNode", + "variants": [ + { + "kind": "enumTupleVariantTypeNode", + "name": "yesVotePercentage", + "tuple": { + "kind": "tupleTypeNode", + "items": [ + { + "kind": "numberTypeNode", + "format": "u8", + "endian": "le" + } + ] + } + }, + { + "kind": "enumTupleVariantTypeNode", + "name": "quorumPercentage", + "tuple": { + "kind": "tupleTypeNode", + "items": [ + { + "kind": "numberTypeNode", + "format": "u8", + "endian": "le" + } + ] + } + }, + { + "kind": "enumEmptyVariantTypeNode", + "name": "disabled" + } + ], + "size": { + "kind": "numberTypeNode", + "format": "u8", + "endian": "le" + } + } + }, + { + "kind": "definedTypeNode", + "name": "voteTipping", + "docs": [], + "type": { + "kind": "enumTypeNode", + "variants": [ + { + "kind": "enumEmptyVariantTypeNode", + "name": "strict" + }, + { + "kind": "enumEmptyVariantTypeNode", + "name": "early" + }, + { + "kind": "enumEmptyVariantTypeNode", + "name": "disabled" + } + ], + "size": { + "kind": "numberTypeNode", + "format": "u8", + "endian": "le" + } + } + }, + { + "kind": "definedTypeNode", + "name": "transactionExecutionStatus", + "docs": [], + "type": { + "kind": "enumTypeNode", + "variants": [ + { + "kind": "enumEmptyVariantTypeNode", + "name": "none" + }, + { + "kind": "enumEmptyVariantTypeNode", + "name": "success" + }, + { + "kind": "enumEmptyVariantTypeNode", + "name": "error" + } + ], + "size": { + "kind": "numberTypeNode", + "format": "u8", + "endian": "le" + } + } + }, + { + "kind": "definedTypeNode", + "name": "instructionExecutionFlags", + "docs": [], + "type": { + "kind": "enumTypeNode", + "variants": [ + { + "kind": "enumEmptyVariantTypeNode", + "name": "none" + }, + { + "kind": "enumEmptyVariantTypeNode", + "name": "ordered" + }, + { + "kind": "enumEmptyVariantTypeNode", + "name": "useTransaction" + } + ], + "size": { + "kind": "numberTypeNode", + "format": "u8", + "endian": "le" + } + } + }, + { + "kind": "definedTypeNode", + "name": "mintMaxVoterWeightSource", + "docs": [], + "type": { + "kind": "enumTypeNode", + "variants": [ + { + "kind": "enumTupleVariantTypeNode", + "name": "supplyFraction", + "tuple": { + "kind": "tupleTypeNode", + "items": [ + { + "kind": "numberTypeNode", + "format": "u64", + "endian": "le" + } + ] + } + }, + { + "kind": "enumTupleVariantTypeNode", + "name": "absolute", + "tuple": { + "kind": "tupleTypeNode", + "items": [ + { + "kind": "numberTypeNode", + "format": "u64", + "endian": "le" + } + ] + } + } + ], + "size": { + "kind": "numberTypeNode", + "format": "u8", + "endian": "le" + } + } + }, + { + "kind": "definedTypeNode", + "name": "voteWeightV1", + "docs": [], + "type": { + "kind": "enumTypeNode", + "variants": [ + { + "kind": "enumTupleVariantTypeNode", + "name": "yes", + "tuple": { + "kind": "tupleTypeNode", + "items": [ + { + "kind": "numberTypeNode", + "format": "u64", + "endian": "le" + } + ] + } + }, + { + "kind": "enumTupleVariantTypeNode", + "name": "no", + "tuple": { + "kind": "tupleTypeNode", + "items": [ + { + "kind": "numberTypeNode", + "format": "u64", + "endian": "le" + } + ] + } + } + ], + "size": { + "kind": "numberTypeNode", + "format": "u8", + "endian": "le" + } + } + }, + { + "kind": "definedTypeNode", + "name": "optionVoteResult", + "docs": [], + "type": { + "kind": "enumTypeNode", + "variants": [ + { + "kind": "enumEmptyVariantTypeNode", + "name": "none" + }, + { + "kind": "enumEmptyVariantTypeNode", + "name": "succeeded" + }, + { + "kind": "enumEmptyVariantTypeNode", + "name": "defeated" + } + ], + "size": { + "kind": "numberTypeNode", + "format": "u8", + "endian": "le" + } + } + }, + { + "kind": "definedTypeNode", + "name": "voteType", + "docs": [], + "type": { + "kind": "enumTypeNode", + "variants": [ + { + "kind": "enumEmptyVariantTypeNode", + "name": "singleChoice" + }, + { + "kind": "enumStructVariantTypeNode", + "name": "multiChoice", + "struct": { + "kind": "structTypeNode", + "fields": [ + { + "kind": "structFieldTypeNode", + "name": "choiceType", + "docs": [], + "type": { + "kind": "definedTypeLinkNode", + "name": "multiChoiceType" + } + }, + { + "kind": "structFieldTypeNode", + "name": "minVoterOptions", + "docs": [], + "type": { + "kind": "numberTypeNode", + "format": "u8", + "endian": "le" + } + }, + { + "kind": "structFieldTypeNode", + "name": "maxVoterOptions", + "docs": [], + "type": { + "kind": "numberTypeNode", + "format": "u8", + "endian": "le" + } + }, + { + "kind": "structFieldTypeNode", + "name": "maxWinningOptions", + "docs": [], + "type": { + "kind": "numberTypeNode", + "format": "u8", + "endian": "le" + } + } + ] + } + } + ], + "size": { + "kind": "numberTypeNode", + "format": "u8", + "endian": "le" + } + } + }, + { + "kind": "definedTypeNode", + "name": "multiChoiceType", + "docs": [], + "type": { + "kind": "enumTypeNode", + "variants": [ + { + "kind": "enumEmptyVariantTypeNode", + "name": "fullWeight" + }, + { + "kind": "enumEmptyVariantTypeNode", + "name": "weighted" + } + ], + "size": { + "kind": "numberTypeNode", + "format": "u8", + "endian": "le" + } + } + }, + { + "kind": "definedTypeNode", + "name": "setRealmAuthorityAction", + "docs": [], + "type": { + "kind": "enumTypeNode", + "variants": [ + { + "kind": "enumEmptyVariantTypeNode", + "name": "setUnchecked" + }, + { + "kind": "enumEmptyVariantTypeNode", + "name": "setChecked" + }, + { + "kind": "enumEmptyVariantTypeNode", + "name": "remove" + } + ], + "size": { + "kind": "numberTypeNode", + "format": "u8", + "endian": "le" + } + } + }, + { + "kind": "definedTypeNode", + "name": "governanceInstructionV1", + "docs": [], + "type": { + "kind": "enumTypeNode", + "variants": [ + { + "kind": "enumStructVariantTypeNode", + "name": "createRealm", + "struct": { + "kind": "structTypeNode", + "fields": [ + { + "kind": "structFieldTypeNode", + "name": "name", + "docs": [], + "type": { + "kind": "sizePrefixTypeNode", + "type": { + "kind": "stringTypeNode", + "encoding": "utf8" + }, + "prefix": { + "kind": "numberTypeNode", + "format": "u32", + "endian": "le" + } + } + }, + { + "kind": "structFieldTypeNode", + "name": "configArgs", + "docs": [], + "type": { + "kind": "definedTypeLinkNode", + "name": "realmConfigParamsV1" + } + } + ] + } + }, + { + "kind": "enumStructVariantTypeNode", + "name": "depositGoverningTokens", + "struct": { + "kind": "structTypeNode", + "fields": [ + { + "kind": "structFieldTypeNode", + "name": "amount", + "docs": [], + "type": { + "kind": "numberTypeNode", + "format": "u64", + "endian": "le" + } + } + ] + } + } + ], + "size": { + "kind": "numberTypeNode", + "format": "u8", + "endian": "le" + } + } + }, + { + "kind": "definedTypeNode", + "name": "governingTokenType", + "docs": [], + "type": { + "kind": "enumTypeNode", + "variants": [ + { + "kind": "enumEmptyVariantTypeNode", + "name": "liquid" + }, + { + "kind": "enumEmptyVariantTypeNode", + "name": "membership" + }, + { + "kind": "enumEmptyVariantTypeNode", + "name": "dormant" + } + ], + "size": { + "kind": "numberTypeNode", + "format": "u8", + "endian": "le" + } + } + }, + { + "kind": "definedTypeNode", + "name": "vote", + "docs": [], + "type": { + "kind": "enumTypeNode", + "variants": [ + { + "kind": "enumTupleVariantTypeNode", + "name": "approve", + "tuple": { + "kind": "tupleTypeNode", + "items": [ + { + "kind": "arrayTypeNode", + "item": { + "kind": "definedTypeLinkNode", + "name": "voteChoice" + }, + "count": { + "kind": "prefixedCountNode", + "prefix": { + "kind": "numberTypeNode", + "format": "u32", + "endian": "le" + } + } + } + ] + } + }, + { + "kind": "enumEmptyVariantTypeNode", + "name": "deny" + }, + { + "kind": "enumEmptyVariantTypeNode", + "name": "abstain" + }, + { + "kind": "enumEmptyVariantTypeNode", + "name": "veto" + } + ], + "size": { + "kind": "numberTypeNode", + "format": "u8", + "endian": "le" + } + } + }, + { + "kind": "definedTypeNode", + "name": "voteKind", + "docs": [], + "type": { + "kind": "enumTypeNode", + "variants": [ + { + "kind": "enumEmptyVariantTypeNode", + "name": "electorate" + }, + { + "kind": "enumEmptyVariantTypeNode", + "name": "veto" + } + ], + "size": { + "kind": "numberTypeNode", + "format": "u8", + "endian": "le" + } + } + }, + { + "kind": "definedTypeNode", + "name": "unixTimestamp", + "docs": [], + "type": { + "kind": "numberTypeNode", + "format": "i64", + "endian": "le" + } + }, + { + "kind": "definedTypeNode", + "name": "slot", + "docs": [], + "type": { + "kind": "numberTypeNode", + "format": "u64", + "endian": "le" + } + } + ], + "pdas": [ + { + "kind": "pdaNode", + "name": "realm", + "docs": [ + "Realm account identified by its name" + ], + "seeds": [ + { + "kind": "constantPdaSeedNode", + "type": { + "kind": "stringTypeNode", + "encoding": "utf8" + }, + "value": { + "kind": "stringValueNode", + "string": "governance" + } + }, + { + "kind": "variablePdaSeedNode", + "name": "name", + "docs": [], + "type": { + "kind": "stringTypeNode", + "encoding": "utf8" + } + } + ] + }, + { + "kind": "pdaNode", + "name": "communityTokenHolding", + "docs": [ + "Community token holding account of a realm" + ], + "seeds": [ + { + "kind": "constantPdaSeedNode", + "type": { + "kind": "stringTypeNode", + "encoding": "utf8" + }, + "value": { + "kind": "stringValueNode", + "string": "governance" + } + }, + { + "kind": "variablePdaSeedNode", + "name": "realm", + "docs": [], + "type": { + "kind": "publicKeyTypeNode" + } + }, + { + "kind": "variablePdaSeedNode", + "name": "communityMint", + "docs": [], + "type": { + "kind": "publicKeyTypeNode" + } + } + ] + }, + { + "kind": "pdaNode", + "name": "councilTokenHolding", + "docs": [ + "Council token holding account of a realm" + ], + "seeds": [ + { + "kind": "constantPdaSeedNode", + "type": { + "kind": "stringTypeNode", + "encoding": "utf8" + }, + "value": { + "kind": "stringValueNode", + "string": "governance" + } + }, + { + "kind": "variablePdaSeedNode", + "name": "realm", + "docs": [], + "type": { + "kind": "publicKeyTypeNode" + } + }, + { + "kind": "variablePdaSeedNode", + "name": "councilMint", + "docs": [], + "type": { + "kind": "publicKeyTypeNode" + } + } + ] + }, + { + "kind": "pdaNode", + "name": "realmConfig", + "docs": [ + "Configuration of a realm" + ], + "seeds": [ + { + "kind": "constantPdaSeedNode", + "type": { + "kind": "stringTypeNode", + "encoding": "utf8" + }, + "value": { + "kind": "stringValueNode", + "string": "realm-config" + } + }, + { + "kind": "variablePdaSeedNode", + "name": "realm", + "docs": [], + "type": { + "kind": "publicKeyTypeNode" + } + } + ] + }, + { + "kind": "pdaNode", + "name": "tokenOwnerRecord", + "docs": [ + "Token owner's record within a realm" + ], + "seeds": [ + { + "kind": "constantPdaSeedNode", + "type": { + "kind": "stringTypeNode", + "encoding": "utf8" + }, + "value": { + "kind": "stringValueNode", + "string": "governance" + } + }, + { + "kind": "variablePdaSeedNode", + "name": "realm", + "docs": [], + "type": { + "kind": "publicKeyTypeNode" + } + }, + { + "kind": "variablePdaSeedNode", + "name": "governingTokenMint", + "docs": [], + "type": { + "kind": "publicKeyTypeNode" + } + }, + { + "kind": "variablePdaSeedNode", + "name": "governingTokenOwner", + "docs": [], + "type": { + "kind": "publicKeyTypeNode" + } + } + ] + }, + { + "kind": "pdaNode", + "name": "governingTokenHolding", + "docs": [ + "Governing token holding account" + ], + "seeds": [ + { + "kind": "constantPdaSeedNode", + "type": { + "kind": "stringTypeNode", + "encoding": "utf8" + }, + "value": { + "kind": "stringValueNode", + "string": "governance" + } + }, + { + "kind": "variablePdaSeedNode", + "name": "realm", + "docs": [], + "type": { + "kind": "publicKeyTypeNode" + } + }, + { + "kind": "variablePdaSeedNode", + "name": "governingTokenMint", + "docs": [], + "type": { + "kind": "publicKeyTypeNode" + } + } + ] + }, + { + "kind": "pdaNode", + "name": "governance", + "docs": [ + "Governance account within a realm" + ], + "seeds": [ + { + "kind": "constantPdaSeedNode", + "type": { + "kind": "stringTypeNode", + "encoding": "utf8" + }, + "value": { + "kind": "stringValueNode", + "string": "account-governance" + } + }, + { + "kind": "variablePdaSeedNode", + "name": "realm", + "docs": [], + "type": { + "kind": "publicKeyTypeNode" + } + }, + { + "kind": "variablePdaSeedNode", + "name": "seed", + "docs": [], + "type": { + "kind": "publicKeyTypeNode" + } + } + ] + }, + { + "kind": "pdaNode", + "name": "nativeTreasury", + "docs": [ + "Governance's native SOL treasury account" + ], + "seeds": [ + { + "kind": "constantPdaSeedNode", + "type": { + "kind": "stringTypeNode", + "encoding": "utf8" + }, + "value": { + "kind": "stringValueNode", + "string": "native-treasury" + } + }, + { + "kind": "variablePdaSeedNode", + "name": "governance", + "docs": [], + "type": { + "kind": "publicKeyTypeNode" + } + } + ] + }, + { + "kind": "pdaNode", + "name": "proposal", + "docs": [ + "Governance proposal" + ], + "seeds": [ + { + "kind": "constantPdaSeedNode", + "type": { + "kind": "stringTypeNode", + "encoding": "utf8" + }, + "value": { + "kind": "stringValueNode", + "string": "governance" + } + }, + { + "kind": "variablePdaSeedNode", + "name": "governance", + "docs": [], + "type": { + "kind": "publicKeyTypeNode" + } + }, + { + "kind": "variablePdaSeedNode", + "name": "governingTokenMint", + "docs": [], + "type": { + "kind": "publicKeyTypeNode" + } + }, + { + "kind": "variablePdaSeedNode", + "name": "proposalSeed", + "docs": [], + "type": { + "kind": "publicKeyTypeNode" + } + } + ] + }, + { + "kind": "pdaNode", + "name": "proposalDeposit", + "docs": [ + "Proposal deposit made by a specific payer" + ], + "seeds": [ + { + "kind": "constantPdaSeedNode", + "type": { + "kind": "stringTypeNode", + "encoding": "utf8" + }, + "value": { + "kind": "stringValueNode", + "string": "proposal-deposit" + } + }, + { + "kind": "variablePdaSeedNode", + "name": "proposal", + "docs": [], + "type": { + "kind": "publicKeyTypeNode" + } + }, + { + "kind": "variablePdaSeedNode", + "name": "depositPayer", + "docs": [], + "type": { + "kind": "publicKeyTypeNode" + } + } + ] + }, + { + "kind": "pdaNode", + "name": "signatoryRecord", + "docs": [ + "Signatory's record on a proposal" + ], + "seeds": [ + { + "kind": "constantPdaSeedNode", + "type": { + "kind": "stringTypeNode", + "encoding": "utf8" + }, + "value": { + "kind": "stringValueNode", + "string": "governance" + } + }, + { + "kind": "variablePdaSeedNode", + "name": "proposal", + "docs": [], + "type": { + "kind": "publicKeyTypeNode" + } + }, + { + "kind": "variablePdaSeedNode", + "name": "signatory", + "docs": [], + "type": { + "kind": "publicKeyTypeNode" + } + } + ] + }, + { + "kind": "pdaNode", + "name": "proposalTransaction", + "docs": [ + "Transaction within a proposal option" + ], + "seeds": [ + { + "kind": "constantPdaSeedNode", + "type": { + "kind": "stringTypeNode", + "encoding": "utf8" + }, + "value": { + "kind": "stringValueNode", + "string": "governance" + } + }, + { + "kind": "variablePdaSeedNode", + "name": "proposal", + "docs": [], + "type": { + "kind": "publicKeyTypeNode" + } + }, + { + "kind": "variablePdaSeedNode", + "name": "optionIndex", + "docs": [], + "type": { + "kind": "numberTypeNode", + "format": "u8", + "endian": "le" + } + }, + { + "kind": "variablePdaSeedNode", + "name": "index", + "docs": [], + "type": { + "kind": "numberTypeNode", + "format": "u16", + "endian": "le" + } + } + ] + }, + { + "kind": "pdaNode", + "name": "voteRecord", + "docs": [ + "Vote record on a proposal" + ], + "seeds": [ + { + "kind": "constantPdaSeedNode", + "type": { + "kind": "stringTypeNode", + "encoding": "utf8" + }, + "value": { + "kind": "stringValueNode", + "string": "governance" + } + }, + { + "kind": "variablePdaSeedNode", + "name": "proposal", + "docs": [], + "type": { + "kind": "publicKeyTypeNode" + } + }, + { + "kind": "variablePdaSeedNode", + "name": "tokenOwnerRecord", + "docs": [], + "type": { + "kind": "publicKeyTypeNode" + } + } + ] + }, + { + "kind": "pdaNode", + "name": "requiredSignatory", + "docs": [ + "Required signatory on a governance" + ], + "seeds": [ + { + "kind": "constantPdaSeedNode", + "type": { + "kind": "stringTypeNode", + "encoding": "utf8" + }, + "value": { + "kind": "stringValueNode", + "string": "required-signatory" + } + }, + { + "kind": "variablePdaSeedNode", + "name": "governance", + "docs": [], + "type": { + "kind": "publicKeyTypeNode" + } + }, + { + "kind": "variablePdaSeedNode", + "name": "signatory", + "docs": [], + "type": { + "kind": "publicKeyTypeNode" + } + } + ] + } + ], + "errors": [ + { + "kind": "errorNode", + "name": "invalidInstruction", + "code": 500, + "message": "Invalid instruction passed to program", + "docs": [ + "InvalidInstruction: Invalid instruction passed to program" + ] + }, + { + "kind": "errorNode", + "name": "realmAlreadyExists", + "code": 501, + "message": "Realm with the given name and governing mints already exists", + "docs": [ + "RealmAlreadyExists: Realm with the given name and governing mints already exists" + ] + }, + { + "kind": "errorNode", + "name": "invalidRealm", + "code": 502, + "message": "Invalid realm", + "docs": [ + "InvalidRealm: Invalid realm" + ] + }, + { + "kind": "errorNode", + "name": "invalidGoverningTokenMint", + "code": 503, + "message": "Invalid Governing Token Mint", + "docs": [ + "InvalidGoverningTokenMint: Invalid Governing Token Mint" + ] + }, + { + "kind": "errorNode", + "name": "governingTokenOwnerMustSign", + "code": 504, + "message": "Governing Token Owner must sign transaction", + "docs": [ + "GoverningTokenOwnerMustSign: Governing Token Owner must sign transaction" + ] + }, + { + "kind": "errorNode", + "name": "governingTokenOwnerOrDelegateMustSign", + "code": 505, + "message": "Governing Token Owner or Delegate must sign transaction", + "docs": [ + "GoverningTokenOwnerOrDelegateMustSign: Governing Token Owner or Delegate must sign transaction" + ] + }, + { + "kind": "errorNode", + "name": "allVotesMustBeRelinquishedToWithdrawGoverningTokens", + "code": 506, + "message": "All votes must be relinquished to withdraw governing tokens", + "docs": [ + "AllVotesMustBeRelinquishedToWithdrawGoverningTokens: All votes must be relinquished to withdraw governing tokens" + ] + }, + { + "kind": "errorNode", + "name": "invalidTokenOwnerRecordAccountAddress", + "code": 507, + "message": "Invalid Token Owner Record account address", + "docs": [ + "InvalidTokenOwnerRecordAccountAddress: Invalid Token Owner Record account address" + ] + }, + { + "kind": "errorNode", + "name": "invalidGoverningMintForTokenOwnerRecord", + "code": 508, + "message": "Invalid GoverningMint for TokenOwnerRecord", + "docs": [ + "InvalidGoverningMintForTokenOwnerRecord: Invalid GoverningMint for TokenOwnerRecord" + ] + }, + { + "kind": "errorNode", + "name": "invalidRealmForTokenOwnerRecord", + "code": 509, + "message": "Invalid Realm for TokenOwnerRecord", + "docs": [ + "InvalidRealmForTokenOwnerRecord: Invalid Realm for TokenOwnerRecord" + ] + }, + { + "kind": "errorNode", + "name": "invalidProposalForProposalTransaction", + "code": 510, + "message": "Invalid Proposal for ProposalTransaction,", + "docs": [ + "InvalidProposalForProposalTransaction: Invalid Proposal for ProposalTransaction," + ] + }, + { + "kind": "errorNode", + "name": "invalidSignatoryAddress", + "code": 511, + "message": "Invalid Signatory account address", + "docs": [ + "InvalidSignatoryAddress: Invalid Signatory account address" + ] + }, + { + "kind": "errorNode", + "name": "signatoryAlreadySignedOff", + "code": 512, + "message": "Signatory already signed off", + "docs": [ + "SignatoryAlreadySignedOff: Signatory already signed off" + ] + }, + { + "kind": "errorNode", + "name": "signatoryMustSign", + "code": 513, + "message": "Signatory must sign", + "docs": [ + "SignatoryMustSign: Signatory must sign" + ] + }, + { + "kind": "errorNode", + "name": "invalidProposalOwnerAccount", + "code": 514, + "message": "Invalid Proposal Owner", + "docs": [ + "InvalidProposalOwnerAccount: Invalid Proposal Owner" + ] + }, + { + "kind": "errorNode", + "name": "invalidProposalForVoterRecord", + "code": 515, + "message": "Invalid Proposal for VoterRecord", + "docs": [ + "InvalidProposalForVoterRecord: Invalid Proposal for VoterRecord" + ] + }, + { + "kind": "errorNode", + "name": "invalidGoverningTokenOwnerForVoteRecord", + "code": 516, + "message": "Invalid GoverningTokenOwner for VoteRecord", + "docs": [ + "InvalidGoverningTokenOwnerForVoteRecord: Invalid GoverningTokenOwner for VoteRecord" + ] + }, + { + "kind": "errorNode", + "name": "invalidVoteThresholdPercentage", + "code": 517, + "message": "Invalid Governance config: Vote threshold percentage out of range", + "docs": [ + "InvalidVoteThresholdPercentage: Invalid Governance config: Vote threshold percentage out of range" + ] + }, + { + "kind": "errorNode", + "name": "proposalAlreadyExists", + "code": 518, + "message": "Proposal for the given Governance, Governing Token Mint and index already exists", + "docs": [ + "ProposalAlreadyExists: Proposal for the given Governance, Governing Token Mint and index already exists" + ] + }, + { + "kind": "errorNode", + "name": "voteAlreadyExists", + "code": 519, + "message": "Token Owner already voted on the Proposal", + "docs": [ + "VoteAlreadyExists: Token Owner already voted on the Proposal" + ] + }, + { + "kind": "errorNode", + "name": "notEnoughTokensToCreateProposal", + "code": 520, + "message": "Owner doesn't have enough governing tokens to create Proposal", + "docs": [ + "NotEnoughTokensToCreateProposal: Owner doesn't have enough governing tokens to create Proposal" + ] + }, + { + "kind": "errorNode", + "name": "invalidStateCannotEditSignatories", + "code": 521, + "message": "Invalid State: Can't edit Signatories", + "docs": [ + "InvalidStateCannotEditSignatories: Invalid State: Can't edit Signatories" + ] + }, + { + "kind": "errorNode", + "name": "invalidProposalState", + "code": 522, + "message": "Invalid Proposal state", + "docs": [ + "InvalidProposalState: Invalid Proposal state" + ] + }, + { + "kind": "errorNode", + "name": "invalidStateCannotEditTransactions", + "code": 523, + "message": "Invalid State: Can't edit transactions", + "docs": [ + "InvalidStateCannotEditTransactions: Invalid State: Can't edit transactions" + ] + }, + { + "kind": "errorNode", + "name": "invalidStateCannotExecuteTransaction", + "code": 524, + "message": "Invalid State: Can't execute transaction", + "docs": [ + "InvalidStateCannotExecuteTransaction: Invalid State: Can't execute transaction" + ] + }, + { + "kind": "errorNode", + "name": "cannotExecuteTransactionWithinHoldUpTime", + "code": 525, + "message": "Can't execute transaction within its hold up time", + "docs": [ + "CannotExecuteTransactionWithinHoldUpTime: Can't execute transaction within its hold up time" + ] + }, + { + "kind": "errorNode", + "name": "transactionAlreadyExecuted", + "code": 526, + "message": "Transaction already executed", + "docs": [ + "TransactionAlreadyExecuted: Transaction already executed" + ] + }, + { + "kind": "errorNode", + "name": "invalidTransactionIndex", + "code": 527, + "message": "Invalid Transaction index", + "docs": [ + "InvalidTransactionIndex: Invalid Transaction index" + ] + }, + { + "kind": "errorNode", + "name": "transactionHoldUpTimeBelowRequiredMin", + "code": 528, + "message": "Transaction hold up time is below the min specified by Governance", + "docs": [ + "TransactionHoldUpTimeBelowRequiredMin: Transaction hold up time is below the min specified by Governance" + ] + }, + { + "kind": "errorNode", + "name": "transactionAlreadyExists", + "code": 529, + "message": "Transaction at the given index for the Proposal already exists", + "docs": [ + "TransactionAlreadyExists: Transaction at the given index for the Proposal already exists" + ] + }, + { + "kind": "errorNode", + "name": "invalidStateCannotSignOff", + "code": 530, + "message": "Invalid State: Can't sign off", + "docs": [ + "InvalidStateCannotSignOff: Invalid State: Can't sign off" + ] + }, + { + "kind": "errorNode", + "name": "invalidStateCannotVote", + "code": 531, + "message": "Invalid State: Can't vote", + "docs": [ + "InvalidStateCannotVote: Invalid State: Can't vote" + ] + }, + { + "kind": "errorNode", + "name": "invalidStateCannotFinalize", + "code": 532, + "message": "Invalid State: Can't finalize vote", + "docs": [ + "InvalidStateCannotFinalize: Invalid State: Can't finalize vote" + ] + }, + { + "kind": "errorNode", + "name": "invalidStateCannotCancelProposal", + "code": 533, + "message": "Invalid State: Can't cancel Proposal", + "docs": [ + "InvalidStateCannotCancelProposal: Invalid State: Can't cancel Proposal" + ] + }, + { + "kind": "errorNode", + "name": "voteAlreadyRelinquished", + "code": 534, + "message": "Vote already relinquished", + "docs": [ + "VoteAlreadyRelinquished: Vote already relinquished" + ] + }, + { + "kind": "errorNode", + "name": "cannotFinalizeVotingInProgress", + "code": 535, + "message": "Can't finalize vote. Voting still in progress", + "docs": [ + "CannotFinalizeVotingInProgress: Can't finalize vote. Voting still in progress" + ] + }, + { + "kind": "errorNode", + "name": "proposalVotingTimeExpired", + "code": 536, + "message": "Proposal voting time expired", + "docs": [ + "ProposalVotingTimeExpired: Proposal voting time expired" + ] + }, + { + "kind": "errorNode", + "name": "invalidSignatoryMint", + "code": 537, + "message": "Invalid Signatory Mint", + "docs": [ + "InvalidSignatoryMint: Invalid Signatory Mint" + ] + }, + { + "kind": "errorNode", + "name": "invalidGovernanceForProposal", + "code": 538, + "message": "Proposal does not belong to the given Governance", + "docs": [ + "InvalidGovernanceForProposal: Proposal does not belong to the given Governance" + ] + }, + { + "kind": "errorNode", + "name": "invalidGoverningMintForProposal", + "code": 539, + "message": "Proposal does not belong to given Governing Mint", + "docs": [ + "InvalidGoverningMintForProposal: Proposal does not belong to given Governing Mint" + ] + }, + { + "kind": "errorNode", + "name": "mintAuthorityMustSign", + "code": 540, + "message": "Current mint authority must sign transaction", + "docs": [ + "MintAuthorityMustSign: Current mint authority must sign transaction" + ] + }, + { + "kind": "errorNode", + "name": "invalidMintAuthority", + "code": 541, + "message": "Invalid mint authority", + "docs": [ + "InvalidMintAuthority: Invalid mint authority" + ] + }, + { + "kind": "errorNode", + "name": "mintHasNoAuthority", + "code": 542, + "message": "Mint has no authority", + "docs": [ + "MintHasNoAuthority: Mint has no authority" + ] + }, + { + "kind": "errorNode", + "name": "splTokenAccountWithInvalidOwner", + "code": 543, + "message": "Invalid Token account owner", + "docs": [ + "SplTokenAccountWithInvalidOwner: Invalid Token account owner" + ] + }, + { + "kind": "errorNode", + "name": "splTokenMintWithInvalidOwner", + "code": 544, + "message": "Invalid Mint account owner", + "docs": [ + "SplTokenMintWithInvalidOwner: Invalid Mint account owner" + ] + }, + { + "kind": "errorNode", + "name": "splTokenAccountNotInitialized", + "code": 545, + "message": "Token Account is not initialized", + "docs": [ + "SplTokenAccountNotInitialized: Token Account is not initialized" + ] + }, + { + "kind": "errorNode", + "name": "splTokenAccountDoesNotExist", + "code": 546, + "message": "Token Account doesn't exist", + "docs": [ + "SplTokenAccountDoesNotExist: Token Account doesn't exist" + ] + }, + { + "kind": "errorNode", + "name": "splTokenInvalidTokenAccountData", + "code": 547, + "message": "Token account data is invalid", + "docs": [ + "SplTokenInvalidTokenAccountData: Token account data is invalid" + ] + }, + { + "kind": "errorNode", + "name": "splTokenInvalidMintAccountData", + "code": 548, + "message": "Token mint account data is invalid", + "docs": [ + "SplTokenInvalidMintAccountData: Token mint account data is invalid" + ] + }, + { + "kind": "errorNode", + "name": "splTokenMintNotInitialized", + "code": 549, + "message": "Token Mint account is not initialized", + "docs": [ + "SplTokenMintNotInitialized: Token Mint account is not initialized" + ] + }, + { + "kind": "errorNode", + "name": "splTokenMintDoesNotExist", + "code": 550, + "message": "Token Mint account doesn't exist", + "docs": [ + "SplTokenMintDoesNotExist: Token Mint account doesn't exist" + ] + }, + { + "kind": "errorNode", + "name": "invalidProgramDataAccountAddress", + "code": 551, + "message": "Invalid ProgramData account address", + "docs": [ + "InvalidProgramDataAccountAddress: Invalid ProgramData account address" + ] + }, + { + "kind": "errorNode", + "name": "invalidProgramDataAccountData", + "code": 552, + "message": "Invalid ProgramData account Data", + "docs": [ + "InvalidProgramDataAccountData: Invalid ProgramData account Data" + ] + }, + { + "kind": "errorNode", + "name": "invalidUpgradeAuthority", + "code": 553, + "message": "Provided upgrade authority doesn't match current program upgrade authority", + "docs": [ + "InvalidUpgradeAuthority: Provided upgrade authority doesn't match current program upgrade authority" + ] + }, + { + "kind": "errorNode", + "name": "upgradeAuthorityMustSign", + "code": 554, + "message": "Current program upgrade authority must sign transaction", + "docs": [ + "UpgradeAuthorityMustSign: Current program upgrade authority must sign transaction" + ] + }, + { + "kind": "errorNode", + "name": "programNotUpgradable", + "code": 555, + "message": "Given program is not upgradable", + "docs": [ + "ProgramNotUpgradable: Given program is not upgradable" + ] + }, + { + "kind": "errorNode", + "name": "invalidTokenOwner", + "code": 556, + "message": "Invalid token owner", + "docs": [ + "InvalidTokenOwner: Invalid token owner" + ] + }, + { + "kind": "errorNode", + "name": "tokenOwnerMustSign", + "code": 557, + "message": "Current token owner must sign transaction", + "docs": [ + "TokenOwnerMustSign: Current token owner must sign transaction" + ] + }, + { + "kind": "errorNode", + "name": "voteThresholdTypeNotSupported", + "code": 558, + "message": "Given VoteThresholdType is not supported", + "docs": [ + "VoteThresholdTypeNotSupported: Given VoteThresholdType is not supported" + ] + }, + { + "kind": "errorNode", + "name": "voteWeightSourceNotSupported", + "code": 559, + "message": "Given VoteWeightSource is not supported", + "docs": [ + "VoteWeightSourceNotSupported: Given VoteWeightSource is not supported" + ] + }, + { + "kind": "errorNode", + "name": "legacy1", + "code": 560, + "message": "Legacy1", + "docs": [ + "Legacy1: Legacy1" + ] + }, + { + "kind": "errorNode", + "name": "governancePdaMustSign", + "code": 561, + "message": "Governance PDA must sign", + "docs": [ + "GovernancePdaMustSign: Governance PDA must sign" + ] + }, + { + "kind": "errorNode", + "name": "transactionAlreadyFlaggedWithError", + "code": 562, + "message": "Transaction already flagged with error", + "docs": [ + "TransactionAlreadyFlaggedWithError: Transaction already flagged with error" + ] + }, + { + "kind": "errorNode", + "name": "invalidRealmForGovernance", + "code": 563, + "message": "Invalid Realm for Governance", + "docs": [ + "InvalidRealmForGovernance: Invalid Realm for Governance" + ] + }, + { + "kind": "errorNode", + "name": "invalidAuthorityForRealm", + "code": 564, + "message": "Invalid Authority for Realm", + "docs": [ + "InvalidAuthorityForRealm: Invalid Authority for Realm" + ] + }, + { + "kind": "errorNode", + "name": "realmHasNoAuthority", + "code": 565, + "message": "Realm has no authority", + "docs": [ + "RealmHasNoAuthority: Realm has no authority" + ] + }, + { + "kind": "errorNode", + "name": "realmAuthorityMustSign", + "code": 566, + "message": "Realm authority must sign", + "docs": [ + "RealmAuthorityMustSign: Realm authority must sign" + ] + }, + { + "kind": "errorNode", + "name": "invalidGoverningTokenHoldingAccount", + "code": 567, + "message": "Invalid governing token holding account", + "docs": [ + "InvalidGoverningTokenHoldingAccount: Invalid governing token holding account" + ] + }, + { + "kind": "errorNode", + "name": "realmCouncilMintChangeIsNotSupported", + "code": 568, + "message": "Realm council mint change is not supported", + "docs": [ + "RealmCouncilMintChangeIsNotSupported: Realm council mint change is not supported" + ] + }, + { + "kind": "errorNode", + "name": "invalidMaxVoterWeightAbsoluteValue", + "code": 569, + "message": "Invalid max voter weight absolute value", + "docs": [ + "InvalidMaxVoterWeightAbsoluteValue: Invalid max voter weight absolute value" + ] + }, + { + "kind": "errorNode", + "name": "invalidMaxVoterWeightSupplyFraction", + "code": 570, + "message": "Invalid max voter weight supply fraction", + "docs": [ + "InvalidMaxVoterWeightSupplyFraction: Invalid max voter weight supply fraction" + ] + }, + { + "kind": "errorNode", + "name": "notEnoughTokensToCreateGovernance", + "code": 571, + "message": "Owner doesn't have enough governing tokens to create Governance", + "docs": [ + "NotEnoughTokensToCreateGovernance: Owner doesn't have enough governing tokens to create Governance" + ] + }, + { + "kind": "errorNode", + "name": "tooManyOutstandingProposals", + "code": 572, + "message": "Too many outstanding proposals", + "docs": [ + "TooManyOutstandingProposals: Too many outstanding proposals" + ] + }, + { + "kind": "errorNode", + "name": "allProposalsMustBeFinalisedToWithdrawGoverningTokens", + "code": 573, + "message": "All proposals must be finalized to withdraw governing tokens", + "docs": [ + "AllProposalsMustBeFinalisedToWithdrawGoverningTokens: All proposals must be finalized to withdraw governing tokens" + ] + }, + { + "kind": "errorNode", + "name": "invalidVoterWeightRecordForRealm", + "code": 574, + "message": "Invalid VoterWeightRecord for Realm", + "docs": [ + "InvalidVoterWeightRecordForRealm: Invalid VoterWeightRecord for Realm" + ] + }, + { + "kind": "errorNode", + "name": "invalidVoterWeightRecordForGoverningTokenMint", + "code": 575, + "message": "Invalid VoterWeightRecord for GoverningTokenMint", + "docs": [ + "InvalidVoterWeightRecordForGoverningTokenMint: Invalid VoterWeightRecord for GoverningTokenMint" + ] + }, + { + "kind": "errorNode", + "name": "invalidVoterWeightRecordForTokenOwner", + "code": 576, + "message": "Invalid VoterWeightRecord for TokenOwner", + "docs": [ + "InvalidVoterWeightRecordForTokenOwner: Invalid VoterWeightRecord for TokenOwner" + ] + }, + { + "kind": "errorNode", + "name": "voterWeightRecordExpired", + "code": 577, + "message": "VoterWeightRecord expired", + "docs": [ + "VoterWeightRecordExpired: VoterWeightRecord expired" + ] + }, + { + "kind": "errorNode", + "name": "invalidRealmConfigForRealm", + "code": 578, + "message": "Invalid RealmConfig for Realm", + "docs": [ + "InvalidRealmConfigForRealm: Invalid RealmConfig for Realm" + ] + }, + { + "kind": "errorNode", + "name": "tokenOwnerRecordAlreadyExists", + "code": 579, + "message": "TokenOwnerRecord already exists", + "docs": [ + "TokenOwnerRecordAlreadyExists: TokenOwnerRecord already exists" + ] + }, + { + "kind": "errorNode", + "name": "governingTokenDepositsNotAllowed", + "code": 580, + "message": "Governing token deposits not allowed", + "docs": [ + "GoverningTokenDepositsNotAllowed: Governing token deposits not allowed" + ] + }, + { + "kind": "errorNode", + "name": "invalidVoteChoiceWeightPercentage", + "code": 581, + "message": "Invalid vote choice weight percentage", + "docs": [ + "InvalidVoteChoiceWeightPercentage: Invalid vote choice weight percentage" + ] + }, + { + "kind": "errorNode", + "name": "voteTypeNotSupported", + "code": 582, + "message": "Vote type not supported", + "docs": [ + "VoteTypeNotSupported: Vote type not supported" + ] + }, + { + "kind": "errorNode", + "name": "invalidProposalOptions", + "code": 583, + "message": "Invalid proposal options", + "docs": [ + "InvalidProposalOptions: Invalid proposal options" + ] + }, + { + "kind": "errorNode", + "name": "proposalIsNotExecutable", + "code": 584, + "message": "Proposal is not not executable", + "docs": [ + "ProposalIsNotExecutable: Proposal is not not executable" + ] + }, + { + "kind": "errorNode", + "name": "denyVoteIsNotAllowed", + "code": 585, + "message": "Deny vote is not allowed", + "docs": [ + "DenyVoteIsNotAllowed: Deny vote is not allowed" + ] + }, + { + "kind": "errorNode", + "name": "cannotExecuteDefeatedOption", + "code": 586, + "message": "Cannot execute defeated option", + "docs": [ + "CannotExecuteDefeatedOption: Cannot execute defeated option" + ] + }, + { + "kind": "errorNode", + "name": "voterWeightRecordInvalidAction", + "code": 587, + "message": "VoterWeightRecord invalid action", + "docs": [ + "VoterWeightRecordInvalidAction: VoterWeightRecord invalid action" + ] + }, + { + "kind": "errorNode", + "name": "voterWeightRecordInvalidActionTarget", + "code": 588, + "message": "VoterWeightRecord invalid action target", + "docs": [ + "VoterWeightRecordInvalidActionTarget: VoterWeightRecord invalid action target" + ] + }, + { + "kind": "errorNode", + "name": "invalidMaxVoterWeightRecordForRealm", + "code": 589, + "message": "Invalid MaxVoterWeightRecord for Realm", + "docs": [ + "InvalidMaxVoterWeightRecordForRealm: Invalid MaxVoterWeightRecord for Realm" + ] + }, + { + "kind": "errorNode", + "name": "invalidMaxVoterWeightRecordForGoverningTokenMint", + "code": 590, + "message": "Invalid MaxVoterWeightRecord for GoverningTokenMint", + "docs": [ + "InvalidMaxVoterWeightRecordForGoverningTokenMint: Invalid MaxVoterWeightRecord for GoverningTokenMint" + ] + }, + { + "kind": "errorNode", + "name": "maxVoterWeightRecordExpired", + "code": 591, + "message": "MaxVoterWeightRecord expired", + "docs": [ + "MaxVoterWeightRecordExpired: MaxVoterWeightRecord expired" + ] + }, + { + "kind": "errorNode", + "name": "notSupportedVoteType", + "code": 592, + "message": "Not supported VoteType", + "docs": [ + "NotSupportedVoteType: Not supported VoteType" + ] + }, + { + "kind": "errorNode", + "name": "realmConfigChangeNotAllowed", + "code": 593, + "message": "RealmConfig change not allowed", + "docs": [ + "RealmConfigChangeNotAllowed: RealmConfig change not allowed" + ] + }, + { + "kind": "errorNode", + "name": "governanceConfigChangeNotAllowed", + "code": 594, + "message": "GovernanceConfig change not allowed", + "docs": [ + "GovernanceConfigChangeNotAllowed: GovernanceConfig change not allowed" + ] + }, + { + "kind": "errorNode", + "name": "atLeastOneVoteThresholdRequired", + "code": 595, + "message": "At least one VoteThreshold is required", + "docs": [ + "AtLeastOneVoteThresholdRequired: At least one VoteThreshold is required" + ] + }, + { + "kind": "errorNode", + "name": "reservedBufferMustBeEmpty", + "code": 596, + "message": "Reserved buffer must be empty", + "docs": [ + "ReservedBufferMustBeEmpty: Reserved buffer must be empty" + ] + }, + { + "kind": "errorNode", + "name": "cannotRelinquishInFinalizingState", + "code": 597, + "message": "Cannot Relinquish in Finalizing state", + "docs": [ + "CannotRelinquishInFinalizingState: Cannot Relinquish in Finalizing state" + ] + }, + { + "kind": "errorNode", + "name": "invalidRealmConfigAddress", + "code": 598, + "message": "Invalid RealmConfig account address", + "docs": [ + "InvalidRealmConfigAddress: Invalid RealmConfig account address" + ] + }, + { + "kind": "errorNode", + "name": "cannotDepositDormantTokens", + "code": 599, + "message": "Cannot deposit dormant tokens", + "docs": [ + "CannotDepositDormantTokens: Cannot deposit dormant tokens" + ] + }, + { + "kind": "errorNode", + "name": "cannotWithdrawMembershipTokens", + "code": 600, + "message": "Cannot withdraw membership tokens", + "docs": [ + "CannotWithdrawMembershipTokens: Cannot withdraw membership tokens" + ] + }, + { + "kind": "errorNode", + "name": "cannotRevokeGoverningTokens", + "code": 601, + "message": "Cannot revoke GoverningTokens", + "docs": [ + "CannotRevokeGoverningTokens: Cannot revoke GoverningTokens" + ] + }, + { + "kind": "errorNode", + "name": "invalidRevokeAmount", + "code": 602, + "message": "Invalid Revoke amount", + "docs": [ + "InvalidRevokeAmount: Invalid Revoke amount" + ] + }, + { + "kind": "errorNode", + "name": "invalidGoverningTokenSource", + "code": 603, + "message": "Invalid GoverningToken source", + "docs": [ + "InvalidGoverningTokenSource: Invalid GoverningToken source" + ] + }, + { + "kind": "errorNode", + "name": "cannotChangeCommunityTokenTypeToMembership", + "code": 604, + "message": "Cannot change community TokenType to Membership", + "docs": [ + "CannotChangeCommunityTokenTypeToMembership: Cannot change community TokenType to Membership" + ] + }, + { + "kind": "errorNode", + "name": "voterWeightThresholdDisabled", + "code": 605, + "message": "Voter weight threshold disabled", + "docs": [ + "VoterWeightThresholdDisabled: Voter weight threshold disabled" + ] + }, + { + "kind": "errorNode", + "name": "voteNotAllowedInCoolOffTime", + "code": 606, + "message": "Vote not allowed in cool off time", + "docs": [ + "VoteNotAllowedInCoolOffTime: Vote not allowed in cool off time" + ] + }, + { + "kind": "errorNode", + "name": "cannotRefundProposalDeposit", + "code": 607, + "message": "Cannot refund ProposalDeposit", + "docs": [ + "CannotRefundProposalDeposit: Cannot refund ProposalDeposit" + ] + }, + { + "kind": "errorNode", + "name": "invalidProposalForProposalDeposit", + "code": 608, + "message": "Invalid Proposal for ProposalDeposit", + "docs": [ + "InvalidProposalForProposalDeposit: Invalid Proposal for ProposalDeposit" + ] + }, + { + "kind": "errorNode", + "name": "invalidDepositExemptProposalCount", + "code": 609, + "message": "Invalid deposit_exempt_proposal_count", + "docs": [ + "InvalidDepositExemptProposalCount: Invalid deposit_exempt_proposal_count" + ] + }, + { + "kind": "errorNode", + "name": "governingTokenMintNotAllowedToVote", + "code": 610, + "message": "GoverningTokenMint not allowed to vote", + "docs": [ + "GoverningTokenMintNotAllowedToVote: GoverningTokenMint not allowed to vote" + ] + }, + { + "kind": "errorNode", + "name": "invalidDepositPayerForProposalDeposit", + "code": 611, + "message": "Invalid deposit Payer for ProposalDeposit", + "docs": [ + "InvalidDepositPayerForProposalDeposit: Invalid deposit Payer for ProposalDeposit" + ] + }, + { + "kind": "errorNode", + "name": "invalidStateNotFinal", + "code": 612, + "message": "Invalid State: Proposal is not in final state", + "docs": [ + "InvalidStateNotFinal: Invalid State: Proposal is not in final state" + ] + }, + { + "kind": "errorNode", + "name": "invalidStateToCompleteProposal", + "code": 613, + "message": "Invalid state for proposal state transition to Completed", + "docs": [ + "InvalidStateToCompleteProposal: Invalid state for proposal state transition to Completed" + ] + }, + { + "kind": "errorNode", + "name": "invalidNumberOfVoteChoices", + "code": 614, + "message": "Invalid number of vote choices", + "docs": [ + "InvalidNumberOfVoteChoices: Invalid number of vote choices" + ] + }, + { + "kind": "errorNode", + "name": "rankedVoteIsNotSupported", + "code": 615, + "message": "Ranked vote is not supported", + "docs": [ + "RankedVoteIsNotSupported: Ranked vote is not supported" + ] + }, + { + "kind": "errorNode", + "name": "choiceWeightMustBe100Percent", + "code": 616, + "message": "Choice weight must be 100%", + "docs": [ + "ChoiceWeightMustBe100Percent: Choice weight must be 100%" + ] + }, + { + "kind": "errorNode", + "name": "singleChoiceOnlyIsAllowed", + "code": 617, + "message": "Single choice only is allowed", + "docs": [ + "SingleChoiceOnlyIsAllowed: Single choice only is allowed" + ] + }, + { + "kind": "errorNode", + "name": "atLeastSingleChoiceIsRequired", + "code": 618, + "message": "At least single choice is required", + "docs": [ + "AtLeastSingleChoiceIsRequired: At least single choice is required" + ] + }, + { + "kind": "errorNode", + "name": "totalVoteWeightMustBe100Percent", + "code": 619, + "message": "Total vote weight must be 100%", + "docs": [ + "TotalVoteWeightMustBe100Percent: Total vote weight must be 100%" + ] + }, + { + "kind": "errorNode", + "name": "invalidMultiChoiceProposalParameters", + "code": 620, + "message": "Invalid multi choice proposal parameters", + "docs": [ + "InvalidMultiChoiceProposalParameters: Invalid multi choice proposal parameters" + ] + }, + { + "kind": "errorNode", + "name": "invalidGovernanceForRequiredSignatory", + "code": 621, + "message": "Invalid Governance for RequiredSignatory", + "docs": [ + "InvalidGovernanceForRequiredSignatory: Invalid Governance for RequiredSignatory" + ] + }, + { + "kind": "errorNode", + "name": "signatoryRecordAlreadyExists", + "code": 622, + "message": "Signatory Record has already been created", + "docs": [ + "SignatoryRecordAlreadyExists: Signatory Record has already been created" + ] + }, + { + "kind": "errorNode", + "name": "instructionDeprecated", + "code": 623, + "message": "Instruction has been removed", + "docs": [ + "InstructionDeprecated: Instruction has been removed" + ] + }, + { + "kind": "errorNode", + "name": "missingRequiredSignatories", + "code": 624, + "message": "Proposal is missing required signatories", + "docs": [ + "MissingRequiredSignatories: Proposal is missing required signatories" + ] + } + ] + }, + "additionalPrograms": [] +} diff --git a/e2e/governance/src/generated/accounts/governance_v1.rs b/e2e/governance/src/generated/accounts/governance_v1.rs new file mode 100644 index 0000000..c7fb13e --- /dev/null +++ b/e2e/governance/src/generated/accounts/governance_v1.rs @@ -0,0 +1,178 @@ +//! This code was AUTOGENERATED using the codama library. +//! Please DO NOT EDIT THIS FILE, instead use visitors +//! to add features, then rerun codama to update it. +//! +//! +//! + +use crate::generated::types::GovernanceAccountType; +use crate::generated::types::GovernanceConfig; +use borsh::BorshDeserialize; +use borsh::BorshSerialize; +use solana_pubkey::Pubkey; + +#[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct GovernanceV1 { + pub account_type: GovernanceAccountType, + #[cfg_attr( + feature = "serde", + serde(with = "serde_with::As::") + )] + pub realm: Pubkey, + #[cfg_attr( + feature = "serde", + serde(with = "serde_with::As::") + )] + pub governed_account: Pubkey, + pub proposals_count: u32, + pub config: GovernanceConfig, +} + +impl GovernanceV1 { + /// Prefix values used to generate a PDA for this account. + /// + /// Values are positional and appear in the following order: + /// + /// 0. `GovernanceV1::PREFIX` + /// 1. realm (`Pubkey`) + /// 2. seed (`Pubkey`) + pub const PREFIX: &'static [u8] = "account-governance".as_bytes(); + + pub fn create_pda( + realm: Pubkey, + seed: Pubkey, + bump: u8, + ) -> Result { + solana_pubkey::Pubkey::create_program_address( + &[ + "account-governance".as_bytes(), + realm.as_ref(), + seed.as_ref(), + &[bump], + ], + &crate::SPL_GOVERNANCE_ID, + ) + } + + pub fn find_pda(realm: &Pubkey, seed: &Pubkey) -> (solana_pubkey::Pubkey, u8) { + solana_pubkey::Pubkey::find_program_address( + &[ + "account-governance".as_bytes(), + realm.as_ref(), + seed.as_ref(), + ], + &crate::SPL_GOVERNANCE_ID, + ) + } + + #[inline(always)] + pub fn from_bytes(data: &[u8]) -> Result { + let mut data = data; + Self::deserialize(&mut data) + } +} + +impl<'a> TryFrom<&solana_account_info::AccountInfo<'a>> for GovernanceV1 { + type Error = std::io::Error; + + fn try_from(account_info: &solana_account_info::AccountInfo<'a>) -> Result { + let mut data: &[u8] = &(*account_info.data).borrow(); + Self::deserialize(&mut data) + } +} + +#[cfg(feature = "fetch")] +pub fn fetch_governance_v1( + rpc: &solana_client::rpc_client::RpcClient, + address: &solana_pubkey::Pubkey, +) -> Result, std::io::Error> { + let accounts = fetch_all_governance_v1(rpc, &[*address])?; + Ok(accounts[0].clone()) +} + +#[cfg(feature = "fetch")] +pub fn fetch_all_governance_v1( + rpc: &solana_client::rpc_client::RpcClient, + addresses: &[solana_pubkey::Pubkey], +) -> Result>, std::io::Error> { + let accounts = rpc + .get_multiple_accounts(addresses) + .map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, e.to_string()))?; + let mut decoded_accounts: Vec> = Vec::new(); + for i in 0..addresses.len() { + let address = addresses[i]; + let account = accounts[i].as_ref().ok_or(std::io::Error::new( + std::io::ErrorKind::Other, + format!("Account not found: {}", address), + ))?; + let data = GovernanceV1::from_bytes(&account.data)?; + decoded_accounts.push(crate::shared::DecodedAccount { + address, + account: account.clone(), + data, + }); + } + Ok(decoded_accounts) +} + +#[cfg(feature = "fetch")] +pub fn fetch_maybe_governance_v1( + rpc: &solana_client::rpc_client::RpcClient, + address: &solana_pubkey::Pubkey, +) -> Result, std::io::Error> { + let accounts = fetch_all_maybe_governance_v1(rpc, &[*address])?; + Ok(accounts[0].clone()) +} + +#[cfg(feature = "fetch")] +pub fn fetch_all_maybe_governance_v1( + rpc: &solana_client::rpc_client::RpcClient, + addresses: &[solana_pubkey::Pubkey], +) -> Result>, std::io::Error> { + let accounts = rpc + .get_multiple_accounts(addresses) + .map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, e.to_string()))?; + let mut decoded_accounts: Vec> = Vec::new(); + for i in 0..addresses.len() { + let address = addresses[i]; + if let Some(account) = accounts[i].as_ref() { + let data = GovernanceV1::from_bytes(&account.data)?; + decoded_accounts.push(crate::shared::MaybeAccount::Exists( + crate::shared::DecodedAccount { + address, + account: account.clone(), + data, + }, + )); + } else { + decoded_accounts.push(crate::shared::MaybeAccount::NotFound(address)); + } + } + Ok(decoded_accounts) +} + +#[cfg(feature = "anchor")] +impl anchor_lang::AccountDeserialize for GovernanceV1 { + fn try_deserialize_unchecked(buf: &mut &[u8]) -> anchor_lang::Result { + Ok(Self::deserialize(buf)?) + } +} + +#[cfg(feature = "anchor")] +impl anchor_lang::AccountSerialize for GovernanceV1 {} + +#[cfg(feature = "anchor")] +impl anchor_lang::Owner for GovernanceV1 { + fn owner() -> Pubkey { + crate::SPL_GOVERNANCE_ID + } +} + +#[cfg(feature = "anchor-idl-build")] +impl anchor_lang::IdlBuild for GovernanceV1 {} + +#[cfg(feature = "anchor-idl-build")] +impl anchor_lang::Discriminator for GovernanceV1 { + const DISCRIMINATOR: &[u8] = &[0; 8]; +} diff --git a/e2e/governance/src/generated/accounts/governance_v2.rs b/e2e/governance/src/generated/accounts/governance_v2.rs new file mode 100644 index 0000000..85e117f --- /dev/null +++ b/e2e/governance/src/generated/accounts/governance_v2.rs @@ -0,0 +1,182 @@ +//! This code was AUTOGENERATED using the codama library. +//! Please DO NOT EDIT THIS FILE, instead use visitors +//! to add features, then rerun codama to update it. +//! +//! +//! + +use crate::generated::types::GovernanceAccountType; +use crate::generated::types::GovernanceConfig; +use crate::generated::types::Reserved119; +use borsh::BorshDeserialize; +use borsh::BorshSerialize; +use solana_pubkey::Pubkey; + +#[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct GovernanceV2 { + pub account_type: GovernanceAccountType, + #[cfg_attr( + feature = "serde", + serde(with = "serde_with::As::") + )] + pub realm: Pubkey, + #[cfg_attr( + feature = "serde", + serde(with = "serde_with::As::") + )] + pub governed_account: Pubkey, + pub reserved1: u32, + pub config: GovernanceConfig, + pub reserved_v2: Reserved119, + pub required_signatories_count: u8, + pub active_proposal_count: u64, +} + +impl GovernanceV2 { + /// Prefix values used to generate a PDA for this account. + /// + /// Values are positional and appear in the following order: + /// + /// 0. `GovernanceV2::PREFIX` + /// 1. realm (`Pubkey`) + /// 2. seed (`Pubkey`) + pub const PREFIX: &'static [u8] = "account-governance".as_bytes(); + + pub fn create_pda( + realm: Pubkey, + seed: Pubkey, + bump: u8, + ) -> Result { + solana_pubkey::Pubkey::create_program_address( + &[ + "account-governance".as_bytes(), + realm.as_ref(), + seed.as_ref(), + &[bump], + ], + &crate::SPL_GOVERNANCE_ID, + ) + } + + pub fn find_pda(realm: &Pubkey, seed: &Pubkey) -> (solana_pubkey::Pubkey, u8) { + solana_pubkey::Pubkey::find_program_address( + &[ + "account-governance".as_bytes(), + realm.as_ref(), + seed.as_ref(), + ], + &crate::SPL_GOVERNANCE_ID, + ) + } + + #[inline(always)] + pub fn from_bytes(data: &[u8]) -> Result { + let mut data = data; + Self::deserialize(&mut data) + } +} + +impl<'a> TryFrom<&solana_account_info::AccountInfo<'a>> for GovernanceV2 { + type Error = std::io::Error; + + fn try_from(account_info: &solana_account_info::AccountInfo<'a>) -> Result { + let mut data: &[u8] = &(*account_info.data).borrow(); + Self::deserialize(&mut data) + } +} + +#[cfg(feature = "fetch")] +pub fn fetch_governance_v2( + rpc: &solana_client::rpc_client::RpcClient, + address: &solana_pubkey::Pubkey, +) -> Result, std::io::Error> { + let accounts = fetch_all_governance_v2(rpc, &[*address])?; + Ok(accounts[0].clone()) +} + +#[cfg(feature = "fetch")] +pub fn fetch_all_governance_v2( + rpc: &solana_client::rpc_client::RpcClient, + addresses: &[solana_pubkey::Pubkey], +) -> Result>, std::io::Error> { + let accounts = rpc + .get_multiple_accounts(addresses) + .map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, e.to_string()))?; + let mut decoded_accounts: Vec> = Vec::new(); + for i in 0..addresses.len() { + let address = addresses[i]; + let account = accounts[i].as_ref().ok_or(std::io::Error::new( + std::io::ErrorKind::Other, + format!("Account not found: {}", address), + ))?; + let data = GovernanceV2::from_bytes(&account.data)?; + decoded_accounts.push(crate::shared::DecodedAccount { + address, + account: account.clone(), + data, + }); + } + Ok(decoded_accounts) +} + +#[cfg(feature = "fetch")] +pub fn fetch_maybe_governance_v2( + rpc: &solana_client::rpc_client::RpcClient, + address: &solana_pubkey::Pubkey, +) -> Result, std::io::Error> { + let accounts = fetch_all_maybe_governance_v2(rpc, &[*address])?; + Ok(accounts[0].clone()) +} + +#[cfg(feature = "fetch")] +pub fn fetch_all_maybe_governance_v2( + rpc: &solana_client::rpc_client::RpcClient, + addresses: &[solana_pubkey::Pubkey], +) -> Result>, std::io::Error> { + let accounts = rpc + .get_multiple_accounts(addresses) + .map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, e.to_string()))?; + let mut decoded_accounts: Vec> = Vec::new(); + for i in 0..addresses.len() { + let address = addresses[i]; + if let Some(account) = accounts[i].as_ref() { + let data = GovernanceV2::from_bytes(&account.data)?; + decoded_accounts.push(crate::shared::MaybeAccount::Exists( + crate::shared::DecodedAccount { + address, + account: account.clone(), + data, + }, + )); + } else { + decoded_accounts.push(crate::shared::MaybeAccount::NotFound(address)); + } + } + Ok(decoded_accounts) +} + +#[cfg(feature = "anchor")] +impl anchor_lang::AccountDeserialize for GovernanceV2 { + fn try_deserialize_unchecked(buf: &mut &[u8]) -> anchor_lang::Result { + Ok(Self::deserialize(buf)?) + } +} + +#[cfg(feature = "anchor")] +impl anchor_lang::AccountSerialize for GovernanceV2 {} + +#[cfg(feature = "anchor")] +impl anchor_lang::Owner for GovernanceV2 { + fn owner() -> Pubkey { + crate::SPL_GOVERNANCE_ID + } +} + +#[cfg(feature = "anchor-idl-build")] +impl anchor_lang::IdlBuild for GovernanceV2 {} + +#[cfg(feature = "anchor-idl-build")] +impl anchor_lang::Discriminator for GovernanceV2 { + const DISCRIMINATOR: &[u8] = &[0; 8]; +} diff --git a/e2e/governance/src/generated/accounts/legacy_token_owner_record.rs b/e2e/governance/src/generated/accounts/legacy_token_owner_record.rs new file mode 100644 index 0000000..0547d43 --- /dev/null +++ b/e2e/governance/src/generated/accounts/legacy_token_owner_record.rs @@ -0,0 +1,197 @@ +//! This code was AUTOGENERATED using the codama library. +//! Please DO NOT EDIT THIS FILE, instead use visitors +//! to add features, then rerun codama to update it. +//! +//! +//! + +use crate::generated::types::GovernanceAccountType; +use borsh::BorshDeserialize; +use borsh::BorshSerialize; +use solana_pubkey::Pubkey; + +#[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct LegacyTokenOwnerRecord { + pub account_type: GovernanceAccountType, + #[cfg_attr( + feature = "serde", + serde(with = "serde_with::As::") + )] + pub realm: Pubkey, + #[cfg_attr( + feature = "serde", + serde(with = "serde_with::As::") + )] + pub governing_token_mint: Pubkey, + #[cfg_attr( + feature = "serde", + serde(with = "serde_with::As::") + )] + pub governing_token_owner: Pubkey, + pub governing_token_deposit_amount: u64, + pub unrelinquished_votes_count: u32, + pub total_votes_count: u32, + pub outstanding_proposal_count: u8, + pub reserved: [u8; 7], + pub governance_delegate: Option, + #[cfg_attr(feature = "serde", serde(with = "serde_big_array::BigArray"))] + pub reserved_v2: [u8; 128], +} + +impl LegacyTokenOwnerRecord { + /// Prefix values used to generate a PDA for this account. + /// + /// Values are positional and appear in the following order: + /// + /// 0. `LegacyTokenOwnerRecord::PREFIX` + /// 1. realm (`Pubkey`) + /// 2. governing_token_mint (`Pubkey`) + /// 3. governing_token_owner (`Pubkey`) + pub const PREFIX: &'static [u8] = "governance".as_bytes(); + + pub fn create_pda( + realm: Pubkey, + governing_token_mint: Pubkey, + governing_token_owner: Pubkey, + bump: u8, + ) -> Result { + solana_pubkey::Pubkey::create_program_address( + &[ + "governance".as_bytes(), + realm.as_ref(), + governing_token_mint.as_ref(), + governing_token_owner.as_ref(), + &[bump], + ], + &crate::SPL_GOVERNANCE_ID, + ) + } + + pub fn find_pda( + realm: &Pubkey, + governing_token_mint: &Pubkey, + governing_token_owner: &Pubkey, + ) -> (solana_pubkey::Pubkey, u8) { + solana_pubkey::Pubkey::find_program_address( + &[ + "governance".as_bytes(), + realm.as_ref(), + governing_token_mint.as_ref(), + governing_token_owner.as_ref(), + ], + &crate::SPL_GOVERNANCE_ID, + ) + } + + #[inline(always)] + pub fn from_bytes(data: &[u8]) -> Result { + let mut data = data; + Self::deserialize(&mut data) + } +} + +impl<'a> TryFrom<&solana_account_info::AccountInfo<'a>> for LegacyTokenOwnerRecord { + type Error = std::io::Error; + + fn try_from(account_info: &solana_account_info::AccountInfo<'a>) -> Result { + let mut data: &[u8] = &(*account_info.data).borrow(); + Self::deserialize(&mut data) + } +} + +#[cfg(feature = "fetch")] +pub fn fetch_legacy_token_owner_record( + rpc: &solana_client::rpc_client::RpcClient, + address: &solana_pubkey::Pubkey, +) -> Result, std::io::Error> { + let accounts = fetch_all_legacy_token_owner_record(rpc, &[*address])?; + Ok(accounts[0].clone()) +} + +#[cfg(feature = "fetch")] +pub fn fetch_all_legacy_token_owner_record( + rpc: &solana_client::rpc_client::RpcClient, + addresses: &[solana_pubkey::Pubkey], +) -> Result>, std::io::Error> { + let accounts = rpc + .get_multiple_accounts(addresses) + .map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, e.to_string()))?; + let mut decoded_accounts: Vec> = + Vec::new(); + for i in 0..addresses.len() { + let address = addresses[i]; + let account = accounts[i].as_ref().ok_or(std::io::Error::new( + std::io::ErrorKind::Other, + format!("Account not found: {}", address), + ))?; + let data = LegacyTokenOwnerRecord::from_bytes(&account.data)?; + decoded_accounts.push(crate::shared::DecodedAccount { + address, + account: account.clone(), + data, + }); + } + Ok(decoded_accounts) +} + +#[cfg(feature = "fetch")] +pub fn fetch_maybe_legacy_token_owner_record( + rpc: &solana_client::rpc_client::RpcClient, + address: &solana_pubkey::Pubkey, +) -> Result, std::io::Error> { + let accounts = fetch_all_maybe_legacy_token_owner_record(rpc, &[*address])?; + Ok(accounts[0].clone()) +} + +#[cfg(feature = "fetch")] +pub fn fetch_all_maybe_legacy_token_owner_record( + rpc: &solana_client::rpc_client::RpcClient, + addresses: &[solana_pubkey::Pubkey], +) -> Result>, std::io::Error> { + let accounts = rpc + .get_multiple_accounts(addresses) + .map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, e.to_string()))?; + let mut decoded_accounts: Vec> = Vec::new(); + for i in 0..addresses.len() { + let address = addresses[i]; + if let Some(account) = accounts[i].as_ref() { + let data = LegacyTokenOwnerRecord::from_bytes(&account.data)?; + decoded_accounts.push(crate::shared::MaybeAccount::Exists( + crate::shared::DecodedAccount { + address, + account: account.clone(), + data, + }, + )); + } else { + decoded_accounts.push(crate::shared::MaybeAccount::NotFound(address)); + } + } + Ok(decoded_accounts) +} + +#[cfg(feature = "anchor")] +impl anchor_lang::AccountDeserialize for LegacyTokenOwnerRecord { + fn try_deserialize_unchecked(buf: &mut &[u8]) -> anchor_lang::Result { + Ok(Self::deserialize(buf)?) + } +} + +#[cfg(feature = "anchor")] +impl anchor_lang::AccountSerialize for LegacyTokenOwnerRecord {} + +#[cfg(feature = "anchor")] +impl anchor_lang::Owner for LegacyTokenOwnerRecord { + fn owner() -> Pubkey { + crate::SPL_GOVERNANCE_ID + } +} + +#[cfg(feature = "anchor-idl-build")] +impl anchor_lang::IdlBuild for LegacyTokenOwnerRecord {} + +#[cfg(feature = "anchor-idl-build")] +impl anchor_lang::Discriminator for LegacyTokenOwnerRecord { + const DISCRIMINATOR: &[u8] = &[0; 8]; +} diff --git a/e2e/governance/src/generated/accounts/mod.rs b/e2e/governance/src/generated/accounts/mod.rs new file mode 100644 index 0000000..4160ab4 --- /dev/null +++ b/e2e/governance/src/generated/accounts/mod.rs @@ -0,0 +1,46 @@ +//! This code was AUTOGENERATED using the codama library. +//! Please DO NOT EDIT THIS FILE, instead use visitors +//! to add features, then rerun codama to update it. +//! +//! +//! + +pub(crate) mod r#governance_v1; +pub(crate) mod r#governance_v2; +pub(crate) mod r#legacy_token_owner_record; +pub(crate) mod r#program_metadata; +pub(crate) mod r#proposal_deposit; +pub(crate) mod r#proposal_instruction_v1; +pub(crate) mod r#proposal_transaction_v2; +pub(crate) mod r#proposal_v1; +pub(crate) mod r#proposal_v2; +pub(crate) mod r#realm_config_account; +pub(crate) mod r#realm_v1; +pub(crate) mod r#realm_v2; +pub(crate) mod r#required_signatory; +pub(crate) mod r#signatory_record_v1; +pub(crate) mod r#signatory_record_v2; +pub(crate) mod r#token_owner_record_v1; +pub(crate) mod r#token_owner_record_v2; +pub(crate) mod r#vote_record_v1; +pub(crate) mod r#vote_record_v2; + +pub use self::r#governance_v1::*; +pub use self::r#governance_v2::*; +pub use self::r#legacy_token_owner_record::*; +pub use self::r#program_metadata::*; +pub use self::r#proposal_deposit::*; +pub use self::r#proposal_instruction_v1::*; +pub use self::r#proposal_transaction_v2::*; +pub use self::r#proposal_v1::*; +pub use self::r#proposal_v2::*; +pub use self::r#realm_config_account::*; +pub use self::r#realm_v1::*; +pub use self::r#realm_v2::*; +pub use self::r#required_signatory::*; +pub use self::r#signatory_record_v1::*; +pub use self::r#signatory_record_v2::*; +pub use self::r#token_owner_record_v1::*; +pub use self::r#token_owner_record_v2::*; +pub use self::r#vote_record_v1::*; +pub use self::r#vote_record_v2::*; diff --git a/e2e/governance/src/generated/accounts/program_metadata.rs b/e2e/governance/src/generated/accounts/program_metadata.rs new file mode 100644 index 0000000..5e2b867 --- /dev/null +++ b/e2e/governance/src/generated/accounts/program_metadata.rs @@ -0,0 +1,133 @@ +//! This code was AUTOGENERATED using the codama library. +//! Please DO NOT EDIT THIS FILE, instead use visitors +//! to add features, then rerun codama to update it. +//! +//! +//! + +use crate::generated::types::GovernanceAccountType; +use crate::generated::types::Slot; +use borsh::BorshDeserialize; +use borsh::BorshSerialize; + +#[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct ProgramMetadata { + pub account_type: GovernanceAccountType, + pub updated_at: Slot, + pub version: String, + #[cfg_attr(feature = "serde", serde(with = "serde_big_array::BigArray"))] + pub reserved: [u8; 64], +} + +impl ProgramMetadata { + #[inline(always)] + pub fn from_bytes(data: &[u8]) -> Result { + let mut data = data; + Self::deserialize(&mut data) + } +} + +impl<'a> TryFrom<&solana_account_info::AccountInfo<'a>> for ProgramMetadata { + type Error = std::io::Error; + + fn try_from(account_info: &solana_account_info::AccountInfo<'a>) -> Result { + let mut data: &[u8] = &(*account_info.data).borrow(); + Self::deserialize(&mut data) + } +} + +#[cfg(feature = "fetch")] +pub fn fetch_program_metadata( + rpc: &solana_client::rpc_client::RpcClient, + address: &solana_pubkey::Pubkey, +) -> Result, std::io::Error> { + let accounts = fetch_all_program_metadata(rpc, &[*address])?; + Ok(accounts[0].clone()) +} + +#[cfg(feature = "fetch")] +pub fn fetch_all_program_metadata( + rpc: &solana_client::rpc_client::RpcClient, + addresses: &[solana_pubkey::Pubkey], +) -> Result>, std::io::Error> { + let accounts = rpc + .get_multiple_accounts(addresses) + .map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, e.to_string()))?; + let mut decoded_accounts: Vec> = Vec::new(); + for i in 0..addresses.len() { + let address = addresses[i]; + let account = accounts[i].as_ref().ok_or(std::io::Error::new( + std::io::ErrorKind::Other, + format!("Account not found: {}", address), + ))?; + let data = ProgramMetadata::from_bytes(&account.data)?; + decoded_accounts.push(crate::shared::DecodedAccount { + address, + account: account.clone(), + data, + }); + } + Ok(decoded_accounts) +} + +#[cfg(feature = "fetch")] +pub fn fetch_maybe_program_metadata( + rpc: &solana_client::rpc_client::RpcClient, + address: &solana_pubkey::Pubkey, +) -> Result, std::io::Error> { + let accounts = fetch_all_maybe_program_metadata(rpc, &[*address])?; + Ok(accounts[0].clone()) +} + +#[cfg(feature = "fetch")] +pub fn fetch_all_maybe_program_metadata( + rpc: &solana_client::rpc_client::RpcClient, + addresses: &[solana_pubkey::Pubkey], +) -> Result>, std::io::Error> { + let accounts = rpc + .get_multiple_accounts(addresses) + .map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, e.to_string()))?; + let mut decoded_accounts: Vec> = Vec::new(); + for i in 0..addresses.len() { + let address = addresses[i]; + if let Some(account) = accounts[i].as_ref() { + let data = ProgramMetadata::from_bytes(&account.data)?; + decoded_accounts.push(crate::shared::MaybeAccount::Exists( + crate::shared::DecodedAccount { + address, + account: account.clone(), + data, + }, + )); + } else { + decoded_accounts.push(crate::shared::MaybeAccount::NotFound(address)); + } + } + Ok(decoded_accounts) +} + +#[cfg(feature = "anchor")] +impl anchor_lang::AccountDeserialize for ProgramMetadata { + fn try_deserialize_unchecked(buf: &mut &[u8]) -> anchor_lang::Result { + Ok(Self::deserialize(buf)?) + } +} + +#[cfg(feature = "anchor")] +impl anchor_lang::AccountSerialize for ProgramMetadata {} + +#[cfg(feature = "anchor")] +impl anchor_lang::Owner for ProgramMetadata { + fn owner() -> Pubkey { + crate::SPL_GOVERNANCE_ID + } +} + +#[cfg(feature = "anchor-idl-build")] +impl anchor_lang::IdlBuild for ProgramMetadata {} + +#[cfg(feature = "anchor-idl-build")] +impl anchor_lang::Discriminator for ProgramMetadata { + const DISCRIMINATOR: &[u8] = &[0; 8]; +} diff --git a/e2e/governance/src/generated/accounts/proposal_deposit.rs b/e2e/governance/src/generated/accounts/proposal_deposit.rs new file mode 100644 index 0000000..695552b --- /dev/null +++ b/e2e/governance/src/generated/accounts/proposal_deposit.rs @@ -0,0 +1,177 @@ +//! This code was AUTOGENERATED using the codama library. +//! Please DO NOT EDIT THIS FILE, instead use visitors +//! to add features, then rerun codama to update it. +//! +//! +//! + +use crate::generated::types::GovernanceAccountType; +use borsh::BorshDeserialize; +use borsh::BorshSerialize; +use solana_pubkey::Pubkey; + +#[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct ProposalDeposit { + pub account_type: GovernanceAccountType, + #[cfg_attr( + feature = "serde", + serde(with = "serde_with::As::") + )] + pub proposal: Pubkey, + #[cfg_attr( + feature = "serde", + serde(with = "serde_with::As::") + )] + pub deposit_payer: Pubkey, + #[cfg_attr(feature = "serde", serde(with = "serde_big_array::BigArray"))] + pub reserved: [u8; 64], +} + +impl ProposalDeposit { + /// Prefix values used to generate a PDA for this account. + /// + /// Values are positional and appear in the following order: + /// + /// 0. `ProposalDeposit::PREFIX` + /// 1. proposal (`Pubkey`) + /// 2. deposit_payer (`Pubkey`) + pub const PREFIX: &'static [u8] = "proposal-deposit".as_bytes(); + + pub fn create_pda( + proposal: Pubkey, + deposit_payer: Pubkey, + bump: u8, + ) -> Result { + solana_pubkey::Pubkey::create_program_address( + &[ + "proposal-deposit".as_bytes(), + proposal.as_ref(), + deposit_payer.as_ref(), + &[bump], + ], + &crate::SPL_GOVERNANCE_ID, + ) + } + + pub fn find_pda(proposal: &Pubkey, deposit_payer: &Pubkey) -> (solana_pubkey::Pubkey, u8) { + solana_pubkey::Pubkey::find_program_address( + &[ + "proposal-deposit".as_bytes(), + proposal.as_ref(), + deposit_payer.as_ref(), + ], + &crate::SPL_GOVERNANCE_ID, + ) + } + + #[inline(always)] + pub fn from_bytes(data: &[u8]) -> Result { + let mut data = data; + Self::deserialize(&mut data) + } +} + +impl<'a> TryFrom<&solana_account_info::AccountInfo<'a>> for ProposalDeposit { + type Error = std::io::Error; + + fn try_from(account_info: &solana_account_info::AccountInfo<'a>) -> Result { + let mut data: &[u8] = &(*account_info.data).borrow(); + Self::deserialize(&mut data) + } +} + +#[cfg(feature = "fetch")] +pub fn fetch_proposal_deposit( + rpc: &solana_client::rpc_client::RpcClient, + address: &solana_pubkey::Pubkey, +) -> Result, std::io::Error> { + let accounts = fetch_all_proposal_deposit(rpc, &[*address])?; + Ok(accounts[0].clone()) +} + +#[cfg(feature = "fetch")] +pub fn fetch_all_proposal_deposit( + rpc: &solana_client::rpc_client::RpcClient, + addresses: &[solana_pubkey::Pubkey], +) -> Result>, std::io::Error> { + let accounts = rpc + .get_multiple_accounts(addresses) + .map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, e.to_string()))?; + let mut decoded_accounts: Vec> = Vec::new(); + for i in 0..addresses.len() { + let address = addresses[i]; + let account = accounts[i].as_ref().ok_or(std::io::Error::new( + std::io::ErrorKind::Other, + format!("Account not found: {}", address), + ))?; + let data = ProposalDeposit::from_bytes(&account.data)?; + decoded_accounts.push(crate::shared::DecodedAccount { + address, + account: account.clone(), + data, + }); + } + Ok(decoded_accounts) +} + +#[cfg(feature = "fetch")] +pub fn fetch_maybe_proposal_deposit( + rpc: &solana_client::rpc_client::RpcClient, + address: &solana_pubkey::Pubkey, +) -> Result, std::io::Error> { + let accounts = fetch_all_maybe_proposal_deposit(rpc, &[*address])?; + Ok(accounts[0].clone()) +} + +#[cfg(feature = "fetch")] +pub fn fetch_all_maybe_proposal_deposit( + rpc: &solana_client::rpc_client::RpcClient, + addresses: &[solana_pubkey::Pubkey], +) -> Result>, std::io::Error> { + let accounts = rpc + .get_multiple_accounts(addresses) + .map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, e.to_string()))?; + let mut decoded_accounts: Vec> = Vec::new(); + for i in 0..addresses.len() { + let address = addresses[i]; + if let Some(account) = accounts[i].as_ref() { + let data = ProposalDeposit::from_bytes(&account.data)?; + decoded_accounts.push(crate::shared::MaybeAccount::Exists( + crate::shared::DecodedAccount { + address, + account: account.clone(), + data, + }, + )); + } else { + decoded_accounts.push(crate::shared::MaybeAccount::NotFound(address)); + } + } + Ok(decoded_accounts) +} + +#[cfg(feature = "anchor")] +impl anchor_lang::AccountDeserialize for ProposalDeposit { + fn try_deserialize_unchecked(buf: &mut &[u8]) -> anchor_lang::Result { + Ok(Self::deserialize(buf)?) + } +} + +#[cfg(feature = "anchor")] +impl anchor_lang::AccountSerialize for ProposalDeposit {} + +#[cfg(feature = "anchor")] +impl anchor_lang::Owner for ProposalDeposit { + fn owner() -> Pubkey { + crate::SPL_GOVERNANCE_ID + } +} + +#[cfg(feature = "anchor-idl-build")] +impl anchor_lang::IdlBuild for ProposalDeposit {} + +#[cfg(feature = "anchor-idl-build")] +impl anchor_lang::Discriminator for ProposalDeposit { + const DISCRIMINATOR: &[u8] = &[0; 8]; +} diff --git a/e2e/governance/src/generated/accounts/proposal_instruction_v1.rs b/e2e/governance/src/generated/accounts/proposal_instruction_v1.rs new file mode 100644 index 0000000..28df3ab --- /dev/null +++ b/e2e/governance/src/generated/accounts/proposal_instruction_v1.rs @@ -0,0 +1,187 @@ +//! This code was AUTOGENERATED using the codama library. +//! Please DO NOT EDIT THIS FILE, instead use visitors +//! to add features, then rerun codama to update it. +//! +//! +//! + +use crate::generated::types::GovernanceAccountType; +use crate::generated::types::InstructionData; +use crate::generated::types::TransactionExecutionStatus; +use crate::generated::types::UnixTimestamp; +use borsh::BorshDeserialize; +use borsh::BorshSerialize; +use solana_pubkey::Pubkey; + +#[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct ProposalInstructionV1 { + pub account_type: GovernanceAccountType, + #[cfg_attr( + feature = "serde", + serde(with = "serde_with::As::") + )] + pub proposal: Pubkey, + pub instruction_index: u16, + pub hold_up_time: u32, + pub instruction: InstructionData, + pub executed_at: Option, + pub execution_status: TransactionExecutionStatus, +} + +impl ProposalInstructionV1 { + /// Prefix values used to generate a PDA for this account. + /// + /// Values are positional and appear in the following order: + /// + /// 0. `ProposalInstructionV1::PREFIX` + /// 1. proposal (`Pubkey`) + /// 2. option_index (`u8`) + /// 3. index (`u16`) + pub const PREFIX: &'static [u8] = "governance".as_bytes(); + + pub fn create_pda( + proposal: Pubkey, + option_index: u8, + index: u16, + bump: u8, + ) -> Result { + solana_pubkey::Pubkey::create_program_address( + &[ + "governance".as_bytes(), + proposal.as_ref(), + option_index.to_string().as_ref(), + index.to_string().as_ref(), + &[bump], + ], + &crate::SPL_GOVERNANCE_ID, + ) + } + + pub fn find_pda( + proposal: &Pubkey, + option_index: u8, + index: u16, + ) -> (solana_pubkey::Pubkey, u8) { + solana_pubkey::Pubkey::find_program_address( + &[ + "governance".as_bytes(), + proposal.as_ref(), + option_index.to_string().as_ref(), + index.to_string().as_ref(), + ], + &crate::SPL_GOVERNANCE_ID, + ) + } + + #[inline(always)] + pub fn from_bytes(data: &[u8]) -> Result { + let mut data = data; + Self::deserialize(&mut data) + } +} + +impl<'a> TryFrom<&solana_account_info::AccountInfo<'a>> for ProposalInstructionV1 { + type Error = std::io::Error; + + fn try_from(account_info: &solana_account_info::AccountInfo<'a>) -> Result { + let mut data: &[u8] = &(*account_info.data).borrow(); + Self::deserialize(&mut data) + } +} + +#[cfg(feature = "fetch")] +pub fn fetch_proposal_instruction_v1( + rpc: &solana_client::rpc_client::RpcClient, + address: &solana_pubkey::Pubkey, +) -> Result, std::io::Error> { + let accounts = fetch_all_proposal_instruction_v1(rpc, &[*address])?; + Ok(accounts[0].clone()) +} + +#[cfg(feature = "fetch")] +pub fn fetch_all_proposal_instruction_v1( + rpc: &solana_client::rpc_client::RpcClient, + addresses: &[solana_pubkey::Pubkey], +) -> Result>, std::io::Error> { + let accounts = rpc + .get_multiple_accounts(addresses) + .map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, e.to_string()))?; + let mut decoded_accounts: Vec> = + Vec::new(); + for i in 0..addresses.len() { + let address = addresses[i]; + let account = accounts[i].as_ref().ok_or(std::io::Error::new( + std::io::ErrorKind::Other, + format!("Account not found: {}", address), + ))?; + let data = ProposalInstructionV1::from_bytes(&account.data)?; + decoded_accounts.push(crate::shared::DecodedAccount { + address, + account: account.clone(), + data, + }); + } + Ok(decoded_accounts) +} + +#[cfg(feature = "fetch")] +pub fn fetch_maybe_proposal_instruction_v1( + rpc: &solana_client::rpc_client::RpcClient, + address: &solana_pubkey::Pubkey, +) -> Result, std::io::Error> { + let accounts = fetch_all_maybe_proposal_instruction_v1(rpc, &[*address])?; + Ok(accounts[0].clone()) +} + +#[cfg(feature = "fetch")] +pub fn fetch_all_maybe_proposal_instruction_v1( + rpc: &solana_client::rpc_client::RpcClient, + addresses: &[solana_pubkey::Pubkey], +) -> Result>, std::io::Error> { + let accounts = rpc + .get_multiple_accounts(addresses) + .map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, e.to_string()))?; + let mut decoded_accounts: Vec> = Vec::new(); + for i in 0..addresses.len() { + let address = addresses[i]; + if let Some(account) = accounts[i].as_ref() { + let data = ProposalInstructionV1::from_bytes(&account.data)?; + decoded_accounts.push(crate::shared::MaybeAccount::Exists( + crate::shared::DecodedAccount { + address, + account: account.clone(), + data, + }, + )); + } else { + decoded_accounts.push(crate::shared::MaybeAccount::NotFound(address)); + } + } + Ok(decoded_accounts) +} + +#[cfg(feature = "anchor")] +impl anchor_lang::AccountDeserialize for ProposalInstructionV1 { + fn try_deserialize_unchecked(buf: &mut &[u8]) -> anchor_lang::Result { + Ok(Self::deserialize(buf)?) + } +} + +#[cfg(feature = "anchor")] +impl anchor_lang::AccountSerialize for ProposalInstructionV1 {} + +#[cfg(feature = "anchor")] +impl anchor_lang::Owner for ProposalInstructionV1 { + fn owner() -> Pubkey { + crate::SPL_GOVERNANCE_ID + } +} + +#[cfg(feature = "anchor-idl-build")] +impl anchor_lang::IdlBuild for ProposalInstructionV1 {} + +#[cfg(feature = "anchor-idl-build")] +impl anchor_lang::Discriminator for ProposalInstructionV1 { + const DISCRIMINATOR: &[u8] = &[0; 8]; +} diff --git a/e2e/governance/src/generated/accounts/proposal_transaction_v2.rs b/e2e/governance/src/generated/accounts/proposal_transaction_v2.rs new file mode 100644 index 0000000..9fa1d2e --- /dev/null +++ b/e2e/governance/src/generated/accounts/proposal_transaction_v2.rs @@ -0,0 +1,189 @@ +//! This code was AUTOGENERATED using the codama library. +//! Please DO NOT EDIT THIS FILE, instead use visitors +//! to add features, then rerun codama to update it. +//! +//! +//! + +use crate::generated::types::GovernanceAccountType; +use crate::generated::types::InstructionData; +use crate::generated::types::TransactionExecutionStatus; +use crate::generated::types::UnixTimestamp; +use borsh::BorshDeserialize; +use borsh::BorshSerialize; +use solana_pubkey::Pubkey; + +#[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct ProposalTransactionV2 { + pub account_type: GovernanceAccountType, + #[cfg_attr( + feature = "serde", + serde(with = "serde_with::As::") + )] + pub proposal: Pubkey, + pub option_index: u8, + pub transaction_index: u16, + pub hold_up_time: u32, + pub instructions: Vec, + pub executed_at: Option, + pub execution_status: TransactionExecutionStatus, + pub reserved_v2: [u8; 8], +} + +impl ProposalTransactionV2 { + /// Prefix values used to generate a PDA for this account. + /// + /// Values are positional and appear in the following order: + /// + /// 0. `ProposalTransactionV2::PREFIX` + /// 1. proposal (`Pubkey`) + /// 2. option_index (`u8`) + /// 3. index (`u16`) + pub const PREFIX: &'static [u8] = "governance".as_bytes(); + + pub fn create_pda( + proposal: Pubkey, + option_index: u8, + index: u16, + bump: u8, + ) -> Result { + solana_pubkey::Pubkey::create_program_address( + &[ + "governance".as_bytes(), + proposal.as_ref(), + option_index.to_string().as_ref(), + index.to_string().as_ref(), + &[bump], + ], + &crate::SPL_GOVERNANCE_ID, + ) + } + + pub fn find_pda( + proposal: &Pubkey, + option_index: u8, + index: u16, + ) -> (solana_pubkey::Pubkey, u8) { + solana_pubkey::Pubkey::find_program_address( + &[ + "governance".as_bytes(), + proposal.as_ref(), + option_index.to_string().as_ref(), + index.to_string().as_ref(), + ], + &crate::SPL_GOVERNANCE_ID, + ) + } + + #[inline(always)] + pub fn from_bytes(data: &[u8]) -> Result { + let mut data = data; + Self::deserialize(&mut data) + } +} + +impl<'a> TryFrom<&solana_account_info::AccountInfo<'a>> for ProposalTransactionV2 { + type Error = std::io::Error; + + fn try_from(account_info: &solana_account_info::AccountInfo<'a>) -> Result { + let mut data: &[u8] = &(*account_info.data).borrow(); + Self::deserialize(&mut data) + } +} + +#[cfg(feature = "fetch")] +pub fn fetch_proposal_transaction_v2( + rpc: &solana_client::rpc_client::RpcClient, + address: &solana_pubkey::Pubkey, +) -> Result, std::io::Error> { + let accounts = fetch_all_proposal_transaction_v2(rpc, &[*address])?; + Ok(accounts[0].clone()) +} + +#[cfg(feature = "fetch")] +pub fn fetch_all_proposal_transaction_v2( + rpc: &solana_client::rpc_client::RpcClient, + addresses: &[solana_pubkey::Pubkey], +) -> Result>, std::io::Error> { + let accounts = rpc + .get_multiple_accounts(addresses) + .map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, e.to_string()))?; + let mut decoded_accounts: Vec> = + Vec::new(); + for i in 0..addresses.len() { + let address = addresses[i]; + let account = accounts[i].as_ref().ok_or(std::io::Error::new( + std::io::ErrorKind::Other, + format!("Account not found: {}", address), + ))?; + let data = ProposalTransactionV2::from_bytes(&account.data)?; + decoded_accounts.push(crate::shared::DecodedAccount { + address, + account: account.clone(), + data, + }); + } + Ok(decoded_accounts) +} + +#[cfg(feature = "fetch")] +pub fn fetch_maybe_proposal_transaction_v2( + rpc: &solana_client::rpc_client::RpcClient, + address: &solana_pubkey::Pubkey, +) -> Result, std::io::Error> { + let accounts = fetch_all_maybe_proposal_transaction_v2(rpc, &[*address])?; + Ok(accounts[0].clone()) +} + +#[cfg(feature = "fetch")] +pub fn fetch_all_maybe_proposal_transaction_v2( + rpc: &solana_client::rpc_client::RpcClient, + addresses: &[solana_pubkey::Pubkey], +) -> Result>, std::io::Error> { + let accounts = rpc + .get_multiple_accounts(addresses) + .map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, e.to_string()))?; + let mut decoded_accounts: Vec> = Vec::new(); + for i in 0..addresses.len() { + let address = addresses[i]; + if let Some(account) = accounts[i].as_ref() { + let data = ProposalTransactionV2::from_bytes(&account.data)?; + decoded_accounts.push(crate::shared::MaybeAccount::Exists( + crate::shared::DecodedAccount { + address, + account: account.clone(), + data, + }, + )); + } else { + decoded_accounts.push(crate::shared::MaybeAccount::NotFound(address)); + } + } + Ok(decoded_accounts) +} + +#[cfg(feature = "anchor")] +impl anchor_lang::AccountDeserialize for ProposalTransactionV2 { + fn try_deserialize_unchecked(buf: &mut &[u8]) -> anchor_lang::Result { + Ok(Self::deserialize(buf)?) + } +} + +#[cfg(feature = "anchor")] +impl anchor_lang::AccountSerialize for ProposalTransactionV2 {} + +#[cfg(feature = "anchor")] +impl anchor_lang::Owner for ProposalTransactionV2 { + fn owner() -> Pubkey { + crate::SPL_GOVERNANCE_ID + } +} + +#[cfg(feature = "anchor-idl-build")] +impl anchor_lang::IdlBuild for ProposalTransactionV2 {} + +#[cfg(feature = "anchor-idl-build")] +impl anchor_lang::Discriminator for ProposalTransactionV2 { + const DISCRIMINATOR: &[u8] = &[0; 8]; +} diff --git a/e2e/governance/src/generated/accounts/proposal_v1.rs b/e2e/governance/src/generated/accounts/proposal_v1.rs new file mode 100644 index 0000000..7c68cb4 --- /dev/null +++ b/e2e/governance/src/generated/accounts/proposal_v1.rs @@ -0,0 +1,213 @@ +//! This code was AUTOGENERATED using the codama library. +//! Please DO NOT EDIT THIS FILE, instead use visitors +//! to add features, then rerun codama to update it. +//! +//! +//! + +use crate::generated::types::GovernanceAccountType; +use crate::generated::types::InstructionExecutionFlags; +use crate::generated::types::ProposalState; +use crate::generated::types::Slot; +use crate::generated::types::UnixTimestamp; +use crate::generated::types::VoteThreshold; +use borsh::BorshDeserialize; +use borsh::BorshSerialize; +use solana_pubkey::Pubkey; + +#[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct ProposalV1 { + pub account_type: GovernanceAccountType, + #[cfg_attr( + feature = "serde", + serde(with = "serde_with::As::") + )] + pub governance: Pubkey, + #[cfg_attr( + feature = "serde", + serde(with = "serde_with::As::") + )] + pub governing_token_mint: Pubkey, + pub state: ProposalState, + #[cfg_attr( + feature = "serde", + serde(with = "serde_with::As::") + )] + pub token_owner_record: Pubkey, + pub signatories_count: u8, + pub signatories_signed_off_count: u8, + pub yes_votes_count: u64, + pub no_votes_count: u64, + pub instructions_executed_count: u16, + pub instructions_count: u16, + pub instructions_next_index: u16, + pub draft_at: UnixTimestamp, + pub signing_off_at: Option, + pub voting_at: Option, + pub voting_at_slot: Option, + pub voting_completed_at: Option, + pub executing_at: Option, + pub closed_at: Option, + pub execution_flags: InstructionExecutionFlags, + pub max_vote_weight: Option, + pub vote_threshold: Option, + pub name: String, + pub description_link: String, +} + +impl ProposalV1 { + /// Prefix values used to generate a PDA for this account. + /// + /// Values are positional and appear in the following order: + /// + /// 0. `ProposalV1::PREFIX` + /// 1. governance (`Pubkey`) + /// 2. governing_token_mint (`Pubkey`) + /// 3. proposal_seed (`Pubkey`) + pub const PREFIX: &'static [u8] = "governance".as_bytes(); + + pub fn create_pda( + governance: Pubkey, + governing_token_mint: Pubkey, + proposal_seed: Pubkey, + bump: u8, + ) -> Result { + solana_pubkey::Pubkey::create_program_address( + &[ + "governance".as_bytes(), + governance.as_ref(), + governing_token_mint.as_ref(), + proposal_seed.as_ref(), + &[bump], + ], + &crate::SPL_GOVERNANCE_ID, + ) + } + + pub fn find_pda( + governance: &Pubkey, + governing_token_mint: &Pubkey, + proposal_seed: &Pubkey, + ) -> (solana_pubkey::Pubkey, u8) { + solana_pubkey::Pubkey::find_program_address( + &[ + "governance".as_bytes(), + governance.as_ref(), + governing_token_mint.as_ref(), + proposal_seed.as_ref(), + ], + &crate::SPL_GOVERNANCE_ID, + ) + } + + #[inline(always)] + pub fn from_bytes(data: &[u8]) -> Result { + let mut data = data; + Self::deserialize(&mut data) + } +} + +impl<'a> TryFrom<&solana_account_info::AccountInfo<'a>> for ProposalV1 { + type Error = std::io::Error; + + fn try_from(account_info: &solana_account_info::AccountInfo<'a>) -> Result { + let mut data: &[u8] = &(*account_info.data).borrow(); + Self::deserialize(&mut data) + } +} + +#[cfg(feature = "fetch")] +pub fn fetch_proposal_v1( + rpc: &solana_client::rpc_client::RpcClient, + address: &solana_pubkey::Pubkey, +) -> Result, std::io::Error> { + let accounts = fetch_all_proposal_v1(rpc, &[*address])?; + Ok(accounts[0].clone()) +} + +#[cfg(feature = "fetch")] +pub fn fetch_all_proposal_v1( + rpc: &solana_client::rpc_client::RpcClient, + addresses: &[solana_pubkey::Pubkey], +) -> Result>, std::io::Error> { + let accounts = rpc + .get_multiple_accounts(addresses) + .map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, e.to_string()))?; + let mut decoded_accounts: Vec> = Vec::new(); + for i in 0..addresses.len() { + let address = addresses[i]; + let account = accounts[i].as_ref().ok_or(std::io::Error::new( + std::io::ErrorKind::Other, + format!("Account not found: {}", address), + ))?; + let data = ProposalV1::from_bytes(&account.data)?; + decoded_accounts.push(crate::shared::DecodedAccount { + address, + account: account.clone(), + data, + }); + } + Ok(decoded_accounts) +} + +#[cfg(feature = "fetch")] +pub fn fetch_maybe_proposal_v1( + rpc: &solana_client::rpc_client::RpcClient, + address: &solana_pubkey::Pubkey, +) -> Result, std::io::Error> { + let accounts = fetch_all_maybe_proposal_v1(rpc, &[*address])?; + Ok(accounts[0].clone()) +} + +#[cfg(feature = "fetch")] +pub fn fetch_all_maybe_proposal_v1( + rpc: &solana_client::rpc_client::RpcClient, + addresses: &[solana_pubkey::Pubkey], +) -> Result>, std::io::Error> { + let accounts = rpc + .get_multiple_accounts(addresses) + .map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, e.to_string()))?; + let mut decoded_accounts: Vec> = Vec::new(); + for i in 0..addresses.len() { + let address = addresses[i]; + if let Some(account) = accounts[i].as_ref() { + let data = ProposalV1::from_bytes(&account.data)?; + decoded_accounts.push(crate::shared::MaybeAccount::Exists( + crate::shared::DecodedAccount { + address, + account: account.clone(), + data, + }, + )); + } else { + decoded_accounts.push(crate::shared::MaybeAccount::NotFound(address)); + } + } + Ok(decoded_accounts) +} + +#[cfg(feature = "anchor")] +impl anchor_lang::AccountDeserialize for ProposalV1 { + fn try_deserialize_unchecked(buf: &mut &[u8]) -> anchor_lang::Result { + Ok(Self::deserialize(buf)?) + } +} + +#[cfg(feature = "anchor")] +impl anchor_lang::AccountSerialize for ProposalV1 {} + +#[cfg(feature = "anchor")] +impl anchor_lang::Owner for ProposalV1 { + fn owner() -> Pubkey { + crate::SPL_GOVERNANCE_ID + } +} + +#[cfg(feature = "anchor-idl-build")] +impl anchor_lang::IdlBuild for ProposalV1 {} + +#[cfg(feature = "anchor-idl-build")] +impl anchor_lang::Discriminator for ProposalV1 { + const DISCRIMINATOR: &[u8] = &[0; 8]; +} diff --git a/e2e/governance/src/generated/accounts/proposal_v2.rs b/e2e/governance/src/generated/accounts/proposal_v2.rs new file mode 100644 index 0000000..772d940 --- /dev/null +++ b/e2e/governance/src/generated/accounts/proposal_v2.rs @@ -0,0 +1,220 @@ +//! This code was AUTOGENERATED using the codama library. +//! Please DO NOT EDIT THIS FILE, instead use visitors +//! to add features, then rerun codama to update it. +//! +//! +//! + +use crate::generated::types::GovernanceAccountType; +use crate::generated::types::InstructionExecutionFlags; +use crate::generated::types::ProposalOption; +use crate::generated::types::ProposalState; +use crate::generated::types::Slot; +use crate::generated::types::UnixTimestamp; +use crate::generated::types::VoteThreshold; +use crate::generated::types::VoteType; +use borsh::BorshDeserialize; +use borsh::BorshSerialize; +use solana_pubkey::Pubkey; + +#[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct ProposalV2 { + pub account_type: GovernanceAccountType, + #[cfg_attr( + feature = "serde", + serde(with = "serde_with::As::") + )] + pub governance: Pubkey, + #[cfg_attr( + feature = "serde", + serde(with = "serde_with::As::") + )] + pub governing_token_mint: Pubkey, + pub state: ProposalState, + #[cfg_attr( + feature = "serde", + serde(with = "serde_with::As::") + )] + pub token_owner_record: Pubkey, + pub signatories_count: u8, + pub signatories_signed_off_count: u8, + pub vote_type: VoteType, + pub options: Vec, + pub deny_vote_weight: Option, + pub reserved1: u8, + pub abstain_vote_weight: Option, + pub start_voting_at: Option, + pub draft_at: UnixTimestamp, + pub signing_off_at: Option, + pub voting_at: Option, + pub voting_at_slot: Option, + pub voting_completed_at: Option, + pub executing_at: Option, + pub closed_at: Option, + pub execution_flags: InstructionExecutionFlags, + pub max_vote_weight: Option, + pub max_voting_time: Option, + pub vote_threshold: Option, + #[cfg_attr(feature = "serde", serde(with = "serde_big_array::BigArray"))] + pub reserved: [u8; 64], + pub name: String, + pub description_link: String, + pub veto_vote_weight: u64, +} + +impl ProposalV2 { + /// Prefix values used to generate a PDA for this account. + /// + /// Values are positional and appear in the following order: + /// + /// 0. `ProposalV2::PREFIX` + /// 1. governance (`Pubkey`) + /// 2. governing_token_mint (`Pubkey`) + /// 3. proposal_seed (`Pubkey`) + pub const PREFIX: &'static [u8] = "governance".as_bytes(); + + pub fn create_pda( + governance: Pubkey, + governing_token_mint: Pubkey, + proposal_seed: Pubkey, + bump: u8, + ) -> Result { + solana_pubkey::Pubkey::create_program_address( + &[ + "governance".as_bytes(), + governance.as_ref(), + governing_token_mint.as_ref(), + proposal_seed.as_ref(), + &[bump], + ], + &crate::SPL_GOVERNANCE_ID, + ) + } + + pub fn find_pda( + governance: &Pubkey, + governing_token_mint: &Pubkey, + proposal_seed: &Pubkey, + ) -> (solana_pubkey::Pubkey, u8) { + solana_pubkey::Pubkey::find_program_address( + &[ + "governance".as_bytes(), + governance.as_ref(), + governing_token_mint.as_ref(), + proposal_seed.as_ref(), + ], + &crate::SPL_GOVERNANCE_ID, + ) + } + + #[inline(always)] + pub fn from_bytes(data: &[u8]) -> Result { + let mut data = data; + Self::deserialize(&mut data) + } +} + +impl<'a> TryFrom<&solana_account_info::AccountInfo<'a>> for ProposalV2 { + type Error = std::io::Error; + + fn try_from(account_info: &solana_account_info::AccountInfo<'a>) -> Result { + let mut data: &[u8] = &(*account_info.data).borrow(); + Self::deserialize(&mut data) + } +} + +#[cfg(feature = "fetch")] +pub fn fetch_proposal_v2( + rpc: &solana_client::rpc_client::RpcClient, + address: &solana_pubkey::Pubkey, +) -> Result, std::io::Error> { + let accounts = fetch_all_proposal_v2(rpc, &[*address])?; + Ok(accounts[0].clone()) +} + +#[cfg(feature = "fetch")] +pub fn fetch_all_proposal_v2( + rpc: &solana_client::rpc_client::RpcClient, + addresses: &[solana_pubkey::Pubkey], +) -> Result>, std::io::Error> { + let accounts = rpc + .get_multiple_accounts(addresses) + .map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, e.to_string()))?; + let mut decoded_accounts: Vec> = Vec::new(); + for i in 0..addresses.len() { + let address = addresses[i]; + let account = accounts[i].as_ref().ok_or(std::io::Error::new( + std::io::ErrorKind::Other, + format!("Account not found: {}", address), + ))?; + let data = ProposalV2::from_bytes(&account.data)?; + decoded_accounts.push(crate::shared::DecodedAccount { + address, + account: account.clone(), + data, + }); + } + Ok(decoded_accounts) +} + +#[cfg(feature = "fetch")] +pub fn fetch_maybe_proposal_v2( + rpc: &solana_client::rpc_client::RpcClient, + address: &solana_pubkey::Pubkey, +) -> Result, std::io::Error> { + let accounts = fetch_all_maybe_proposal_v2(rpc, &[*address])?; + Ok(accounts[0].clone()) +} + +#[cfg(feature = "fetch")] +pub fn fetch_all_maybe_proposal_v2( + rpc: &solana_client::rpc_client::RpcClient, + addresses: &[solana_pubkey::Pubkey], +) -> Result>, std::io::Error> { + let accounts = rpc + .get_multiple_accounts(addresses) + .map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, e.to_string()))?; + let mut decoded_accounts: Vec> = Vec::new(); + for i in 0..addresses.len() { + let address = addresses[i]; + if let Some(account) = accounts[i].as_ref() { + let data = ProposalV2::from_bytes(&account.data)?; + decoded_accounts.push(crate::shared::MaybeAccount::Exists( + crate::shared::DecodedAccount { + address, + account: account.clone(), + data, + }, + )); + } else { + decoded_accounts.push(crate::shared::MaybeAccount::NotFound(address)); + } + } + Ok(decoded_accounts) +} + +#[cfg(feature = "anchor")] +impl anchor_lang::AccountDeserialize for ProposalV2 { + fn try_deserialize_unchecked(buf: &mut &[u8]) -> anchor_lang::Result { + Ok(Self::deserialize(buf)?) + } +} + +#[cfg(feature = "anchor")] +impl anchor_lang::AccountSerialize for ProposalV2 {} + +#[cfg(feature = "anchor")] +impl anchor_lang::Owner for ProposalV2 { + fn owner() -> Pubkey { + crate::SPL_GOVERNANCE_ID + } +} + +#[cfg(feature = "anchor-idl-build")] +impl anchor_lang::IdlBuild for ProposalV2 {} + +#[cfg(feature = "anchor-idl-build")] +impl anchor_lang::Discriminator for ProposalV2 { + const DISCRIMINATOR: &[u8] = &[0; 8]; +} diff --git a/e2e/governance/src/generated/accounts/realm_config_account.rs b/e2e/governance/src/generated/accounts/realm_config_account.rs new file mode 100644 index 0000000..2892b1b --- /dev/null +++ b/e2e/governance/src/generated/accounts/realm_config_account.rs @@ -0,0 +1,164 @@ +//! This code was AUTOGENERATED using the codama library. +//! Please DO NOT EDIT THIS FILE, instead use visitors +//! to add features, then rerun codama to update it. +//! +//! +//! + +use crate::generated::types::GovernanceAccountType; +use crate::generated::types::GoverningTokenConfig; +use crate::generated::types::Reserved110; +use borsh::BorshDeserialize; +use borsh::BorshSerialize; +use solana_pubkey::Pubkey; + +#[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct RealmConfigAccount { + pub account_type: GovernanceAccountType, + #[cfg_attr( + feature = "serde", + serde(with = "serde_with::As::") + )] + pub realm: Pubkey, + pub community_token_config: GoverningTokenConfig, + pub council_token_config: GoverningTokenConfig, + pub reserved: Reserved110, +} + +impl RealmConfigAccount { + /// Prefix values used to generate a PDA for this account. + /// + /// Values are positional and appear in the following order: + /// + /// 0. `RealmConfigAccount::PREFIX` + /// 1. realm (`Pubkey`) + pub const PREFIX: &'static [u8] = "realm-config".as_bytes(); + + pub fn create_pda( + realm: Pubkey, + bump: u8, + ) -> Result { + solana_pubkey::Pubkey::create_program_address( + &["realm-config".as_bytes(), realm.as_ref(), &[bump]], + &crate::SPL_GOVERNANCE_ID, + ) + } + + pub fn find_pda(realm: &Pubkey) -> (solana_pubkey::Pubkey, u8) { + solana_pubkey::Pubkey::find_program_address( + &["realm-config".as_bytes(), realm.as_ref()], + &crate::SPL_GOVERNANCE_ID, + ) + } + + #[inline(always)] + pub fn from_bytes(data: &[u8]) -> Result { + let mut data = data; + Self::deserialize(&mut data) + } +} + +impl<'a> TryFrom<&solana_account_info::AccountInfo<'a>> for RealmConfigAccount { + type Error = std::io::Error; + + fn try_from(account_info: &solana_account_info::AccountInfo<'a>) -> Result { + let mut data: &[u8] = &(*account_info.data).borrow(); + Self::deserialize(&mut data) + } +} + +#[cfg(feature = "fetch")] +pub fn fetch_realm_config_account( + rpc: &solana_client::rpc_client::RpcClient, + address: &solana_pubkey::Pubkey, +) -> Result, std::io::Error> { + let accounts = fetch_all_realm_config_account(rpc, &[*address])?; + Ok(accounts[0].clone()) +} + +#[cfg(feature = "fetch")] +pub fn fetch_all_realm_config_account( + rpc: &solana_client::rpc_client::RpcClient, + addresses: &[solana_pubkey::Pubkey], +) -> Result>, std::io::Error> { + let accounts = rpc + .get_multiple_accounts(addresses) + .map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, e.to_string()))?; + let mut decoded_accounts: Vec> = Vec::new(); + for i in 0..addresses.len() { + let address = addresses[i]; + let account = accounts[i].as_ref().ok_or(std::io::Error::new( + std::io::ErrorKind::Other, + format!("Account not found: {}", address), + ))?; + let data = RealmConfigAccount::from_bytes(&account.data)?; + decoded_accounts.push(crate::shared::DecodedAccount { + address, + account: account.clone(), + data, + }); + } + Ok(decoded_accounts) +} + +#[cfg(feature = "fetch")] +pub fn fetch_maybe_realm_config_account( + rpc: &solana_client::rpc_client::RpcClient, + address: &solana_pubkey::Pubkey, +) -> Result, std::io::Error> { + let accounts = fetch_all_maybe_realm_config_account(rpc, &[*address])?; + Ok(accounts[0].clone()) +} + +#[cfg(feature = "fetch")] +pub fn fetch_all_maybe_realm_config_account( + rpc: &solana_client::rpc_client::RpcClient, + addresses: &[solana_pubkey::Pubkey], +) -> Result>, std::io::Error> { + let accounts = rpc + .get_multiple_accounts(addresses) + .map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, e.to_string()))?; + let mut decoded_accounts: Vec> = Vec::new(); + for i in 0..addresses.len() { + let address = addresses[i]; + if let Some(account) = accounts[i].as_ref() { + let data = RealmConfigAccount::from_bytes(&account.data)?; + decoded_accounts.push(crate::shared::MaybeAccount::Exists( + crate::shared::DecodedAccount { + address, + account: account.clone(), + data, + }, + )); + } else { + decoded_accounts.push(crate::shared::MaybeAccount::NotFound(address)); + } + } + Ok(decoded_accounts) +} + +#[cfg(feature = "anchor")] +impl anchor_lang::AccountDeserialize for RealmConfigAccount { + fn try_deserialize_unchecked(buf: &mut &[u8]) -> anchor_lang::Result { + Ok(Self::deserialize(buf)?) + } +} + +#[cfg(feature = "anchor")] +impl anchor_lang::AccountSerialize for RealmConfigAccount {} + +#[cfg(feature = "anchor")] +impl anchor_lang::Owner for RealmConfigAccount { + fn owner() -> Pubkey { + crate::SPL_GOVERNANCE_ID + } +} + +#[cfg(feature = "anchor-idl-build")] +impl anchor_lang::IdlBuild for RealmConfigAccount {} + +#[cfg(feature = "anchor-idl-build")] +impl anchor_lang::Discriminator for RealmConfigAccount { + const DISCRIMINATOR: &[u8] = &[0; 8]; +} diff --git a/e2e/governance/src/generated/accounts/realm_v1.rs b/e2e/governance/src/generated/accounts/realm_v1.rs new file mode 100644 index 0000000..d9d5dad --- /dev/null +++ b/e2e/governance/src/generated/accounts/realm_v1.rs @@ -0,0 +1,166 @@ +//! This code was AUTOGENERATED using the codama library. +//! Please DO NOT EDIT THIS FILE, instead use visitors +//! to add features, then rerun codama to update it. +//! +//! +//! + +use crate::generated::types::GovernanceAccountType; +use crate::generated::types::RealmConfig; +use borsh::BorshDeserialize; +use borsh::BorshSerialize; +use kaigan::types::RemainderStr; +use solana_pubkey::Pubkey; + +#[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct RealmV1 { + pub account_type: GovernanceAccountType, + #[cfg_attr( + feature = "serde", + serde(with = "serde_with::As::") + )] + pub community_mint: Pubkey, + pub config: RealmConfig, + pub reserved: [u8; 6], + pub voting_proposal_count: u16, + pub authority: Option, + pub name: String, +} + +impl RealmV1 { + /// Prefix values used to generate a PDA for this account. + /// + /// Values are positional and appear in the following order: + /// + /// 0. `RealmV1::PREFIX` + /// 1. name (`RemainderStr`) + pub const PREFIX: &'static [u8] = "governance".as_bytes(); + + pub fn create_pda( + name: RemainderStr, + bump: u8, + ) -> Result { + solana_pubkey::Pubkey::create_program_address( + &["governance".as_bytes(), name.to_string().as_ref(), &[bump]], + &crate::SPL_GOVERNANCE_ID, + ) + } + + pub fn find_pda(name: RemainderStr) -> (solana_pubkey::Pubkey, u8) { + solana_pubkey::Pubkey::find_program_address( + &["governance".as_bytes(), name.to_string().as_ref()], + &crate::SPL_GOVERNANCE_ID, + ) + } + + #[inline(always)] + pub fn from_bytes(data: &[u8]) -> Result { + let mut data = data; + Self::deserialize(&mut data) + } +} + +impl<'a> TryFrom<&solana_account_info::AccountInfo<'a>> for RealmV1 { + type Error = std::io::Error; + + fn try_from(account_info: &solana_account_info::AccountInfo<'a>) -> Result { + let mut data: &[u8] = &(*account_info.data).borrow(); + Self::deserialize(&mut data) + } +} + +#[cfg(feature = "fetch")] +pub fn fetch_realm_v1( + rpc: &solana_client::rpc_client::RpcClient, + address: &solana_pubkey::Pubkey, +) -> Result, std::io::Error> { + let accounts = fetch_all_realm_v1(rpc, &[*address])?; + Ok(accounts[0].clone()) +} + +#[cfg(feature = "fetch")] +pub fn fetch_all_realm_v1( + rpc: &solana_client::rpc_client::RpcClient, + addresses: &[solana_pubkey::Pubkey], +) -> Result>, std::io::Error> { + let accounts = rpc + .get_multiple_accounts(addresses) + .map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, e.to_string()))?; + let mut decoded_accounts: Vec> = Vec::new(); + for i in 0..addresses.len() { + let address = addresses[i]; + let account = accounts[i].as_ref().ok_or(std::io::Error::new( + std::io::ErrorKind::Other, + format!("Account not found: {}", address), + ))?; + let data = RealmV1::from_bytes(&account.data)?; + decoded_accounts.push(crate::shared::DecodedAccount { + address, + account: account.clone(), + data, + }); + } + Ok(decoded_accounts) +} + +#[cfg(feature = "fetch")] +pub fn fetch_maybe_realm_v1( + rpc: &solana_client::rpc_client::RpcClient, + address: &solana_pubkey::Pubkey, +) -> Result, std::io::Error> { + let accounts = fetch_all_maybe_realm_v1(rpc, &[*address])?; + Ok(accounts[0].clone()) +} + +#[cfg(feature = "fetch")] +pub fn fetch_all_maybe_realm_v1( + rpc: &solana_client::rpc_client::RpcClient, + addresses: &[solana_pubkey::Pubkey], +) -> Result>, std::io::Error> { + let accounts = rpc + .get_multiple_accounts(addresses) + .map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, e.to_string()))?; + let mut decoded_accounts: Vec> = Vec::new(); + for i in 0..addresses.len() { + let address = addresses[i]; + if let Some(account) = accounts[i].as_ref() { + let data = RealmV1::from_bytes(&account.data)?; + decoded_accounts.push(crate::shared::MaybeAccount::Exists( + crate::shared::DecodedAccount { + address, + account: account.clone(), + data, + }, + )); + } else { + decoded_accounts.push(crate::shared::MaybeAccount::NotFound(address)); + } + } + Ok(decoded_accounts) +} + +#[cfg(feature = "anchor")] +impl anchor_lang::AccountDeserialize for RealmV1 { + fn try_deserialize_unchecked(buf: &mut &[u8]) -> anchor_lang::Result { + Ok(Self::deserialize(buf)?) + } +} + +#[cfg(feature = "anchor")] +impl anchor_lang::AccountSerialize for RealmV1 {} + +#[cfg(feature = "anchor")] +impl anchor_lang::Owner for RealmV1 { + fn owner() -> Pubkey { + crate::SPL_GOVERNANCE_ID + } +} + +#[cfg(feature = "anchor-idl-build")] +impl anchor_lang::IdlBuild for RealmV1 {} + +#[cfg(feature = "anchor-idl-build")] +impl anchor_lang::Discriminator for RealmV1 { + const DISCRIMINATOR: &[u8] = &[0; 8]; +} diff --git a/e2e/governance/src/generated/accounts/realm_v2.rs b/e2e/governance/src/generated/accounts/realm_v2.rs new file mode 100644 index 0000000..04551d8 --- /dev/null +++ b/e2e/governance/src/generated/accounts/realm_v2.rs @@ -0,0 +1,168 @@ +//! This code was AUTOGENERATED using the codama library. +//! Please DO NOT EDIT THIS FILE, instead use visitors +//! to add features, then rerun codama to update it. +//! +//! +//! + +use crate::generated::types::GovernanceAccountType; +use crate::generated::types::RealmConfig; +use borsh::BorshDeserialize; +use borsh::BorshSerialize; +use kaigan::types::RemainderStr; +use solana_pubkey::Pubkey; + +#[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct RealmV2 { + pub account_type: GovernanceAccountType, + #[cfg_attr( + feature = "serde", + serde(with = "serde_with::As::") + )] + pub community_mint: Pubkey, + pub config: RealmConfig, + pub reserved: [u8; 6], + pub legacy1: u16, + pub authority: Option, + pub name: String, + #[cfg_attr(feature = "serde", serde(with = "serde_big_array::BigArray"))] + pub reserved_v2: [u8; 128], +} + +impl RealmV2 { + /// Prefix values used to generate a PDA for this account. + /// + /// Values are positional and appear in the following order: + /// + /// 0. `RealmV2::PREFIX` + /// 1. name (`RemainderStr`) + pub const PREFIX: &'static [u8] = "governance".as_bytes(); + + pub fn create_pda( + name: RemainderStr, + bump: u8, + ) -> Result { + solana_pubkey::Pubkey::create_program_address( + &["governance".as_bytes(), name.to_string().as_ref(), &[bump]], + &crate::SPL_GOVERNANCE_ID, + ) + } + + pub fn find_pda(name: RemainderStr) -> (solana_pubkey::Pubkey, u8) { + solana_pubkey::Pubkey::find_program_address( + &["governance".as_bytes(), name.to_string().as_ref()], + &crate::SPL_GOVERNANCE_ID, + ) + } + + #[inline(always)] + pub fn from_bytes(data: &[u8]) -> Result { + let mut data = data; + Self::deserialize(&mut data) + } +} + +impl<'a> TryFrom<&solana_account_info::AccountInfo<'a>> for RealmV2 { + type Error = std::io::Error; + + fn try_from(account_info: &solana_account_info::AccountInfo<'a>) -> Result { + let mut data: &[u8] = &(*account_info.data).borrow(); + Self::deserialize(&mut data) + } +} + +#[cfg(feature = "fetch")] +pub fn fetch_realm_v2( + rpc: &solana_client::rpc_client::RpcClient, + address: &solana_pubkey::Pubkey, +) -> Result, std::io::Error> { + let accounts = fetch_all_realm_v2(rpc, &[*address])?; + Ok(accounts[0].clone()) +} + +#[cfg(feature = "fetch")] +pub fn fetch_all_realm_v2( + rpc: &solana_client::rpc_client::RpcClient, + addresses: &[solana_pubkey::Pubkey], +) -> Result>, std::io::Error> { + let accounts = rpc + .get_multiple_accounts(addresses) + .map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, e.to_string()))?; + let mut decoded_accounts: Vec> = Vec::new(); + for i in 0..addresses.len() { + let address = addresses[i]; + let account = accounts[i].as_ref().ok_or(std::io::Error::new( + std::io::ErrorKind::Other, + format!("Account not found: {}", address), + ))?; + let data = RealmV2::from_bytes(&account.data)?; + decoded_accounts.push(crate::shared::DecodedAccount { + address, + account: account.clone(), + data, + }); + } + Ok(decoded_accounts) +} + +#[cfg(feature = "fetch")] +pub fn fetch_maybe_realm_v2( + rpc: &solana_client::rpc_client::RpcClient, + address: &solana_pubkey::Pubkey, +) -> Result, std::io::Error> { + let accounts = fetch_all_maybe_realm_v2(rpc, &[*address])?; + Ok(accounts[0].clone()) +} + +#[cfg(feature = "fetch")] +pub fn fetch_all_maybe_realm_v2( + rpc: &solana_client::rpc_client::RpcClient, + addresses: &[solana_pubkey::Pubkey], +) -> Result>, std::io::Error> { + let accounts = rpc + .get_multiple_accounts(addresses) + .map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, e.to_string()))?; + let mut decoded_accounts: Vec> = Vec::new(); + for i in 0..addresses.len() { + let address = addresses[i]; + if let Some(account) = accounts[i].as_ref() { + let data = RealmV2::from_bytes(&account.data)?; + decoded_accounts.push(crate::shared::MaybeAccount::Exists( + crate::shared::DecodedAccount { + address, + account: account.clone(), + data, + }, + )); + } else { + decoded_accounts.push(crate::shared::MaybeAccount::NotFound(address)); + } + } + Ok(decoded_accounts) +} + +#[cfg(feature = "anchor")] +impl anchor_lang::AccountDeserialize for RealmV2 { + fn try_deserialize_unchecked(buf: &mut &[u8]) -> anchor_lang::Result { + Ok(Self::deserialize(buf)?) + } +} + +#[cfg(feature = "anchor")] +impl anchor_lang::AccountSerialize for RealmV2 {} + +#[cfg(feature = "anchor")] +impl anchor_lang::Owner for RealmV2 { + fn owner() -> Pubkey { + crate::SPL_GOVERNANCE_ID + } +} + +#[cfg(feature = "anchor-idl-build")] +impl anchor_lang::IdlBuild for RealmV2 {} + +#[cfg(feature = "anchor-idl-build")] +impl anchor_lang::Discriminator for RealmV2 { + const DISCRIMINATOR: &[u8] = &[0; 8]; +} diff --git a/e2e/governance/src/generated/accounts/required_signatory.rs b/e2e/governance/src/generated/accounts/required_signatory.rs new file mode 100644 index 0000000..3fbfc3e --- /dev/null +++ b/e2e/governance/src/generated/accounts/required_signatory.rs @@ -0,0 +1,176 @@ +//! This code was AUTOGENERATED using the codama library. +//! Please DO NOT EDIT THIS FILE, instead use visitors +//! to add features, then rerun codama to update it. +//! +//! +//! + +use crate::generated::types::GovernanceAccountType; +use borsh::BorshDeserialize; +use borsh::BorshSerialize; +use solana_pubkey::Pubkey; + +#[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct RequiredSignatory { + pub account_type: GovernanceAccountType, + pub account_version: u8, + #[cfg_attr( + feature = "serde", + serde(with = "serde_with::As::") + )] + pub governance: Pubkey, + #[cfg_attr( + feature = "serde", + serde(with = "serde_with::As::") + )] + pub signatory: Pubkey, +} + +impl RequiredSignatory { + /// Prefix values used to generate a PDA for this account. + /// + /// Values are positional and appear in the following order: + /// + /// 0. `RequiredSignatory::PREFIX` + /// 1. governance (`Pubkey`) + /// 2. signatory (`Pubkey`) + pub const PREFIX: &'static [u8] = "required-signatory".as_bytes(); + + pub fn create_pda( + governance: Pubkey, + signatory: Pubkey, + bump: u8, + ) -> Result { + solana_pubkey::Pubkey::create_program_address( + &[ + "required-signatory".as_bytes(), + governance.as_ref(), + signatory.as_ref(), + &[bump], + ], + &crate::SPL_GOVERNANCE_ID, + ) + } + + pub fn find_pda(governance: &Pubkey, signatory: &Pubkey) -> (solana_pubkey::Pubkey, u8) { + solana_pubkey::Pubkey::find_program_address( + &[ + "required-signatory".as_bytes(), + governance.as_ref(), + signatory.as_ref(), + ], + &crate::SPL_GOVERNANCE_ID, + ) + } + + #[inline(always)] + pub fn from_bytes(data: &[u8]) -> Result { + let mut data = data; + Self::deserialize(&mut data) + } +} + +impl<'a> TryFrom<&solana_account_info::AccountInfo<'a>> for RequiredSignatory { + type Error = std::io::Error; + + fn try_from(account_info: &solana_account_info::AccountInfo<'a>) -> Result { + let mut data: &[u8] = &(*account_info.data).borrow(); + Self::deserialize(&mut data) + } +} + +#[cfg(feature = "fetch")] +pub fn fetch_required_signatory( + rpc: &solana_client::rpc_client::RpcClient, + address: &solana_pubkey::Pubkey, +) -> Result, std::io::Error> { + let accounts = fetch_all_required_signatory(rpc, &[*address])?; + Ok(accounts[0].clone()) +} + +#[cfg(feature = "fetch")] +pub fn fetch_all_required_signatory( + rpc: &solana_client::rpc_client::RpcClient, + addresses: &[solana_pubkey::Pubkey], +) -> Result>, std::io::Error> { + let accounts = rpc + .get_multiple_accounts(addresses) + .map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, e.to_string()))?; + let mut decoded_accounts: Vec> = Vec::new(); + for i in 0..addresses.len() { + let address = addresses[i]; + let account = accounts[i].as_ref().ok_or(std::io::Error::new( + std::io::ErrorKind::Other, + format!("Account not found: {}", address), + ))?; + let data = RequiredSignatory::from_bytes(&account.data)?; + decoded_accounts.push(crate::shared::DecodedAccount { + address, + account: account.clone(), + data, + }); + } + Ok(decoded_accounts) +} + +#[cfg(feature = "fetch")] +pub fn fetch_maybe_required_signatory( + rpc: &solana_client::rpc_client::RpcClient, + address: &solana_pubkey::Pubkey, +) -> Result, std::io::Error> { + let accounts = fetch_all_maybe_required_signatory(rpc, &[*address])?; + Ok(accounts[0].clone()) +} + +#[cfg(feature = "fetch")] +pub fn fetch_all_maybe_required_signatory( + rpc: &solana_client::rpc_client::RpcClient, + addresses: &[solana_pubkey::Pubkey], +) -> Result>, std::io::Error> { + let accounts = rpc + .get_multiple_accounts(addresses) + .map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, e.to_string()))?; + let mut decoded_accounts: Vec> = Vec::new(); + for i in 0..addresses.len() { + let address = addresses[i]; + if let Some(account) = accounts[i].as_ref() { + let data = RequiredSignatory::from_bytes(&account.data)?; + decoded_accounts.push(crate::shared::MaybeAccount::Exists( + crate::shared::DecodedAccount { + address, + account: account.clone(), + data, + }, + )); + } else { + decoded_accounts.push(crate::shared::MaybeAccount::NotFound(address)); + } + } + Ok(decoded_accounts) +} + +#[cfg(feature = "anchor")] +impl anchor_lang::AccountDeserialize for RequiredSignatory { + fn try_deserialize_unchecked(buf: &mut &[u8]) -> anchor_lang::Result { + Ok(Self::deserialize(buf)?) + } +} + +#[cfg(feature = "anchor")] +impl anchor_lang::AccountSerialize for RequiredSignatory {} + +#[cfg(feature = "anchor")] +impl anchor_lang::Owner for RequiredSignatory { + fn owner() -> Pubkey { + crate::SPL_GOVERNANCE_ID + } +} + +#[cfg(feature = "anchor-idl-build")] +impl anchor_lang::IdlBuild for RequiredSignatory {} + +#[cfg(feature = "anchor-idl-build")] +impl anchor_lang::Discriminator for RequiredSignatory { + const DISCRIMINATOR: &[u8] = &[0; 8]; +} diff --git a/e2e/governance/src/generated/accounts/signatory_record_v1.rs b/e2e/governance/src/generated/accounts/signatory_record_v1.rs new file mode 100644 index 0000000..76fbe79 --- /dev/null +++ b/e2e/governance/src/generated/accounts/signatory_record_v1.rs @@ -0,0 +1,176 @@ +//! This code was AUTOGENERATED using the codama library. +//! Please DO NOT EDIT THIS FILE, instead use visitors +//! to add features, then rerun codama to update it. +//! +//! +//! + +use crate::generated::types::GovernanceAccountType; +use borsh::BorshDeserialize; +use borsh::BorshSerialize; +use solana_pubkey::Pubkey; + +#[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct SignatoryRecordV1 { + pub account_type: GovernanceAccountType, + #[cfg_attr( + feature = "serde", + serde(with = "serde_with::As::") + )] + pub proposal: Pubkey, + #[cfg_attr( + feature = "serde", + serde(with = "serde_with::As::") + )] + pub signatory: Pubkey, + pub signed_off: bool, +} + +impl SignatoryRecordV1 { + /// Prefix values used to generate a PDA for this account. + /// + /// Values are positional and appear in the following order: + /// + /// 0. `SignatoryRecordV1::PREFIX` + /// 1. proposal (`Pubkey`) + /// 2. signatory (`Pubkey`) + pub const PREFIX: &'static [u8] = "governance".as_bytes(); + + pub fn create_pda( + proposal: Pubkey, + signatory: Pubkey, + bump: u8, + ) -> Result { + solana_pubkey::Pubkey::create_program_address( + &[ + "governance".as_bytes(), + proposal.as_ref(), + signatory.as_ref(), + &[bump], + ], + &crate::SPL_GOVERNANCE_ID, + ) + } + + pub fn find_pda(proposal: &Pubkey, signatory: &Pubkey) -> (solana_pubkey::Pubkey, u8) { + solana_pubkey::Pubkey::find_program_address( + &[ + "governance".as_bytes(), + proposal.as_ref(), + signatory.as_ref(), + ], + &crate::SPL_GOVERNANCE_ID, + ) + } + + #[inline(always)] + pub fn from_bytes(data: &[u8]) -> Result { + let mut data = data; + Self::deserialize(&mut data) + } +} + +impl<'a> TryFrom<&solana_account_info::AccountInfo<'a>> for SignatoryRecordV1 { + type Error = std::io::Error; + + fn try_from(account_info: &solana_account_info::AccountInfo<'a>) -> Result { + let mut data: &[u8] = &(*account_info.data).borrow(); + Self::deserialize(&mut data) + } +} + +#[cfg(feature = "fetch")] +pub fn fetch_signatory_record_v1( + rpc: &solana_client::rpc_client::RpcClient, + address: &solana_pubkey::Pubkey, +) -> Result, std::io::Error> { + let accounts = fetch_all_signatory_record_v1(rpc, &[*address])?; + Ok(accounts[0].clone()) +} + +#[cfg(feature = "fetch")] +pub fn fetch_all_signatory_record_v1( + rpc: &solana_client::rpc_client::RpcClient, + addresses: &[solana_pubkey::Pubkey], +) -> Result>, std::io::Error> { + let accounts = rpc + .get_multiple_accounts(addresses) + .map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, e.to_string()))?; + let mut decoded_accounts: Vec> = Vec::new(); + for i in 0..addresses.len() { + let address = addresses[i]; + let account = accounts[i].as_ref().ok_or(std::io::Error::new( + std::io::ErrorKind::Other, + format!("Account not found: {}", address), + ))?; + let data = SignatoryRecordV1::from_bytes(&account.data)?; + decoded_accounts.push(crate::shared::DecodedAccount { + address, + account: account.clone(), + data, + }); + } + Ok(decoded_accounts) +} + +#[cfg(feature = "fetch")] +pub fn fetch_maybe_signatory_record_v1( + rpc: &solana_client::rpc_client::RpcClient, + address: &solana_pubkey::Pubkey, +) -> Result, std::io::Error> { + let accounts = fetch_all_maybe_signatory_record_v1(rpc, &[*address])?; + Ok(accounts[0].clone()) +} + +#[cfg(feature = "fetch")] +pub fn fetch_all_maybe_signatory_record_v1( + rpc: &solana_client::rpc_client::RpcClient, + addresses: &[solana_pubkey::Pubkey], +) -> Result>, std::io::Error> { + let accounts = rpc + .get_multiple_accounts(addresses) + .map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, e.to_string()))?; + let mut decoded_accounts: Vec> = Vec::new(); + for i in 0..addresses.len() { + let address = addresses[i]; + if let Some(account) = accounts[i].as_ref() { + let data = SignatoryRecordV1::from_bytes(&account.data)?; + decoded_accounts.push(crate::shared::MaybeAccount::Exists( + crate::shared::DecodedAccount { + address, + account: account.clone(), + data, + }, + )); + } else { + decoded_accounts.push(crate::shared::MaybeAccount::NotFound(address)); + } + } + Ok(decoded_accounts) +} + +#[cfg(feature = "anchor")] +impl anchor_lang::AccountDeserialize for SignatoryRecordV1 { + fn try_deserialize_unchecked(buf: &mut &[u8]) -> anchor_lang::Result { + Ok(Self::deserialize(buf)?) + } +} + +#[cfg(feature = "anchor")] +impl anchor_lang::AccountSerialize for SignatoryRecordV1 {} + +#[cfg(feature = "anchor")] +impl anchor_lang::Owner for SignatoryRecordV1 { + fn owner() -> Pubkey { + crate::SPL_GOVERNANCE_ID + } +} + +#[cfg(feature = "anchor-idl-build")] +impl anchor_lang::IdlBuild for SignatoryRecordV1 {} + +#[cfg(feature = "anchor-idl-build")] +impl anchor_lang::Discriminator for SignatoryRecordV1 { + const DISCRIMINATOR: &[u8] = &[0; 8]; +} diff --git a/e2e/governance/src/generated/accounts/signatory_record_v2.rs b/e2e/governance/src/generated/accounts/signatory_record_v2.rs new file mode 100644 index 0000000..40f57ea --- /dev/null +++ b/e2e/governance/src/generated/accounts/signatory_record_v2.rs @@ -0,0 +1,177 @@ +//! This code was AUTOGENERATED using the codama library. +//! Please DO NOT EDIT THIS FILE, instead use visitors +//! to add features, then rerun codama to update it. +//! +//! +//! + +use crate::generated::types::GovernanceAccountType; +use borsh::BorshDeserialize; +use borsh::BorshSerialize; +use solana_pubkey::Pubkey; + +#[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct SignatoryRecordV2 { + pub account_type: GovernanceAccountType, + #[cfg_attr( + feature = "serde", + serde(with = "serde_with::As::") + )] + pub proposal: Pubkey, + #[cfg_attr( + feature = "serde", + serde(with = "serde_with::As::") + )] + pub signatory: Pubkey, + pub signed_off: bool, + pub reserved_v2: [u8; 8], +} + +impl SignatoryRecordV2 { + /// Prefix values used to generate a PDA for this account. + /// + /// Values are positional and appear in the following order: + /// + /// 0. `SignatoryRecordV2::PREFIX` + /// 1. proposal (`Pubkey`) + /// 2. signatory (`Pubkey`) + pub const PREFIX: &'static [u8] = "governance".as_bytes(); + + pub fn create_pda( + proposal: Pubkey, + signatory: Pubkey, + bump: u8, + ) -> Result { + solana_pubkey::Pubkey::create_program_address( + &[ + "governance".as_bytes(), + proposal.as_ref(), + signatory.as_ref(), + &[bump], + ], + &crate::SPL_GOVERNANCE_ID, + ) + } + + pub fn find_pda(proposal: &Pubkey, signatory: &Pubkey) -> (solana_pubkey::Pubkey, u8) { + solana_pubkey::Pubkey::find_program_address( + &[ + "governance".as_bytes(), + proposal.as_ref(), + signatory.as_ref(), + ], + &crate::SPL_GOVERNANCE_ID, + ) + } + + #[inline(always)] + pub fn from_bytes(data: &[u8]) -> Result { + let mut data = data; + Self::deserialize(&mut data) + } +} + +impl<'a> TryFrom<&solana_account_info::AccountInfo<'a>> for SignatoryRecordV2 { + type Error = std::io::Error; + + fn try_from(account_info: &solana_account_info::AccountInfo<'a>) -> Result { + let mut data: &[u8] = &(*account_info.data).borrow(); + Self::deserialize(&mut data) + } +} + +#[cfg(feature = "fetch")] +pub fn fetch_signatory_record_v2( + rpc: &solana_client::rpc_client::RpcClient, + address: &solana_pubkey::Pubkey, +) -> Result, std::io::Error> { + let accounts = fetch_all_signatory_record_v2(rpc, &[*address])?; + Ok(accounts[0].clone()) +} + +#[cfg(feature = "fetch")] +pub fn fetch_all_signatory_record_v2( + rpc: &solana_client::rpc_client::RpcClient, + addresses: &[solana_pubkey::Pubkey], +) -> Result>, std::io::Error> { + let accounts = rpc + .get_multiple_accounts(addresses) + .map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, e.to_string()))?; + let mut decoded_accounts: Vec> = Vec::new(); + for i in 0..addresses.len() { + let address = addresses[i]; + let account = accounts[i].as_ref().ok_or(std::io::Error::new( + std::io::ErrorKind::Other, + format!("Account not found: {}", address), + ))?; + let data = SignatoryRecordV2::from_bytes(&account.data)?; + decoded_accounts.push(crate::shared::DecodedAccount { + address, + account: account.clone(), + data, + }); + } + Ok(decoded_accounts) +} + +#[cfg(feature = "fetch")] +pub fn fetch_maybe_signatory_record_v2( + rpc: &solana_client::rpc_client::RpcClient, + address: &solana_pubkey::Pubkey, +) -> Result, std::io::Error> { + let accounts = fetch_all_maybe_signatory_record_v2(rpc, &[*address])?; + Ok(accounts[0].clone()) +} + +#[cfg(feature = "fetch")] +pub fn fetch_all_maybe_signatory_record_v2( + rpc: &solana_client::rpc_client::RpcClient, + addresses: &[solana_pubkey::Pubkey], +) -> Result>, std::io::Error> { + let accounts = rpc + .get_multiple_accounts(addresses) + .map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, e.to_string()))?; + let mut decoded_accounts: Vec> = Vec::new(); + for i in 0..addresses.len() { + let address = addresses[i]; + if let Some(account) = accounts[i].as_ref() { + let data = SignatoryRecordV2::from_bytes(&account.data)?; + decoded_accounts.push(crate::shared::MaybeAccount::Exists( + crate::shared::DecodedAccount { + address, + account: account.clone(), + data, + }, + )); + } else { + decoded_accounts.push(crate::shared::MaybeAccount::NotFound(address)); + } + } + Ok(decoded_accounts) +} + +#[cfg(feature = "anchor")] +impl anchor_lang::AccountDeserialize for SignatoryRecordV2 { + fn try_deserialize_unchecked(buf: &mut &[u8]) -> anchor_lang::Result { + Ok(Self::deserialize(buf)?) + } +} + +#[cfg(feature = "anchor")] +impl anchor_lang::AccountSerialize for SignatoryRecordV2 {} + +#[cfg(feature = "anchor")] +impl anchor_lang::Owner for SignatoryRecordV2 { + fn owner() -> Pubkey { + crate::SPL_GOVERNANCE_ID + } +} + +#[cfg(feature = "anchor-idl-build")] +impl anchor_lang::IdlBuild for SignatoryRecordV2 {} + +#[cfg(feature = "anchor-idl-build")] +impl anchor_lang::Discriminator for SignatoryRecordV2 { + const DISCRIMINATOR: &[u8] = &[0; 8]; +} diff --git a/e2e/governance/src/generated/accounts/token_owner_record_v1.rs b/e2e/governance/src/generated/accounts/token_owner_record_v1.rs new file mode 100644 index 0000000..fd4abc8 --- /dev/null +++ b/e2e/governance/src/generated/accounts/token_owner_record_v1.rs @@ -0,0 +1,194 @@ +//! This code was AUTOGENERATED using the codama library. +//! Please DO NOT EDIT THIS FILE, instead use visitors +//! to add features, then rerun codama to update it. +//! +//! +//! + +use crate::generated::types::GovernanceAccountType; +use borsh::BorshDeserialize; +use borsh::BorshSerialize; +use solana_pubkey::Pubkey; + +#[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct TokenOwnerRecordV1 { + pub account_type: GovernanceAccountType, + #[cfg_attr( + feature = "serde", + serde(with = "serde_with::As::") + )] + pub realm: Pubkey, + #[cfg_attr( + feature = "serde", + serde(with = "serde_with::As::") + )] + pub governing_token_mint: Pubkey, + #[cfg_attr( + feature = "serde", + serde(with = "serde_with::As::") + )] + pub governing_token_owner: Pubkey, + pub governing_token_deposit_amount: u64, + pub unrelinquished_votes_count: u64, + pub outstanding_proposal_count: u8, + pub version: u8, + pub reserved: [u8; 6], + pub governance_delegate: Option, +} + +impl TokenOwnerRecordV1 { + /// Prefix values used to generate a PDA for this account. + /// + /// Values are positional and appear in the following order: + /// + /// 0. `TokenOwnerRecordV1::PREFIX` + /// 1. realm (`Pubkey`) + /// 2. governing_token_mint (`Pubkey`) + /// 3. governing_token_owner (`Pubkey`) + pub const PREFIX: &'static [u8] = "governance".as_bytes(); + + pub fn create_pda( + realm: Pubkey, + governing_token_mint: Pubkey, + governing_token_owner: Pubkey, + bump: u8, + ) -> Result { + solana_pubkey::Pubkey::create_program_address( + &[ + "governance".as_bytes(), + realm.as_ref(), + governing_token_mint.as_ref(), + governing_token_owner.as_ref(), + &[bump], + ], + &crate::SPL_GOVERNANCE_ID, + ) + } + + pub fn find_pda( + realm: &Pubkey, + governing_token_mint: &Pubkey, + governing_token_owner: &Pubkey, + ) -> (solana_pubkey::Pubkey, u8) { + solana_pubkey::Pubkey::find_program_address( + &[ + "governance".as_bytes(), + realm.as_ref(), + governing_token_mint.as_ref(), + governing_token_owner.as_ref(), + ], + &crate::SPL_GOVERNANCE_ID, + ) + } + + #[inline(always)] + pub fn from_bytes(data: &[u8]) -> Result { + let mut data = data; + Self::deserialize(&mut data) + } +} + +impl<'a> TryFrom<&solana_account_info::AccountInfo<'a>> for TokenOwnerRecordV1 { + type Error = std::io::Error; + + fn try_from(account_info: &solana_account_info::AccountInfo<'a>) -> Result { + let mut data: &[u8] = &(*account_info.data).borrow(); + Self::deserialize(&mut data) + } +} + +#[cfg(feature = "fetch")] +pub fn fetch_token_owner_record_v1( + rpc: &solana_client::rpc_client::RpcClient, + address: &solana_pubkey::Pubkey, +) -> Result, std::io::Error> { + let accounts = fetch_all_token_owner_record_v1(rpc, &[*address])?; + Ok(accounts[0].clone()) +} + +#[cfg(feature = "fetch")] +pub fn fetch_all_token_owner_record_v1( + rpc: &solana_client::rpc_client::RpcClient, + addresses: &[solana_pubkey::Pubkey], +) -> Result>, std::io::Error> { + let accounts = rpc + .get_multiple_accounts(addresses) + .map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, e.to_string()))?; + let mut decoded_accounts: Vec> = Vec::new(); + for i in 0..addresses.len() { + let address = addresses[i]; + let account = accounts[i].as_ref().ok_or(std::io::Error::new( + std::io::ErrorKind::Other, + format!("Account not found: {}", address), + ))?; + let data = TokenOwnerRecordV1::from_bytes(&account.data)?; + decoded_accounts.push(crate::shared::DecodedAccount { + address, + account: account.clone(), + data, + }); + } + Ok(decoded_accounts) +} + +#[cfg(feature = "fetch")] +pub fn fetch_maybe_token_owner_record_v1( + rpc: &solana_client::rpc_client::RpcClient, + address: &solana_pubkey::Pubkey, +) -> Result, std::io::Error> { + let accounts = fetch_all_maybe_token_owner_record_v1(rpc, &[*address])?; + Ok(accounts[0].clone()) +} + +#[cfg(feature = "fetch")] +pub fn fetch_all_maybe_token_owner_record_v1( + rpc: &solana_client::rpc_client::RpcClient, + addresses: &[solana_pubkey::Pubkey], +) -> Result>, std::io::Error> { + let accounts = rpc + .get_multiple_accounts(addresses) + .map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, e.to_string()))?; + let mut decoded_accounts: Vec> = Vec::new(); + for i in 0..addresses.len() { + let address = addresses[i]; + if let Some(account) = accounts[i].as_ref() { + let data = TokenOwnerRecordV1::from_bytes(&account.data)?; + decoded_accounts.push(crate::shared::MaybeAccount::Exists( + crate::shared::DecodedAccount { + address, + account: account.clone(), + data, + }, + )); + } else { + decoded_accounts.push(crate::shared::MaybeAccount::NotFound(address)); + } + } + Ok(decoded_accounts) +} + +#[cfg(feature = "anchor")] +impl anchor_lang::AccountDeserialize for TokenOwnerRecordV1 { + fn try_deserialize_unchecked(buf: &mut &[u8]) -> anchor_lang::Result { + Ok(Self::deserialize(buf)?) + } +} + +#[cfg(feature = "anchor")] +impl anchor_lang::AccountSerialize for TokenOwnerRecordV1 {} + +#[cfg(feature = "anchor")] +impl anchor_lang::Owner for TokenOwnerRecordV1 { + fn owner() -> Pubkey { + crate::SPL_GOVERNANCE_ID + } +} + +#[cfg(feature = "anchor-idl-build")] +impl anchor_lang::IdlBuild for TokenOwnerRecordV1 {} + +#[cfg(feature = "anchor-idl-build")] +impl anchor_lang::Discriminator for TokenOwnerRecordV1 { + const DISCRIMINATOR: &[u8] = &[0; 8]; +} diff --git a/e2e/governance/src/generated/accounts/token_owner_record_v2.rs b/e2e/governance/src/generated/accounts/token_owner_record_v2.rs new file mode 100644 index 0000000..319bc3c --- /dev/null +++ b/e2e/governance/src/generated/accounts/token_owner_record_v2.rs @@ -0,0 +1,196 @@ +//! This code was AUTOGENERATED using the codama library. +//! Please DO NOT EDIT THIS FILE, instead use visitors +//! to add features, then rerun codama to update it. +//! +//! +//! + +use crate::generated::types::GovernanceAccountType; +use borsh::BorshDeserialize; +use borsh::BorshSerialize; +use solana_pubkey::Pubkey; + +#[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct TokenOwnerRecordV2 { + pub account_type: GovernanceAccountType, + #[cfg_attr( + feature = "serde", + serde(with = "serde_with::As::") + )] + pub realm: Pubkey, + #[cfg_attr( + feature = "serde", + serde(with = "serde_with::As::") + )] + pub governing_token_mint: Pubkey, + #[cfg_attr( + feature = "serde", + serde(with = "serde_with::As::") + )] + pub governing_token_owner: Pubkey, + pub governing_token_deposit_amount: u64, + pub unrelinquished_votes_count: u64, + pub outstanding_proposal_count: u8, + pub version: u8, + pub reserved: [u8; 6], + pub governance_delegate: Option, + #[cfg_attr(feature = "serde", serde(with = "serde_big_array::BigArray"))] + pub reserved_v2: [u8; 128], +} + +impl TokenOwnerRecordV2 { + /// Prefix values used to generate a PDA for this account. + /// + /// Values are positional and appear in the following order: + /// + /// 0. `TokenOwnerRecordV2::PREFIX` + /// 1. realm (`Pubkey`) + /// 2. governing_token_mint (`Pubkey`) + /// 3. governing_token_owner (`Pubkey`) + pub const PREFIX: &'static [u8] = "governance".as_bytes(); + + pub fn create_pda( + realm: Pubkey, + governing_token_mint: Pubkey, + governing_token_owner: Pubkey, + bump: u8, + ) -> Result { + solana_pubkey::Pubkey::create_program_address( + &[ + "governance".as_bytes(), + realm.as_ref(), + governing_token_mint.as_ref(), + governing_token_owner.as_ref(), + &[bump], + ], + &crate::SPL_GOVERNANCE_ID, + ) + } + + pub fn find_pda( + realm: &Pubkey, + governing_token_mint: &Pubkey, + governing_token_owner: &Pubkey, + ) -> (solana_pubkey::Pubkey, u8) { + solana_pubkey::Pubkey::find_program_address( + &[ + "governance".as_bytes(), + realm.as_ref(), + governing_token_mint.as_ref(), + governing_token_owner.as_ref(), + ], + &crate::SPL_GOVERNANCE_ID, + ) + } + + #[inline(always)] + pub fn from_bytes(data: &[u8]) -> Result { + let mut data = data; + Self::deserialize(&mut data) + } +} + +impl<'a> TryFrom<&solana_account_info::AccountInfo<'a>> for TokenOwnerRecordV2 { + type Error = std::io::Error; + + fn try_from(account_info: &solana_account_info::AccountInfo<'a>) -> Result { + let mut data: &[u8] = &(*account_info.data).borrow(); + Self::deserialize(&mut data) + } +} + +#[cfg(feature = "fetch")] +pub fn fetch_token_owner_record_v2( + rpc: &solana_client::rpc_client::RpcClient, + address: &solana_pubkey::Pubkey, +) -> Result, std::io::Error> { + let accounts = fetch_all_token_owner_record_v2(rpc, &[*address])?; + Ok(accounts[0].clone()) +} + +#[cfg(feature = "fetch")] +pub fn fetch_all_token_owner_record_v2( + rpc: &solana_client::rpc_client::RpcClient, + addresses: &[solana_pubkey::Pubkey], +) -> Result>, std::io::Error> { + let accounts = rpc + .get_multiple_accounts(addresses) + .map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, e.to_string()))?; + let mut decoded_accounts: Vec> = Vec::new(); + for i in 0..addresses.len() { + let address = addresses[i]; + let account = accounts[i].as_ref().ok_or(std::io::Error::new( + std::io::ErrorKind::Other, + format!("Account not found: {}", address), + ))?; + let data = TokenOwnerRecordV2::from_bytes(&account.data)?; + decoded_accounts.push(crate::shared::DecodedAccount { + address, + account: account.clone(), + data, + }); + } + Ok(decoded_accounts) +} + +#[cfg(feature = "fetch")] +pub fn fetch_maybe_token_owner_record_v2( + rpc: &solana_client::rpc_client::RpcClient, + address: &solana_pubkey::Pubkey, +) -> Result, std::io::Error> { + let accounts = fetch_all_maybe_token_owner_record_v2(rpc, &[*address])?; + Ok(accounts[0].clone()) +} + +#[cfg(feature = "fetch")] +pub fn fetch_all_maybe_token_owner_record_v2( + rpc: &solana_client::rpc_client::RpcClient, + addresses: &[solana_pubkey::Pubkey], +) -> Result>, std::io::Error> { + let accounts = rpc + .get_multiple_accounts(addresses) + .map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, e.to_string()))?; + let mut decoded_accounts: Vec> = Vec::new(); + for i in 0..addresses.len() { + let address = addresses[i]; + if let Some(account) = accounts[i].as_ref() { + let data = TokenOwnerRecordV2::from_bytes(&account.data)?; + decoded_accounts.push(crate::shared::MaybeAccount::Exists( + crate::shared::DecodedAccount { + address, + account: account.clone(), + data, + }, + )); + } else { + decoded_accounts.push(crate::shared::MaybeAccount::NotFound(address)); + } + } + Ok(decoded_accounts) +} + +#[cfg(feature = "anchor")] +impl anchor_lang::AccountDeserialize for TokenOwnerRecordV2 { + fn try_deserialize_unchecked(buf: &mut &[u8]) -> anchor_lang::Result { + Ok(Self::deserialize(buf)?) + } +} + +#[cfg(feature = "anchor")] +impl anchor_lang::AccountSerialize for TokenOwnerRecordV2 {} + +#[cfg(feature = "anchor")] +impl anchor_lang::Owner for TokenOwnerRecordV2 { + fn owner() -> Pubkey { + crate::SPL_GOVERNANCE_ID + } +} + +#[cfg(feature = "anchor-idl-build")] +impl anchor_lang::IdlBuild for TokenOwnerRecordV2 {} + +#[cfg(feature = "anchor-idl-build")] +impl anchor_lang::Discriminator for TokenOwnerRecordV2 { + const DISCRIMINATOR: &[u8] = &[0; 8]; +} diff --git a/e2e/governance/src/generated/accounts/vote_record_v1.rs b/e2e/governance/src/generated/accounts/vote_record_v1.rs new file mode 100644 index 0000000..477d07b --- /dev/null +++ b/e2e/governance/src/generated/accounts/vote_record_v1.rs @@ -0,0 +1,178 @@ +//! This code was AUTOGENERATED using the codama library. +//! Please DO NOT EDIT THIS FILE, instead use visitors +//! to add features, then rerun codama to update it. +//! +//! +//! + +use crate::generated::types::GovernanceAccountType; +use crate::generated::types::VoteWeightV1; +use borsh::BorshDeserialize; +use borsh::BorshSerialize; +use solana_pubkey::Pubkey; + +#[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct VoteRecordV1 { + pub account_type: GovernanceAccountType, + #[cfg_attr( + feature = "serde", + serde(with = "serde_with::As::") + )] + pub proposal: Pubkey, + #[cfg_attr( + feature = "serde", + serde(with = "serde_with::As::") + )] + pub governing_token_owner: Pubkey, + pub is_relinquished: bool, + pub vote_weight: VoteWeightV1, +} + +impl VoteRecordV1 { + /// Prefix values used to generate a PDA for this account. + /// + /// Values are positional and appear in the following order: + /// + /// 0. `VoteRecordV1::PREFIX` + /// 1. proposal (`Pubkey`) + /// 2. token_owner_record (`Pubkey`) + pub const PREFIX: &'static [u8] = "governance".as_bytes(); + + pub fn create_pda( + proposal: Pubkey, + token_owner_record: Pubkey, + bump: u8, + ) -> Result { + solana_pubkey::Pubkey::create_program_address( + &[ + "governance".as_bytes(), + proposal.as_ref(), + token_owner_record.as_ref(), + &[bump], + ], + &crate::SPL_GOVERNANCE_ID, + ) + } + + pub fn find_pda(proposal: &Pubkey, token_owner_record: &Pubkey) -> (solana_pubkey::Pubkey, u8) { + solana_pubkey::Pubkey::find_program_address( + &[ + "governance".as_bytes(), + proposal.as_ref(), + token_owner_record.as_ref(), + ], + &crate::SPL_GOVERNANCE_ID, + ) + } + + #[inline(always)] + pub fn from_bytes(data: &[u8]) -> Result { + let mut data = data; + Self::deserialize(&mut data) + } +} + +impl<'a> TryFrom<&solana_account_info::AccountInfo<'a>> for VoteRecordV1 { + type Error = std::io::Error; + + fn try_from(account_info: &solana_account_info::AccountInfo<'a>) -> Result { + let mut data: &[u8] = &(*account_info.data).borrow(); + Self::deserialize(&mut data) + } +} + +#[cfg(feature = "fetch")] +pub fn fetch_vote_record_v1( + rpc: &solana_client::rpc_client::RpcClient, + address: &solana_pubkey::Pubkey, +) -> Result, std::io::Error> { + let accounts = fetch_all_vote_record_v1(rpc, &[*address])?; + Ok(accounts[0].clone()) +} + +#[cfg(feature = "fetch")] +pub fn fetch_all_vote_record_v1( + rpc: &solana_client::rpc_client::RpcClient, + addresses: &[solana_pubkey::Pubkey], +) -> Result>, std::io::Error> { + let accounts = rpc + .get_multiple_accounts(addresses) + .map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, e.to_string()))?; + let mut decoded_accounts: Vec> = Vec::new(); + for i in 0..addresses.len() { + let address = addresses[i]; + let account = accounts[i].as_ref().ok_or(std::io::Error::new( + std::io::ErrorKind::Other, + format!("Account not found: {}", address), + ))?; + let data = VoteRecordV1::from_bytes(&account.data)?; + decoded_accounts.push(crate::shared::DecodedAccount { + address, + account: account.clone(), + data, + }); + } + Ok(decoded_accounts) +} + +#[cfg(feature = "fetch")] +pub fn fetch_maybe_vote_record_v1( + rpc: &solana_client::rpc_client::RpcClient, + address: &solana_pubkey::Pubkey, +) -> Result, std::io::Error> { + let accounts = fetch_all_maybe_vote_record_v1(rpc, &[*address])?; + Ok(accounts[0].clone()) +} + +#[cfg(feature = "fetch")] +pub fn fetch_all_maybe_vote_record_v1( + rpc: &solana_client::rpc_client::RpcClient, + addresses: &[solana_pubkey::Pubkey], +) -> Result>, std::io::Error> { + let accounts = rpc + .get_multiple_accounts(addresses) + .map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, e.to_string()))?; + let mut decoded_accounts: Vec> = Vec::new(); + for i in 0..addresses.len() { + let address = addresses[i]; + if let Some(account) = accounts[i].as_ref() { + let data = VoteRecordV1::from_bytes(&account.data)?; + decoded_accounts.push(crate::shared::MaybeAccount::Exists( + crate::shared::DecodedAccount { + address, + account: account.clone(), + data, + }, + )); + } else { + decoded_accounts.push(crate::shared::MaybeAccount::NotFound(address)); + } + } + Ok(decoded_accounts) +} + +#[cfg(feature = "anchor")] +impl anchor_lang::AccountDeserialize for VoteRecordV1 { + fn try_deserialize_unchecked(buf: &mut &[u8]) -> anchor_lang::Result { + Ok(Self::deserialize(buf)?) + } +} + +#[cfg(feature = "anchor")] +impl anchor_lang::AccountSerialize for VoteRecordV1 {} + +#[cfg(feature = "anchor")] +impl anchor_lang::Owner for VoteRecordV1 { + fn owner() -> Pubkey { + crate::SPL_GOVERNANCE_ID + } +} + +#[cfg(feature = "anchor-idl-build")] +impl anchor_lang::IdlBuild for VoteRecordV1 {} + +#[cfg(feature = "anchor-idl-build")] +impl anchor_lang::Discriminator for VoteRecordV1 { + const DISCRIMINATOR: &[u8] = &[0; 8]; +} diff --git a/e2e/governance/src/generated/accounts/vote_record_v2.rs b/e2e/governance/src/generated/accounts/vote_record_v2.rs new file mode 100644 index 0000000..de784cb --- /dev/null +++ b/e2e/governance/src/generated/accounts/vote_record_v2.rs @@ -0,0 +1,180 @@ +//! This code was AUTOGENERATED using the codama library. +//! Please DO NOT EDIT THIS FILE, instead use visitors +//! to add features, then rerun codama to update it. +//! +//! +//! + +use crate::generated::types::GovernanceAccountType; +use crate::generated::types::Vote; +use borsh::BorshDeserialize; +use borsh::BorshSerialize; +use solana_pubkey::Pubkey; + +#[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct VoteRecordV2 { + pub account_type: GovernanceAccountType, + #[cfg_attr( + feature = "serde", + serde(with = "serde_with::As::") + )] + pub proposal: Pubkey, + #[cfg_attr( + feature = "serde", + serde(with = "serde_with::As::") + )] + pub governing_token_owner: Pubkey, + pub is_relinquished: bool, + pub voter_weight: u64, + pub vote: Vote, + pub reserved_v2: [u8; 8], +} + +impl VoteRecordV2 { + /// Prefix values used to generate a PDA for this account. + /// + /// Values are positional and appear in the following order: + /// + /// 0. `VoteRecordV2::PREFIX` + /// 1. proposal (`Pubkey`) + /// 2. token_owner_record (`Pubkey`) + pub const PREFIX: &'static [u8] = "governance".as_bytes(); + + pub fn create_pda( + proposal: Pubkey, + token_owner_record: Pubkey, + bump: u8, + ) -> Result { + solana_pubkey::Pubkey::create_program_address( + &[ + "governance".as_bytes(), + proposal.as_ref(), + token_owner_record.as_ref(), + &[bump], + ], + &crate::SPL_GOVERNANCE_ID, + ) + } + + pub fn find_pda(proposal: &Pubkey, token_owner_record: &Pubkey) -> (solana_pubkey::Pubkey, u8) { + solana_pubkey::Pubkey::find_program_address( + &[ + "governance".as_bytes(), + proposal.as_ref(), + token_owner_record.as_ref(), + ], + &crate::SPL_GOVERNANCE_ID, + ) + } + + #[inline(always)] + pub fn from_bytes(data: &[u8]) -> Result { + let mut data = data; + Self::deserialize(&mut data) + } +} + +impl<'a> TryFrom<&solana_account_info::AccountInfo<'a>> for VoteRecordV2 { + type Error = std::io::Error; + + fn try_from(account_info: &solana_account_info::AccountInfo<'a>) -> Result { + let mut data: &[u8] = &(*account_info.data).borrow(); + Self::deserialize(&mut data) + } +} + +#[cfg(feature = "fetch")] +pub fn fetch_vote_record_v2( + rpc: &solana_client::rpc_client::RpcClient, + address: &solana_pubkey::Pubkey, +) -> Result, std::io::Error> { + let accounts = fetch_all_vote_record_v2(rpc, &[*address])?; + Ok(accounts[0].clone()) +} + +#[cfg(feature = "fetch")] +pub fn fetch_all_vote_record_v2( + rpc: &solana_client::rpc_client::RpcClient, + addresses: &[solana_pubkey::Pubkey], +) -> Result>, std::io::Error> { + let accounts = rpc + .get_multiple_accounts(addresses) + .map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, e.to_string()))?; + let mut decoded_accounts: Vec> = Vec::new(); + for i in 0..addresses.len() { + let address = addresses[i]; + let account = accounts[i].as_ref().ok_or(std::io::Error::new( + std::io::ErrorKind::Other, + format!("Account not found: {}", address), + ))?; + let data = VoteRecordV2::from_bytes(&account.data)?; + decoded_accounts.push(crate::shared::DecodedAccount { + address, + account: account.clone(), + data, + }); + } + Ok(decoded_accounts) +} + +#[cfg(feature = "fetch")] +pub fn fetch_maybe_vote_record_v2( + rpc: &solana_client::rpc_client::RpcClient, + address: &solana_pubkey::Pubkey, +) -> Result, std::io::Error> { + let accounts = fetch_all_maybe_vote_record_v2(rpc, &[*address])?; + Ok(accounts[0].clone()) +} + +#[cfg(feature = "fetch")] +pub fn fetch_all_maybe_vote_record_v2( + rpc: &solana_client::rpc_client::RpcClient, + addresses: &[solana_pubkey::Pubkey], +) -> Result>, std::io::Error> { + let accounts = rpc + .get_multiple_accounts(addresses) + .map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, e.to_string()))?; + let mut decoded_accounts: Vec> = Vec::new(); + for i in 0..addresses.len() { + let address = addresses[i]; + if let Some(account) = accounts[i].as_ref() { + let data = VoteRecordV2::from_bytes(&account.data)?; + decoded_accounts.push(crate::shared::MaybeAccount::Exists( + crate::shared::DecodedAccount { + address, + account: account.clone(), + data, + }, + )); + } else { + decoded_accounts.push(crate::shared::MaybeAccount::NotFound(address)); + } + } + Ok(decoded_accounts) +} + +#[cfg(feature = "anchor")] +impl anchor_lang::AccountDeserialize for VoteRecordV2 { + fn try_deserialize_unchecked(buf: &mut &[u8]) -> anchor_lang::Result { + Ok(Self::deserialize(buf)?) + } +} + +#[cfg(feature = "anchor")] +impl anchor_lang::AccountSerialize for VoteRecordV2 {} + +#[cfg(feature = "anchor")] +impl anchor_lang::Owner for VoteRecordV2 { + fn owner() -> Pubkey { + crate::SPL_GOVERNANCE_ID + } +} + +#[cfg(feature = "anchor-idl-build")] +impl anchor_lang::IdlBuild for VoteRecordV2 {} + +#[cfg(feature = "anchor-idl-build")] +impl anchor_lang::Discriminator for VoteRecordV2 { + const DISCRIMINATOR: &[u8] = &[0; 8]; +} diff --git a/e2e/governance/src/generated/errors/mod.rs b/e2e/governance/src/generated/errors/mod.rs new file mode 100644 index 0000000..b84bbdc --- /dev/null +++ b/e2e/governance/src/generated/errors/mod.rs @@ -0,0 +1,10 @@ +//! This code was AUTOGENERATED using the codama library. +//! Please DO NOT EDIT THIS FILE, instead use visitors +//! to add features, then rerun codama to update it. +//! +//! +//! + +pub(crate) mod spl_governance; + +pub use self::spl_governance::SplGovernanceError; diff --git a/e2e/governance/src/generated/errors/spl_governance.rs b/e2e/governance/src/generated/errors/spl_governance.rs new file mode 100644 index 0000000..6e19600 --- /dev/null +++ b/e2e/governance/src/generated/errors/spl_governance.rs @@ -0,0 +1,394 @@ +//! This code was AUTOGENERATED using the codama library. +//! Please DO NOT EDIT THIS FILE, instead use visitors +//! to add features, then rerun codama to update it. +//! +//! +//! + +use num_derive::FromPrimitive; +use thiserror::Error; + +#[derive(Clone, Debug, Eq, Error, FromPrimitive, PartialEq)] +pub enum SplGovernanceError { + /// 500 - Invalid instruction passed to program + #[error("Invalid instruction passed to program")] + InvalidInstruction = 0x1F4, + /// 501 - Realm with the given name and governing mints already exists + #[error("Realm with the given name and governing mints already exists")] + RealmAlreadyExists = 0x1F5, + /// 502 - Invalid realm + #[error("Invalid realm")] + InvalidRealm = 0x1F6, + /// 503 - Invalid Governing Token Mint + #[error("Invalid Governing Token Mint")] + InvalidGoverningTokenMint = 0x1F7, + /// 504 - Governing Token Owner must sign transaction + #[error("Governing Token Owner must sign transaction")] + GoverningTokenOwnerMustSign = 0x1F8, + /// 505 - Governing Token Owner or Delegate must sign transaction + #[error("Governing Token Owner or Delegate must sign transaction")] + GoverningTokenOwnerOrDelegateMustSign = 0x1F9, + /// 506 - All votes must be relinquished to withdraw governing tokens + #[error("All votes must be relinquished to withdraw governing tokens")] + AllVotesMustBeRelinquishedToWithdrawGoverningTokens = 0x1FA, + /// 507 - Invalid Token Owner Record account address + #[error("Invalid Token Owner Record account address")] + InvalidTokenOwnerRecordAccountAddress = 0x1FB, + /// 508 - Invalid GoverningMint for TokenOwnerRecord + #[error("Invalid GoverningMint for TokenOwnerRecord")] + InvalidGoverningMintForTokenOwnerRecord = 0x1FC, + /// 509 - Invalid Realm for TokenOwnerRecord + #[error("Invalid Realm for TokenOwnerRecord")] + InvalidRealmForTokenOwnerRecord = 0x1FD, + /// 510 - Invalid Proposal for ProposalTransaction, + #[error("Invalid Proposal for ProposalTransaction,")] + InvalidProposalForProposalTransaction = 0x1FE, + /// 511 - Invalid Signatory account address + #[error("Invalid Signatory account address")] + InvalidSignatoryAddress = 0x1FF, + /// 512 - Signatory already signed off + #[error("Signatory already signed off")] + SignatoryAlreadySignedOff = 0x200, + /// 513 - Signatory must sign + #[error("Signatory must sign")] + SignatoryMustSign = 0x201, + /// 514 - Invalid Proposal Owner + #[error("Invalid Proposal Owner")] + InvalidProposalOwnerAccount = 0x202, + /// 515 - Invalid Proposal for VoterRecord + #[error("Invalid Proposal for VoterRecord")] + InvalidProposalForVoterRecord = 0x203, + /// 516 - Invalid GoverningTokenOwner for VoteRecord + #[error("Invalid GoverningTokenOwner for VoteRecord")] + InvalidGoverningTokenOwnerForVoteRecord = 0x204, + /// 517 - Invalid Governance config: Vote threshold percentage out of range + #[error("Invalid Governance config: Vote threshold percentage out of range")] + InvalidVoteThresholdPercentage = 0x205, + /// 518 - Proposal for the given Governance, Governing Token Mint and index already exists + #[error("Proposal for the given Governance, Governing Token Mint and index already exists")] + ProposalAlreadyExists = 0x206, + /// 519 - Token Owner already voted on the Proposal + #[error("Token Owner already voted on the Proposal")] + VoteAlreadyExists = 0x207, + /// 520 - Owner doesn't have enough governing tokens to create Proposal + #[error("Owner doesn't have enough governing tokens to create Proposal")] + NotEnoughTokensToCreateProposal = 0x208, + /// 521 - Invalid State: Can't edit Signatories + #[error("Invalid State: Can't edit Signatories")] + InvalidStateCannotEditSignatories = 0x209, + /// 522 - Invalid Proposal state + #[error("Invalid Proposal state")] + InvalidProposalState = 0x20A, + /// 523 - Invalid State: Can't edit transactions + #[error("Invalid State: Can't edit transactions")] + InvalidStateCannotEditTransactions = 0x20B, + /// 524 - Invalid State: Can't execute transaction + #[error("Invalid State: Can't execute transaction")] + InvalidStateCannotExecuteTransaction = 0x20C, + /// 525 - Can't execute transaction within its hold up time + #[error("Can't execute transaction within its hold up time")] + CannotExecuteTransactionWithinHoldUpTime = 0x20D, + /// 526 - Transaction already executed + #[error("Transaction already executed")] + TransactionAlreadyExecuted = 0x20E, + /// 527 - Invalid Transaction index + #[error("Invalid Transaction index")] + InvalidTransactionIndex = 0x20F, + /// 528 - Transaction hold up time is below the min specified by Governance + #[error("Transaction hold up time is below the min specified by Governance")] + TransactionHoldUpTimeBelowRequiredMin = 0x210, + /// 529 - Transaction at the given index for the Proposal already exists + #[error("Transaction at the given index for the Proposal already exists")] + TransactionAlreadyExists = 0x211, + /// 530 - Invalid State: Can't sign off + #[error("Invalid State: Can't sign off")] + InvalidStateCannotSignOff = 0x212, + /// 531 - Invalid State: Can't vote + #[error("Invalid State: Can't vote")] + InvalidStateCannotVote = 0x213, + /// 532 - Invalid State: Can't finalize vote + #[error("Invalid State: Can't finalize vote")] + InvalidStateCannotFinalize = 0x214, + /// 533 - Invalid State: Can't cancel Proposal + #[error("Invalid State: Can't cancel Proposal")] + InvalidStateCannotCancelProposal = 0x215, + /// 534 - Vote already relinquished + #[error("Vote already relinquished")] + VoteAlreadyRelinquished = 0x216, + /// 535 - Can't finalize vote. Voting still in progress + #[error("Can't finalize vote. Voting still in progress")] + CannotFinalizeVotingInProgress = 0x217, + /// 536 - Proposal voting time expired + #[error("Proposal voting time expired")] + ProposalVotingTimeExpired = 0x218, + /// 537 - Invalid Signatory Mint + #[error("Invalid Signatory Mint")] + InvalidSignatoryMint = 0x219, + /// 538 - Proposal does not belong to the given Governance + #[error("Proposal does not belong to the given Governance")] + InvalidGovernanceForProposal = 0x21A, + /// 539 - Proposal does not belong to given Governing Mint + #[error("Proposal does not belong to given Governing Mint")] + InvalidGoverningMintForProposal = 0x21B, + /// 540 - Current mint authority must sign transaction + #[error("Current mint authority must sign transaction")] + MintAuthorityMustSign = 0x21C, + /// 541 - Invalid mint authority + #[error("Invalid mint authority")] + InvalidMintAuthority = 0x21D, + /// 542 - Mint has no authority + #[error("Mint has no authority")] + MintHasNoAuthority = 0x21E, + /// 543 - Invalid Token account owner + #[error("Invalid Token account owner")] + SplTokenAccountWithInvalidOwner = 0x21F, + /// 544 - Invalid Mint account owner + #[error("Invalid Mint account owner")] + SplTokenMintWithInvalidOwner = 0x220, + /// 545 - Token Account is not initialized + #[error("Token Account is not initialized")] + SplTokenAccountNotInitialized = 0x221, + /// 546 - Token Account doesn't exist + #[error("Token Account doesn't exist")] + SplTokenAccountDoesNotExist = 0x222, + /// 547 - Token account data is invalid + #[error("Token account data is invalid")] + SplTokenInvalidTokenAccountData = 0x223, + /// 548 - Token mint account data is invalid + #[error("Token mint account data is invalid")] + SplTokenInvalidMintAccountData = 0x224, + /// 549 - Token Mint account is not initialized + #[error("Token Mint account is not initialized")] + SplTokenMintNotInitialized = 0x225, + /// 550 - Token Mint account doesn't exist + #[error("Token Mint account doesn't exist")] + SplTokenMintDoesNotExist = 0x226, + /// 551 - Invalid ProgramData account address + #[error("Invalid ProgramData account address")] + InvalidProgramDataAccountAddress = 0x227, + /// 552 - Invalid ProgramData account Data + #[error("Invalid ProgramData account Data")] + InvalidProgramDataAccountData = 0x228, + /// 553 - Provided upgrade authority doesn't match current program upgrade authority + #[error("Provided upgrade authority doesn't match current program upgrade authority")] + InvalidUpgradeAuthority = 0x229, + /// 554 - Current program upgrade authority must sign transaction + #[error("Current program upgrade authority must sign transaction")] + UpgradeAuthorityMustSign = 0x22A, + /// 555 - Given program is not upgradable + #[error("Given program is not upgradable")] + ProgramNotUpgradable = 0x22B, + /// 556 - Invalid token owner + #[error("Invalid token owner")] + InvalidTokenOwner = 0x22C, + /// 557 - Current token owner must sign transaction + #[error("Current token owner must sign transaction")] + TokenOwnerMustSign = 0x22D, + /// 558 - Given VoteThresholdType is not supported + #[error("Given VoteThresholdType is not supported")] + VoteThresholdTypeNotSupported = 0x22E, + /// 559 - Given VoteWeightSource is not supported + #[error("Given VoteWeightSource is not supported")] + VoteWeightSourceNotSupported = 0x22F, + /// 560 - Legacy1 + #[error("Legacy1")] + Legacy1 = 0x230, + /// 561 - Governance PDA must sign + #[error("Governance PDA must sign")] + GovernancePdaMustSign = 0x231, + /// 562 - Transaction already flagged with error + #[error("Transaction already flagged with error")] + TransactionAlreadyFlaggedWithError = 0x232, + /// 563 - Invalid Realm for Governance + #[error("Invalid Realm for Governance")] + InvalidRealmForGovernance = 0x233, + /// 564 - Invalid Authority for Realm + #[error("Invalid Authority for Realm")] + InvalidAuthorityForRealm = 0x234, + /// 565 - Realm has no authority + #[error("Realm has no authority")] + RealmHasNoAuthority = 0x235, + /// 566 - Realm authority must sign + #[error("Realm authority must sign")] + RealmAuthorityMustSign = 0x236, + /// 567 - Invalid governing token holding account + #[error("Invalid governing token holding account")] + InvalidGoverningTokenHoldingAccount = 0x237, + /// 568 - Realm council mint change is not supported + #[error("Realm council mint change is not supported")] + RealmCouncilMintChangeIsNotSupported = 0x238, + /// 569 - Invalid max voter weight absolute value + #[error("Invalid max voter weight absolute value")] + InvalidMaxVoterWeightAbsoluteValue = 0x239, + /// 570 - Invalid max voter weight supply fraction + #[error("Invalid max voter weight supply fraction")] + InvalidMaxVoterWeightSupplyFraction = 0x23A, + /// 571 - Owner doesn't have enough governing tokens to create Governance + #[error("Owner doesn't have enough governing tokens to create Governance")] + NotEnoughTokensToCreateGovernance = 0x23B, + /// 572 - Too many outstanding proposals + #[error("Too many outstanding proposals")] + TooManyOutstandingProposals = 0x23C, + /// 573 - All proposals must be finalized to withdraw governing tokens + #[error("All proposals must be finalized to withdraw governing tokens")] + AllProposalsMustBeFinalisedToWithdrawGoverningTokens = 0x23D, + /// 574 - Invalid VoterWeightRecord for Realm + #[error("Invalid VoterWeightRecord for Realm")] + InvalidVoterWeightRecordForRealm = 0x23E, + /// 575 - Invalid VoterWeightRecord for GoverningTokenMint + #[error("Invalid VoterWeightRecord for GoverningTokenMint")] + InvalidVoterWeightRecordForGoverningTokenMint = 0x23F, + /// 576 - Invalid VoterWeightRecord for TokenOwner + #[error("Invalid VoterWeightRecord for TokenOwner")] + InvalidVoterWeightRecordForTokenOwner = 0x240, + /// 577 - VoterWeightRecord expired + #[error("VoterWeightRecord expired")] + VoterWeightRecordExpired = 0x241, + /// 578 - Invalid RealmConfig for Realm + #[error("Invalid RealmConfig for Realm")] + InvalidRealmConfigForRealm = 0x242, + /// 579 - TokenOwnerRecord already exists + #[error("TokenOwnerRecord already exists")] + TokenOwnerRecordAlreadyExists = 0x243, + /// 580 - Governing token deposits not allowed + #[error("Governing token deposits not allowed")] + GoverningTokenDepositsNotAllowed = 0x244, + /// 581 - Invalid vote choice weight percentage + #[error("Invalid vote choice weight percentage")] + InvalidVoteChoiceWeightPercentage = 0x245, + /// 582 - Vote type not supported + #[error("Vote type not supported")] + VoteTypeNotSupported = 0x246, + /// 583 - Invalid proposal options + #[error("Invalid proposal options")] + InvalidProposalOptions = 0x247, + /// 584 - Proposal is not not executable + #[error("Proposal is not not executable")] + ProposalIsNotExecutable = 0x248, + /// 585 - Deny vote is not allowed + #[error("Deny vote is not allowed")] + DenyVoteIsNotAllowed = 0x249, + /// 586 - Cannot execute defeated option + #[error("Cannot execute defeated option")] + CannotExecuteDefeatedOption = 0x24A, + /// 587 - VoterWeightRecord invalid action + #[error("VoterWeightRecord invalid action")] + VoterWeightRecordInvalidAction = 0x24B, + /// 588 - VoterWeightRecord invalid action target + #[error("VoterWeightRecord invalid action target")] + VoterWeightRecordInvalidActionTarget = 0x24C, + /// 589 - Invalid MaxVoterWeightRecord for Realm + #[error("Invalid MaxVoterWeightRecord for Realm")] + InvalidMaxVoterWeightRecordForRealm = 0x24D, + /// 590 - Invalid MaxVoterWeightRecord for GoverningTokenMint + #[error("Invalid MaxVoterWeightRecord for GoverningTokenMint")] + InvalidMaxVoterWeightRecordForGoverningTokenMint = 0x24E, + /// 591 - MaxVoterWeightRecord expired + #[error("MaxVoterWeightRecord expired")] + MaxVoterWeightRecordExpired = 0x24F, + /// 592 - Not supported VoteType + #[error("Not supported VoteType")] + NotSupportedVoteType = 0x250, + /// 593 - RealmConfig change not allowed + #[error("RealmConfig change not allowed")] + RealmConfigChangeNotAllowed = 0x251, + /// 594 - GovernanceConfig change not allowed + #[error("GovernanceConfig change not allowed")] + GovernanceConfigChangeNotAllowed = 0x252, + /// 595 - At least one VoteThreshold is required + #[error("At least one VoteThreshold is required")] + AtLeastOneVoteThresholdRequired = 0x253, + /// 596 - Reserved buffer must be empty + #[error("Reserved buffer must be empty")] + ReservedBufferMustBeEmpty = 0x254, + /// 597 - Cannot Relinquish in Finalizing state + #[error("Cannot Relinquish in Finalizing state")] + CannotRelinquishInFinalizingState = 0x255, + /// 598 - Invalid RealmConfig account address + #[error("Invalid RealmConfig account address")] + InvalidRealmConfigAddress = 0x256, + /// 599 - Cannot deposit dormant tokens + #[error("Cannot deposit dormant tokens")] + CannotDepositDormantTokens = 0x257, + /// 600 - Cannot withdraw membership tokens + #[error("Cannot withdraw membership tokens")] + CannotWithdrawMembershipTokens = 0x258, + /// 601 - Cannot revoke GoverningTokens + #[error("Cannot revoke GoverningTokens")] + CannotRevokeGoverningTokens = 0x259, + /// 602 - Invalid Revoke amount + #[error("Invalid Revoke amount")] + InvalidRevokeAmount = 0x25A, + /// 603 - Invalid GoverningToken source + #[error("Invalid GoverningToken source")] + InvalidGoverningTokenSource = 0x25B, + /// 604 - Cannot change community TokenType to Membership + #[error("Cannot change community TokenType to Membership")] + CannotChangeCommunityTokenTypeToMembership = 0x25C, + /// 605 - Voter weight threshold disabled + #[error("Voter weight threshold disabled")] + VoterWeightThresholdDisabled = 0x25D, + /// 606 - Vote not allowed in cool off time + #[error("Vote not allowed in cool off time")] + VoteNotAllowedInCoolOffTime = 0x25E, + /// 607 - Cannot refund ProposalDeposit + #[error("Cannot refund ProposalDeposit")] + CannotRefundProposalDeposit = 0x25F, + /// 608 - Invalid Proposal for ProposalDeposit + #[error("Invalid Proposal for ProposalDeposit")] + InvalidProposalForProposalDeposit = 0x260, + /// 609 - Invalid deposit_exempt_proposal_count + #[error("Invalid deposit_exempt_proposal_count")] + InvalidDepositExemptProposalCount = 0x261, + /// 610 - GoverningTokenMint not allowed to vote + #[error("GoverningTokenMint not allowed to vote")] + GoverningTokenMintNotAllowedToVote = 0x262, + /// 611 - Invalid deposit Payer for ProposalDeposit + #[error("Invalid deposit Payer for ProposalDeposit")] + InvalidDepositPayerForProposalDeposit = 0x263, + /// 612 - Invalid State: Proposal is not in final state + #[error("Invalid State: Proposal is not in final state")] + InvalidStateNotFinal = 0x264, + /// 613 - Invalid state for proposal state transition to Completed + #[error("Invalid state for proposal state transition to Completed")] + InvalidStateToCompleteProposal = 0x265, + /// 614 - Invalid number of vote choices + #[error("Invalid number of vote choices")] + InvalidNumberOfVoteChoices = 0x266, + /// 615 - Ranked vote is not supported + #[error("Ranked vote is not supported")] + RankedVoteIsNotSupported = 0x267, + /// 616 - Choice weight must be 100% + #[error("Choice weight must be 100%")] + ChoiceWeightMustBe100Percent = 0x268, + /// 617 - Single choice only is allowed + #[error("Single choice only is allowed")] + SingleChoiceOnlyIsAllowed = 0x269, + /// 618 - At least single choice is required + #[error("At least single choice is required")] + AtLeastSingleChoiceIsRequired = 0x26A, + /// 619 - Total vote weight must be 100% + #[error("Total vote weight must be 100%")] + TotalVoteWeightMustBe100Percent = 0x26B, + /// 620 - Invalid multi choice proposal parameters + #[error("Invalid multi choice proposal parameters")] + InvalidMultiChoiceProposalParameters = 0x26C, + /// 621 - Invalid Governance for RequiredSignatory + #[error("Invalid Governance for RequiredSignatory")] + InvalidGovernanceForRequiredSignatory = 0x26D, + /// 622 - Signatory Record has already been created + #[error("Signatory Record has already been created")] + SignatoryRecordAlreadyExists = 0x26E, + /// 623 - Instruction has been removed + #[error("Instruction has been removed")] + InstructionDeprecated = 0x26F, + /// 624 - Proposal is missing required signatories + #[error("Proposal is missing required signatories")] + MissingRequiredSignatories = 0x270, +} + +impl From for solana_program_error::ProgramError { + fn from(e: SplGovernanceError) -> Self { + solana_program_error::ProgramError::Custom(e as u32) + } +} diff --git a/e2e/governance/src/generated/instructions/add_required_signatory.rs b/e2e/governance/src/generated/instructions/add_required_signatory.rs new file mode 100644 index 0000000..0e78413 --- /dev/null +++ b/e2e/governance/src/generated/instructions/add_required_signatory.rs @@ -0,0 +1,454 @@ +//! This code was AUTOGENERATED using the codama library. +//! Please DO NOT EDIT THIS FILE, instead use visitors +//! to add features, then rerun codama to update it. +//! +//! +//! + +use borsh::BorshDeserialize; +use borsh::BorshSerialize; +use solana_pubkey::Pubkey; + +pub const ADD_REQUIRED_SIGNATORY_DISCRIMINATOR: u8 = 29; + +/// Accounts. +#[derive(Debug)] +pub struct AddRequiredSignatory { + /// The Governance account the config is for + pub governance_account: solana_pubkey::Pubkey, + + pub required_signatory_account: solana_pubkey::Pubkey, + + pub payer: solana_pubkey::Pubkey, + + pub system_program: solana_pubkey::Pubkey, +} + +impl AddRequiredSignatory { + pub fn instruction( + &self, + args: AddRequiredSignatoryInstructionArgs, + ) -> solana_instruction::Instruction { + self.instruction_with_remaining_accounts(args, &[]) + } + #[allow(clippy::arithmetic_side_effects)] + #[allow(clippy::vec_init_then_push)] + pub fn instruction_with_remaining_accounts( + &self, + args: AddRequiredSignatoryInstructionArgs, + remaining_accounts: &[solana_instruction::AccountMeta], + ) -> solana_instruction::Instruction { + let mut accounts = Vec::with_capacity(4 + remaining_accounts.len()); + accounts.push(solana_instruction::AccountMeta::new( + self.governance_account, + true, + )); + accounts.push(solana_instruction::AccountMeta::new( + self.required_signatory_account, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.payer, true, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.system_program, + false, + )); + accounts.extend_from_slice(remaining_accounts); + let mut data = AddRequiredSignatoryInstructionData::new() + .try_to_vec() + .unwrap(); + let mut args = args.try_to_vec().unwrap(); + data.append(&mut args); + + solana_instruction::Instruction { + program_id: crate::SPL_GOVERNANCE_ID, + accounts, + data, + } + } +} + +#[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct AddRequiredSignatoryInstructionData { + discriminator: u8, +} + +impl AddRequiredSignatoryInstructionData { + pub fn new() -> Self { + Self { discriminator: 29 } + } + + pub(crate) fn try_to_vec(&self) -> Result, std::io::Error> { + borsh::to_vec(self) + } +} + +impl Default for AddRequiredSignatoryInstructionData { + fn default() -> Self { + Self::new() + } +} + +#[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct AddRequiredSignatoryInstructionArgs { + pub signatory: Pubkey, +} + +impl AddRequiredSignatoryInstructionArgs { + pub(crate) fn try_to_vec(&self) -> Result, std::io::Error> { + borsh::to_vec(self) + } +} + +/// Instruction builder for `AddRequiredSignatory`. +/// +/// ### Accounts: +/// +/// 0. `[writable, signer]` governance_account +/// 1. `[writable]` required_signatory_account +/// 2. `[signer]` payer +/// 3. `[optional]` system_program (default to `11111111111111111111111111111111`) +#[derive(Clone, Debug, Default)] +pub struct AddRequiredSignatoryBuilder { + governance_account: Option, + required_signatory_account: Option, + payer: Option, + system_program: Option, + signatory: Option, + __remaining_accounts: Vec, +} + +impl AddRequiredSignatoryBuilder { + pub fn new() -> Self { + Self::default() + } + /// The Governance account the config is for + #[inline(always)] + pub fn governance_account(&mut self, governance_account: solana_pubkey::Pubkey) -> &mut Self { + self.governance_account = Some(governance_account); + self + } + #[inline(always)] + pub fn required_signatory_account( + &mut self, + required_signatory_account: solana_pubkey::Pubkey, + ) -> &mut Self { + self.required_signatory_account = Some(required_signatory_account); + self + } + #[inline(always)] + pub fn payer(&mut self, payer: solana_pubkey::Pubkey) -> &mut Self { + self.payer = Some(payer); + self + } + /// `[optional account, default to '11111111111111111111111111111111']` + #[inline(always)] + pub fn system_program(&mut self, system_program: solana_pubkey::Pubkey) -> &mut Self { + self.system_program = Some(system_program); + self + } + #[inline(always)] + pub fn signatory(&mut self, signatory: Pubkey) -> &mut Self { + self.signatory = Some(signatory); + self + } + /// Add an additional account to the instruction. + #[inline(always)] + pub fn add_remaining_account(&mut self, account: solana_instruction::AccountMeta) -> &mut Self { + self.__remaining_accounts.push(account); + self + } + /// Add additional accounts to the instruction. + #[inline(always)] + pub fn add_remaining_accounts( + &mut self, + accounts: &[solana_instruction::AccountMeta], + ) -> &mut Self { + self.__remaining_accounts.extend_from_slice(accounts); + self + } + #[allow(clippy::clone_on_copy)] + pub fn instruction(&self) -> solana_instruction::Instruction { + let accounts = AddRequiredSignatory { + governance_account: self + .governance_account + .expect("governance_account is not set"), + required_signatory_account: self + .required_signatory_account + .expect("required_signatory_account is not set"), + payer: self.payer.expect("payer is not set"), + system_program: self + .system_program + .unwrap_or(solana_pubkey::pubkey!("11111111111111111111111111111111")), + }; + let args = AddRequiredSignatoryInstructionArgs { + signatory: self.signatory.clone().expect("signatory is not set"), + }; + + accounts.instruction_with_remaining_accounts(args, &self.__remaining_accounts) + } +} + +/// `add_required_signatory` CPI accounts. +pub struct AddRequiredSignatoryCpiAccounts<'a, 'b> { + /// The Governance account the config is for + pub governance_account: &'b solana_account_info::AccountInfo<'a>, + + pub required_signatory_account: &'b solana_account_info::AccountInfo<'a>, + + pub payer: &'b solana_account_info::AccountInfo<'a>, + + pub system_program: &'b solana_account_info::AccountInfo<'a>, +} + +/// `add_required_signatory` CPI instruction. +pub struct AddRequiredSignatoryCpi<'a, 'b> { + /// The program to invoke. + pub __program: &'b solana_account_info::AccountInfo<'a>, + /// The Governance account the config is for + pub governance_account: &'b solana_account_info::AccountInfo<'a>, + + pub required_signatory_account: &'b solana_account_info::AccountInfo<'a>, + + pub payer: &'b solana_account_info::AccountInfo<'a>, + + pub system_program: &'b solana_account_info::AccountInfo<'a>, + /// The arguments for the instruction. + pub __args: AddRequiredSignatoryInstructionArgs, +} + +impl<'a, 'b> AddRequiredSignatoryCpi<'a, 'b> { + pub fn new( + program: &'b solana_account_info::AccountInfo<'a>, + accounts: AddRequiredSignatoryCpiAccounts<'a, 'b>, + args: AddRequiredSignatoryInstructionArgs, + ) -> Self { + Self { + __program: program, + governance_account: accounts.governance_account, + required_signatory_account: accounts.required_signatory_account, + payer: accounts.payer, + system_program: accounts.system_program, + __args: args, + } + } + #[inline(always)] + pub fn invoke(&self) -> solana_program_error::ProgramResult { + self.invoke_signed_with_remaining_accounts(&[], &[]) + } + #[inline(always)] + pub fn invoke_with_remaining_accounts( + &self, + remaining_accounts: &[(&'b solana_account_info::AccountInfo<'a>, bool, bool)], + ) -> solana_program_error::ProgramResult { + self.invoke_signed_with_remaining_accounts(&[], remaining_accounts) + } + #[inline(always)] + pub fn invoke_signed(&self, signers_seeds: &[&[&[u8]]]) -> solana_program_error::ProgramResult { + self.invoke_signed_with_remaining_accounts(signers_seeds, &[]) + } + #[allow(clippy::arithmetic_side_effects)] + #[allow(clippy::clone_on_copy)] + #[allow(clippy::vec_init_then_push)] + pub fn invoke_signed_with_remaining_accounts( + &self, + signers_seeds: &[&[&[u8]]], + remaining_accounts: &[(&'b solana_account_info::AccountInfo<'a>, bool, bool)], + ) -> solana_program_error::ProgramResult { + let mut accounts = Vec::with_capacity(4 + remaining_accounts.len()); + accounts.push(solana_instruction::AccountMeta::new( + *self.governance_account.key, + true, + )); + accounts.push(solana_instruction::AccountMeta::new( + *self.required_signatory_account.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.payer.key, + true, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.system_program.key, + false, + )); + remaining_accounts.iter().for_each(|remaining_account| { + accounts.push(solana_instruction::AccountMeta { + pubkey: *remaining_account.0.key, + is_signer: remaining_account.1, + is_writable: remaining_account.2, + }) + }); + let mut data = AddRequiredSignatoryInstructionData::new() + .try_to_vec() + .unwrap(); + let mut args = self.__args.try_to_vec().unwrap(); + data.append(&mut args); + + let instruction = solana_instruction::Instruction { + program_id: crate::SPL_GOVERNANCE_ID, + accounts, + data, + }; + let mut account_infos = Vec::with_capacity(5 + remaining_accounts.len()); + account_infos.push(self.__program.clone()); + account_infos.push(self.governance_account.clone()); + account_infos.push(self.required_signatory_account.clone()); + account_infos.push(self.payer.clone()); + account_infos.push(self.system_program.clone()); + remaining_accounts + .iter() + .for_each(|remaining_account| account_infos.push(remaining_account.0.clone())); + + if signers_seeds.is_empty() { + solana_cpi::invoke(&instruction, &account_infos) + } else { + solana_cpi::invoke_signed(&instruction, &account_infos, signers_seeds) + } + } +} + +/// Instruction builder for `AddRequiredSignatory` via CPI. +/// +/// ### Accounts: +/// +/// 0. `[writable, signer]` governance_account +/// 1. `[writable]` required_signatory_account +/// 2. `[signer]` payer +/// 3. `[]` system_program +#[derive(Clone, Debug)] +pub struct AddRequiredSignatoryCpiBuilder<'a, 'b> { + instruction: Box>, +} + +impl<'a, 'b> AddRequiredSignatoryCpiBuilder<'a, 'b> { + pub fn new(program: &'b solana_account_info::AccountInfo<'a>) -> Self { + let instruction = Box::new(AddRequiredSignatoryCpiBuilderInstruction { + __program: program, + governance_account: None, + required_signatory_account: None, + payer: None, + system_program: None, + signatory: None, + __remaining_accounts: Vec::new(), + }); + Self { instruction } + } + /// The Governance account the config is for + #[inline(always)] + pub fn governance_account( + &mut self, + governance_account: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.governance_account = Some(governance_account); + self + } + #[inline(always)] + pub fn required_signatory_account( + &mut self, + required_signatory_account: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.required_signatory_account = Some(required_signatory_account); + self + } + #[inline(always)] + pub fn payer(&mut self, payer: &'b solana_account_info::AccountInfo<'a>) -> &mut Self { + self.instruction.payer = Some(payer); + self + } + #[inline(always)] + pub fn system_program( + &mut self, + system_program: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.system_program = Some(system_program); + self + } + #[inline(always)] + pub fn signatory(&mut self, signatory: Pubkey) -> &mut Self { + self.instruction.signatory = Some(signatory); + self + } + /// Add an additional account to the instruction. + #[inline(always)] + pub fn add_remaining_account( + &mut self, + account: &'b solana_account_info::AccountInfo<'a>, + is_writable: bool, + is_signer: bool, + ) -> &mut Self { + self.instruction + .__remaining_accounts + .push((account, is_writable, is_signer)); + self + } + /// Add additional accounts to the instruction. + /// + /// Each account is represented by a tuple of the `AccountInfo`, a `bool` indicating whether the account is writable or not, + /// and a `bool` indicating whether the account is a signer or not. + #[inline(always)] + pub fn add_remaining_accounts( + &mut self, + accounts: &[(&'b solana_account_info::AccountInfo<'a>, bool, bool)], + ) -> &mut Self { + self.instruction + .__remaining_accounts + .extend_from_slice(accounts); + self + } + #[inline(always)] + pub fn invoke(&self) -> solana_program_error::ProgramResult { + self.invoke_signed(&[]) + } + #[allow(clippy::clone_on_copy)] + #[allow(clippy::vec_init_then_push)] + pub fn invoke_signed(&self, signers_seeds: &[&[&[u8]]]) -> solana_program_error::ProgramResult { + let args = AddRequiredSignatoryInstructionArgs { + signatory: self + .instruction + .signatory + .clone() + .expect("signatory is not set"), + }; + let instruction = AddRequiredSignatoryCpi { + __program: self.instruction.__program, + + governance_account: self + .instruction + .governance_account + .expect("governance_account is not set"), + + required_signatory_account: self + .instruction + .required_signatory_account + .expect("required_signatory_account is not set"), + + payer: self.instruction.payer.expect("payer is not set"), + + system_program: self + .instruction + .system_program + .expect("system_program is not set"), + __args: args, + }; + instruction.invoke_signed_with_remaining_accounts( + signers_seeds, + &self.instruction.__remaining_accounts, + ) + } +} + +#[derive(Clone, Debug)] +struct AddRequiredSignatoryCpiBuilderInstruction<'a, 'b> { + __program: &'b solana_account_info::AccountInfo<'a>, + governance_account: Option<&'b solana_account_info::AccountInfo<'a>>, + required_signatory_account: Option<&'b solana_account_info::AccountInfo<'a>>, + payer: Option<&'b solana_account_info::AccountInfo<'a>>, + system_program: Option<&'b solana_account_info::AccountInfo<'a>>, + signatory: Option, + /// Additional instruction accounts `(AccountInfo, is_writable, is_signer)`. + __remaining_accounts: Vec<(&'b solana_account_info::AccountInfo<'a>, bool, bool)>, +} diff --git a/e2e/governance/src/generated/instructions/add_signatory.rs b/e2e/governance/src/generated/instructions/add_signatory.rs new file mode 100644 index 0000000..b6616ef --- /dev/null +++ b/e2e/governance/src/generated/instructions/add_signatory.rs @@ -0,0 +1,541 @@ +//! This code was AUTOGENERATED using the codama library. +//! Please DO NOT EDIT THIS FILE, instead use visitors +//! to add features, then rerun codama to update it. +//! +//! +//! + +use borsh::BorshDeserialize; +use borsh::BorshSerialize; +use solana_pubkey::Pubkey; + +pub const ADD_SIGNATORY_DISCRIMINATOR: u8 = 7; + +/// Accounts. +#[derive(Debug)] +pub struct AddSignatory { + /// Proposal Account associated with the governance + pub proposal_account: solana_pubkey::Pubkey, + /// TokenOwnerRecord account of the Proposal owner + pub token_owner_record: solana_pubkey::Pubkey, + /// Governance Authority (Token Owner or Governance Delegate) + pub governance_authority: solana_pubkey::Pubkey, + /// Signatory Record Account + pub signatory_record_account: solana_pubkey::Pubkey, + + pub payer: solana_pubkey::Pubkey, + + pub system_program: solana_pubkey::Pubkey, +} + +impl AddSignatory { + pub fn instruction( + &self, + args: AddSignatoryInstructionArgs, + ) -> solana_instruction::Instruction { + self.instruction_with_remaining_accounts(args, &[]) + } + #[allow(clippy::arithmetic_side_effects)] + #[allow(clippy::vec_init_then_push)] + pub fn instruction_with_remaining_accounts( + &self, + args: AddSignatoryInstructionArgs, + remaining_accounts: &[solana_instruction::AccountMeta], + ) -> solana_instruction::Instruction { + let mut accounts = Vec::with_capacity(6 + remaining_accounts.len()); + accounts.push(solana_instruction::AccountMeta::new( + self.proposal_account, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.token_owner_record, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.governance_authority, + true, + )); + accounts.push(solana_instruction::AccountMeta::new( + self.signatory_record_account, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.payer, true, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.system_program, + false, + )); + accounts.extend_from_slice(remaining_accounts); + let mut data = AddSignatoryInstructionData::new().try_to_vec().unwrap(); + let mut args = args.try_to_vec().unwrap(); + data.append(&mut args); + + solana_instruction::Instruction { + program_id: crate::SPL_GOVERNANCE_ID, + accounts, + data, + } + } +} + +#[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct AddSignatoryInstructionData { + discriminator: u8, +} + +impl AddSignatoryInstructionData { + pub fn new() -> Self { + Self { discriminator: 7 } + } + + pub(crate) fn try_to_vec(&self) -> Result, std::io::Error> { + borsh::to_vec(self) + } +} + +impl Default for AddSignatoryInstructionData { + fn default() -> Self { + Self::new() + } +} + +#[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct AddSignatoryInstructionArgs { + pub signatory: Pubkey, +} + +impl AddSignatoryInstructionArgs { + pub(crate) fn try_to_vec(&self) -> Result, std::io::Error> { + borsh::to_vec(self) + } +} + +/// Instruction builder for `AddSignatory`. +/// +/// ### Accounts: +/// +/// 0. `[writable]` proposal_account +/// 1. `[]` token_owner_record +/// 2. `[signer]` governance_authority +/// 3. `[writable]` signatory_record_account +/// 4. `[signer]` payer +/// 5. `[optional]` system_program (default to `11111111111111111111111111111111`) +#[derive(Clone, Debug, Default)] +pub struct AddSignatoryBuilder { + proposal_account: Option, + token_owner_record: Option, + governance_authority: Option, + signatory_record_account: Option, + payer: Option, + system_program: Option, + signatory: Option, + __remaining_accounts: Vec, +} + +impl AddSignatoryBuilder { + pub fn new() -> Self { + Self::default() + } + /// Proposal Account associated with the governance + #[inline(always)] + pub fn proposal_account(&mut self, proposal_account: solana_pubkey::Pubkey) -> &mut Self { + self.proposal_account = Some(proposal_account); + self + } + /// TokenOwnerRecord account of the Proposal owner + #[inline(always)] + pub fn token_owner_record(&mut self, token_owner_record: solana_pubkey::Pubkey) -> &mut Self { + self.token_owner_record = Some(token_owner_record); + self + } + /// Governance Authority (Token Owner or Governance Delegate) + #[inline(always)] + pub fn governance_authority( + &mut self, + governance_authority: solana_pubkey::Pubkey, + ) -> &mut Self { + self.governance_authority = Some(governance_authority); + self + } + /// Signatory Record Account + #[inline(always)] + pub fn signatory_record_account( + &mut self, + signatory_record_account: solana_pubkey::Pubkey, + ) -> &mut Self { + self.signatory_record_account = Some(signatory_record_account); + self + } + #[inline(always)] + pub fn payer(&mut self, payer: solana_pubkey::Pubkey) -> &mut Self { + self.payer = Some(payer); + self + } + /// `[optional account, default to '11111111111111111111111111111111']` + #[inline(always)] + pub fn system_program(&mut self, system_program: solana_pubkey::Pubkey) -> &mut Self { + self.system_program = Some(system_program); + self + } + #[inline(always)] + pub fn signatory(&mut self, signatory: Pubkey) -> &mut Self { + self.signatory = Some(signatory); + self + } + /// Add an additional account to the instruction. + #[inline(always)] + pub fn add_remaining_account(&mut self, account: solana_instruction::AccountMeta) -> &mut Self { + self.__remaining_accounts.push(account); + self + } + /// Add additional accounts to the instruction. + #[inline(always)] + pub fn add_remaining_accounts( + &mut self, + accounts: &[solana_instruction::AccountMeta], + ) -> &mut Self { + self.__remaining_accounts.extend_from_slice(accounts); + self + } + #[allow(clippy::clone_on_copy)] + pub fn instruction(&self) -> solana_instruction::Instruction { + let accounts = AddSignatory { + proposal_account: self.proposal_account.expect("proposal_account is not set"), + token_owner_record: self + .token_owner_record + .expect("token_owner_record is not set"), + governance_authority: self + .governance_authority + .expect("governance_authority is not set"), + signatory_record_account: self + .signatory_record_account + .expect("signatory_record_account is not set"), + payer: self.payer.expect("payer is not set"), + system_program: self + .system_program + .unwrap_or(solana_pubkey::pubkey!("11111111111111111111111111111111")), + }; + let args = AddSignatoryInstructionArgs { + signatory: self.signatory.clone().expect("signatory is not set"), + }; + + accounts.instruction_with_remaining_accounts(args, &self.__remaining_accounts) + } +} + +/// `add_signatory` CPI accounts. +pub struct AddSignatoryCpiAccounts<'a, 'b> { + /// Proposal Account associated with the governance + pub proposal_account: &'b solana_account_info::AccountInfo<'a>, + /// TokenOwnerRecord account of the Proposal owner + pub token_owner_record: &'b solana_account_info::AccountInfo<'a>, + /// Governance Authority (Token Owner or Governance Delegate) + pub governance_authority: &'b solana_account_info::AccountInfo<'a>, + /// Signatory Record Account + pub signatory_record_account: &'b solana_account_info::AccountInfo<'a>, + + pub payer: &'b solana_account_info::AccountInfo<'a>, + + pub system_program: &'b solana_account_info::AccountInfo<'a>, +} + +/// `add_signatory` CPI instruction. +pub struct AddSignatoryCpi<'a, 'b> { + /// The program to invoke. + pub __program: &'b solana_account_info::AccountInfo<'a>, + /// Proposal Account associated with the governance + pub proposal_account: &'b solana_account_info::AccountInfo<'a>, + /// TokenOwnerRecord account of the Proposal owner + pub token_owner_record: &'b solana_account_info::AccountInfo<'a>, + /// Governance Authority (Token Owner or Governance Delegate) + pub governance_authority: &'b solana_account_info::AccountInfo<'a>, + /// Signatory Record Account + pub signatory_record_account: &'b solana_account_info::AccountInfo<'a>, + + pub payer: &'b solana_account_info::AccountInfo<'a>, + + pub system_program: &'b solana_account_info::AccountInfo<'a>, + /// The arguments for the instruction. + pub __args: AddSignatoryInstructionArgs, +} + +impl<'a, 'b> AddSignatoryCpi<'a, 'b> { + pub fn new( + program: &'b solana_account_info::AccountInfo<'a>, + accounts: AddSignatoryCpiAccounts<'a, 'b>, + args: AddSignatoryInstructionArgs, + ) -> Self { + Self { + __program: program, + proposal_account: accounts.proposal_account, + token_owner_record: accounts.token_owner_record, + governance_authority: accounts.governance_authority, + signatory_record_account: accounts.signatory_record_account, + payer: accounts.payer, + system_program: accounts.system_program, + __args: args, + } + } + #[inline(always)] + pub fn invoke(&self) -> solana_program_error::ProgramResult { + self.invoke_signed_with_remaining_accounts(&[], &[]) + } + #[inline(always)] + pub fn invoke_with_remaining_accounts( + &self, + remaining_accounts: &[(&'b solana_account_info::AccountInfo<'a>, bool, bool)], + ) -> solana_program_error::ProgramResult { + self.invoke_signed_with_remaining_accounts(&[], remaining_accounts) + } + #[inline(always)] + pub fn invoke_signed(&self, signers_seeds: &[&[&[u8]]]) -> solana_program_error::ProgramResult { + self.invoke_signed_with_remaining_accounts(signers_seeds, &[]) + } + #[allow(clippy::arithmetic_side_effects)] + #[allow(clippy::clone_on_copy)] + #[allow(clippy::vec_init_then_push)] + pub fn invoke_signed_with_remaining_accounts( + &self, + signers_seeds: &[&[&[u8]]], + remaining_accounts: &[(&'b solana_account_info::AccountInfo<'a>, bool, bool)], + ) -> solana_program_error::ProgramResult { + let mut accounts = Vec::with_capacity(6 + remaining_accounts.len()); + accounts.push(solana_instruction::AccountMeta::new( + *self.proposal_account.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.token_owner_record.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.governance_authority.key, + true, + )); + accounts.push(solana_instruction::AccountMeta::new( + *self.signatory_record_account.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.payer.key, + true, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.system_program.key, + false, + )); + remaining_accounts.iter().for_each(|remaining_account| { + accounts.push(solana_instruction::AccountMeta { + pubkey: *remaining_account.0.key, + is_signer: remaining_account.1, + is_writable: remaining_account.2, + }) + }); + let mut data = AddSignatoryInstructionData::new().try_to_vec().unwrap(); + let mut args = self.__args.try_to_vec().unwrap(); + data.append(&mut args); + + let instruction = solana_instruction::Instruction { + program_id: crate::SPL_GOVERNANCE_ID, + accounts, + data, + }; + let mut account_infos = Vec::with_capacity(7 + remaining_accounts.len()); + account_infos.push(self.__program.clone()); + account_infos.push(self.proposal_account.clone()); + account_infos.push(self.token_owner_record.clone()); + account_infos.push(self.governance_authority.clone()); + account_infos.push(self.signatory_record_account.clone()); + account_infos.push(self.payer.clone()); + account_infos.push(self.system_program.clone()); + remaining_accounts + .iter() + .for_each(|remaining_account| account_infos.push(remaining_account.0.clone())); + + if signers_seeds.is_empty() { + solana_cpi::invoke(&instruction, &account_infos) + } else { + solana_cpi::invoke_signed(&instruction, &account_infos, signers_seeds) + } + } +} + +/// Instruction builder for `AddSignatory` via CPI. +/// +/// ### Accounts: +/// +/// 0. `[writable]` proposal_account +/// 1. `[]` token_owner_record +/// 2. `[signer]` governance_authority +/// 3. `[writable]` signatory_record_account +/// 4. `[signer]` payer +/// 5. `[]` system_program +#[derive(Clone, Debug)] +pub struct AddSignatoryCpiBuilder<'a, 'b> { + instruction: Box>, +} + +impl<'a, 'b> AddSignatoryCpiBuilder<'a, 'b> { + pub fn new(program: &'b solana_account_info::AccountInfo<'a>) -> Self { + let instruction = Box::new(AddSignatoryCpiBuilderInstruction { + __program: program, + proposal_account: None, + token_owner_record: None, + governance_authority: None, + signatory_record_account: None, + payer: None, + system_program: None, + signatory: None, + __remaining_accounts: Vec::new(), + }); + Self { instruction } + } + /// Proposal Account associated with the governance + #[inline(always)] + pub fn proposal_account( + &mut self, + proposal_account: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.proposal_account = Some(proposal_account); + self + } + /// TokenOwnerRecord account of the Proposal owner + #[inline(always)] + pub fn token_owner_record( + &mut self, + token_owner_record: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.token_owner_record = Some(token_owner_record); + self + } + /// Governance Authority (Token Owner or Governance Delegate) + #[inline(always)] + pub fn governance_authority( + &mut self, + governance_authority: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.governance_authority = Some(governance_authority); + self + } + /// Signatory Record Account + #[inline(always)] + pub fn signatory_record_account( + &mut self, + signatory_record_account: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.signatory_record_account = Some(signatory_record_account); + self + } + #[inline(always)] + pub fn payer(&mut self, payer: &'b solana_account_info::AccountInfo<'a>) -> &mut Self { + self.instruction.payer = Some(payer); + self + } + #[inline(always)] + pub fn system_program( + &mut self, + system_program: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.system_program = Some(system_program); + self + } + #[inline(always)] + pub fn signatory(&mut self, signatory: Pubkey) -> &mut Self { + self.instruction.signatory = Some(signatory); + self + } + /// Add an additional account to the instruction. + #[inline(always)] + pub fn add_remaining_account( + &mut self, + account: &'b solana_account_info::AccountInfo<'a>, + is_writable: bool, + is_signer: bool, + ) -> &mut Self { + self.instruction + .__remaining_accounts + .push((account, is_writable, is_signer)); + self + } + /// Add additional accounts to the instruction. + /// + /// Each account is represented by a tuple of the `AccountInfo`, a `bool` indicating whether the account is writable or not, + /// and a `bool` indicating whether the account is a signer or not. + #[inline(always)] + pub fn add_remaining_accounts( + &mut self, + accounts: &[(&'b solana_account_info::AccountInfo<'a>, bool, bool)], + ) -> &mut Self { + self.instruction + .__remaining_accounts + .extend_from_slice(accounts); + self + } + #[inline(always)] + pub fn invoke(&self) -> solana_program_error::ProgramResult { + self.invoke_signed(&[]) + } + #[allow(clippy::clone_on_copy)] + #[allow(clippy::vec_init_then_push)] + pub fn invoke_signed(&self, signers_seeds: &[&[&[u8]]]) -> solana_program_error::ProgramResult { + let args = AddSignatoryInstructionArgs { + signatory: self + .instruction + .signatory + .clone() + .expect("signatory is not set"), + }; + let instruction = AddSignatoryCpi { + __program: self.instruction.__program, + + proposal_account: self + .instruction + .proposal_account + .expect("proposal_account is not set"), + + token_owner_record: self + .instruction + .token_owner_record + .expect("token_owner_record is not set"), + + governance_authority: self + .instruction + .governance_authority + .expect("governance_authority is not set"), + + signatory_record_account: self + .instruction + .signatory_record_account + .expect("signatory_record_account is not set"), + + payer: self.instruction.payer.expect("payer is not set"), + + system_program: self + .instruction + .system_program + .expect("system_program is not set"), + __args: args, + }; + instruction.invoke_signed_with_remaining_accounts( + signers_seeds, + &self.instruction.__remaining_accounts, + ) + } +} + +#[derive(Clone, Debug)] +struct AddSignatoryCpiBuilderInstruction<'a, 'b> { + __program: &'b solana_account_info::AccountInfo<'a>, + proposal_account: Option<&'b solana_account_info::AccountInfo<'a>>, + token_owner_record: Option<&'b solana_account_info::AccountInfo<'a>>, + governance_authority: Option<&'b solana_account_info::AccountInfo<'a>>, + signatory_record_account: Option<&'b solana_account_info::AccountInfo<'a>>, + payer: Option<&'b solana_account_info::AccountInfo<'a>>, + system_program: Option<&'b solana_account_info::AccountInfo<'a>>, + signatory: Option, + /// Additional instruction accounts `(AccountInfo, is_writable, is_signer)`. + __remaining_accounts: Vec<(&'b solana_account_info::AccountInfo<'a>, bool, bool)>, +} diff --git a/e2e/governance/src/generated/instructions/cancel_proposal.rs b/e2e/governance/src/generated/instructions/cancel_proposal.rs new file mode 100644 index 0000000..ad46ea8 --- /dev/null +++ b/e2e/governance/src/generated/instructions/cancel_proposal.rs @@ -0,0 +1,447 @@ +//! This code was AUTOGENERATED using the codama library. +//! Please DO NOT EDIT THIS FILE, instead use visitors +//! to add features, then rerun codama to update it. +//! +//! +//! + +use borsh::BorshDeserialize; +use borsh::BorshSerialize; + +pub const CANCEL_PROPOSAL_DISCRIMINATOR: u8 = 11; + +/// Accounts. +#[derive(Debug)] +pub struct CancelProposal { + pub realm_account: solana_pubkey::Pubkey, + + pub governance_account: solana_pubkey::Pubkey, + + pub proposal_account: solana_pubkey::Pubkey, + /// TokenOwnerRecord account of the Proposal owner + pub token_owner_record: solana_pubkey::Pubkey, + /// Governance authority (Token Owner or Governance Delegate) + pub governance_authority: solana_pubkey::Pubkey, +} + +impl CancelProposal { + pub fn instruction(&self) -> solana_instruction::Instruction { + self.instruction_with_remaining_accounts(&[]) + } + #[allow(clippy::arithmetic_side_effects)] + #[allow(clippy::vec_init_then_push)] + pub fn instruction_with_remaining_accounts( + &self, + remaining_accounts: &[solana_instruction::AccountMeta], + ) -> solana_instruction::Instruction { + let mut accounts = Vec::with_capacity(5 + remaining_accounts.len()); + accounts.push(solana_instruction::AccountMeta::new( + self.realm_account, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + self.governance_account, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + self.proposal_account, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + self.token_owner_record, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.governance_authority, + true, + )); + accounts.extend_from_slice(remaining_accounts); + let data = CancelProposalInstructionData::new().try_to_vec().unwrap(); + + solana_instruction::Instruction { + program_id: crate::SPL_GOVERNANCE_ID, + accounts, + data, + } + } +} + +#[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct CancelProposalInstructionData { + discriminator: u8, +} + +impl CancelProposalInstructionData { + pub fn new() -> Self { + Self { discriminator: 11 } + } + + pub(crate) fn try_to_vec(&self) -> Result, std::io::Error> { + borsh::to_vec(self) + } +} + +impl Default for CancelProposalInstructionData { + fn default() -> Self { + Self::new() + } +} + +/// Instruction builder for `CancelProposal`. +/// +/// ### Accounts: +/// +/// 0. `[writable]` realm_account +/// 1. `[writable]` governance_account +/// 2. `[writable]` proposal_account +/// 3. `[writable]` token_owner_record +/// 4. `[signer]` governance_authority +#[derive(Clone, Debug, Default)] +pub struct CancelProposalBuilder { + realm_account: Option, + governance_account: Option, + proposal_account: Option, + token_owner_record: Option, + governance_authority: Option, + __remaining_accounts: Vec, +} + +impl CancelProposalBuilder { + pub fn new() -> Self { + Self::default() + } + #[inline(always)] + pub fn realm_account(&mut self, realm_account: solana_pubkey::Pubkey) -> &mut Self { + self.realm_account = Some(realm_account); + self + } + #[inline(always)] + pub fn governance_account(&mut self, governance_account: solana_pubkey::Pubkey) -> &mut Self { + self.governance_account = Some(governance_account); + self + } + #[inline(always)] + pub fn proposal_account(&mut self, proposal_account: solana_pubkey::Pubkey) -> &mut Self { + self.proposal_account = Some(proposal_account); + self + } + /// TokenOwnerRecord account of the Proposal owner + #[inline(always)] + pub fn token_owner_record(&mut self, token_owner_record: solana_pubkey::Pubkey) -> &mut Self { + self.token_owner_record = Some(token_owner_record); + self + } + /// Governance authority (Token Owner or Governance Delegate) + #[inline(always)] + pub fn governance_authority( + &mut self, + governance_authority: solana_pubkey::Pubkey, + ) -> &mut Self { + self.governance_authority = Some(governance_authority); + self + } + /// Add an additional account to the instruction. + #[inline(always)] + pub fn add_remaining_account(&mut self, account: solana_instruction::AccountMeta) -> &mut Self { + self.__remaining_accounts.push(account); + self + } + /// Add additional accounts to the instruction. + #[inline(always)] + pub fn add_remaining_accounts( + &mut self, + accounts: &[solana_instruction::AccountMeta], + ) -> &mut Self { + self.__remaining_accounts.extend_from_slice(accounts); + self + } + #[allow(clippy::clone_on_copy)] + pub fn instruction(&self) -> solana_instruction::Instruction { + let accounts = CancelProposal { + realm_account: self.realm_account.expect("realm_account is not set"), + governance_account: self + .governance_account + .expect("governance_account is not set"), + proposal_account: self.proposal_account.expect("proposal_account is not set"), + token_owner_record: self + .token_owner_record + .expect("token_owner_record is not set"), + governance_authority: self + .governance_authority + .expect("governance_authority is not set"), + }; + + accounts.instruction_with_remaining_accounts(&self.__remaining_accounts) + } +} + +/// `cancel_proposal` CPI accounts. +pub struct CancelProposalCpiAccounts<'a, 'b> { + pub realm_account: &'b solana_account_info::AccountInfo<'a>, + + pub governance_account: &'b solana_account_info::AccountInfo<'a>, + + pub proposal_account: &'b solana_account_info::AccountInfo<'a>, + /// TokenOwnerRecord account of the Proposal owner + pub token_owner_record: &'b solana_account_info::AccountInfo<'a>, + /// Governance authority (Token Owner or Governance Delegate) + pub governance_authority: &'b solana_account_info::AccountInfo<'a>, +} + +/// `cancel_proposal` CPI instruction. +pub struct CancelProposalCpi<'a, 'b> { + /// The program to invoke. + pub __program: &'b solana_account_info::AccountInfo<'a>, + + pub realm_account: &'b solana_account_info::AccountInfo<'a>, + + pub governance_account: &'b solana_account_info::AccountInfo<'a>, + + pub proposal_account: &'b solana_account_info::AccountInfo<'a>, + /// TokenOwnerRecord account of the Proposal owner + pub token_owner_record: &'b solana_account_info::AccountInfo<'a>, + /// Governance authority (Token Owner or Governance Delegate) + pub governance_authority: &'b solana_account_info::AccountInfo<'a>, +} + +impl<'a, 'b> CancelProposalCpi<'a, 'b> { + pub fn new( + program: &'b solana_account_info::AccountInfo<'a>, + accounts: CancelProposalCpiAccounts<'a, 'b>, + ) -> Self { + Self { + __program: program, + realm_account: accounts.realm_account, + governance_account: accounts.governance_account, + proposal_account: accounts.proposal_account, + token_owner_record: accounts.token_owner_record, + governance_authority: accounts.governance_authority, + } + } + #[inline(always)] + pub fn invoke(&self) -> solana_program_error::ProgramResult { + self.invoke_signed_with_remaining_accounts(&[], &[]) + } + #[inline(always)] + pub fn invoke_with_remaining_accounts( + &self, + remaining_accounts: &[(&'b solana_account_info::AccountInfo<'a>, bool, bool)], + ) -> solana_program_error::ProgramResult { + self.invoke_signed_with_remaining_accounts(&[], remaining_accounts) + } + #[inline(always)] + pub fn invoke_signed(&self, signers_seeds: &[&[&[u8]]]) -> solana_program_error::ProgramResult { + self.invoke_signed_with_remaining_accounts(signers_seeds, &[]) + } + #[allow(clippy::arithmetic_side_effects)] + #[allow(clippy::clone_on_copy)] + #[allow(clippy::vec_init_then_push)] + pub fn invoke_signed_with_remaining_accounts( + &self, + signers_seeds: &[&[&[u8]]], + remaining_accounts: &[(&'b solana_account_info::AccountInfo<'a>, bool, bool)], + ) -> solana_program_error::ProgramResult { + let mut accounts = Vec::with_capacity(5 + remaining_accounts.len()); + accounts.push(solana_instruction::AccountMeta::new( + *self.realm_account.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + *self.governance_account.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + *self.proposal_account.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + *self.token_owner_record.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.governance_authority.key, + true, + )); + remaining_accounts.iter().for_each(|remaining_account| { + accounts.push(solana_instruction::AccountMeta { + pubkey: *remaining_account.0.key, + is_signer: remaining_account.1, + is_writable: remaining_account.2, + }) + }); + let data = CancelProposalInstructionData::new().try_to_vec().unwrap(); + + let instruction = solana_instruction::Instruction { + program_id: crate::SPL_GOVERNANCE_ID, + accounts, + data, + }; + let mut account_infos = Vec::with_capacity(6 + remaining_accounts.len()); + account_infos.push(self.__program.clone()); + account_infos.push(self.realm_account.clone()); + account_infos.push(self.governance_account.clone()); + account_infos.push(self.proposal_account.clone()); + account_infos.push(self.token_owner_record.clone()); + account_infos.push(self.governance_authority.clone()); + remaining_accounts + .iter() + .for_each(|remaining_account| account_infos.push(remaining_account.0.clone())); + + if signers_seeds.is_empty() { + solana_cpi::invoke(&instruction, &account_infos) + } else { + solana_cpi::invoke_signed(&instruction, &account_infos, signers_seeds) + } + } +} + +/// Instruction builder for `CancelProposal` via CPI. +/// +/// ### Accounts: +/// +/// 0. `[writable]` realm_account +/// 1. `[writable]` governance_account +/// 2. `[writable]` proposal_account +/// 3. `[writable]` token_owner_record +/// 4. `[signer]` governance_authority +#[derive(Clone, Debug)] +pub struct CancelProposalCpiBuilder<'a, 'b> { + instruction: Box>, +} + +impl<'a, 'b> CancelProposalCpiBuilder<'a, 'b> { + pub fn new(program: &'b solana_account_info::AccountInfo<'a>) -> Self { + let instruction = Box::new(CancelProposalCpiBuilderInstruction { + __program: program, + realm_account: None, + governance_account: None, + proposal_account: None, + token_owner_record: None, + governance_authority: None, + __remaining_accounts: Vec::new(), + }); + Self { instruction } + } + #[inline(always)] + pub fn realm_account( + &mut self, + realm_account: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.realm_account = Some(realm_account); + self + } + #[inline(always)] + pub fn governance_account( + &mut self, + governance_account: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.governance_account = Some(governance_account); + self + } + #[inline(always)] + pub fn proposal_account( + &mut self, + proposal_account: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.proposal_account = Some(proposal_account); + self + } + /// TokenOwnerRecord account of the Proposal owner + #[inline(always)] + pub fn token_owner_record( + &mut self, + token_owner_record: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.token_owner_record = Some(token_owner_record); + self + } + /// Governance authority (Token Owner or Governance Delegate) + #[inline(always)] + pub fn governance_authority( + &mut self, + governance_authority: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.governance_authority = Some(governance_authority); + self + } + /// Add an additional account to the instruction. + #[inline(always)] + pub fn add_remaining_account( + &mut self, + account: &'b solana_account_info::AccountInfo<'a>, + is_writable: bool, + is_signer: bool, + ) -> &mut Self { + self.instruction + .__remaining_accounts + .push((account, is_writable, is_signer)); + self + } + /// Add additional accounts to the instruction. + /// + /// Each account is represented by a tuple of the `AccountInfo`, a `bool` indicating whether the account is writable or not, + /// and a `bool` indicating whether the account is a signer or not. + #[inline(always)] + pub fn add_remaining_accounts( + &mut self, + accounts: &[(&'b solana_account_info::AccountInfo<'a>, bool, bool)], + ) -> &mut Self { + self.instruction + .__remaining_accounts + .extend_from_slice(accounts); + self + } + #[inline(always)] + pub fn invoke(&self) -> solana_program_error::ProgramResult { + self.invoke_signed(&[]) + } + #[allow(clippy::clone_on_copy)] + #[allow(clippy::vec_init_then_push)] + pub fn invoke_signed(&self, signers_seeds: &[&[&[u8]]]) -> solana_program_error::ProgramResult { + let instruction = CancelProposalCpi { + __program: self.instruction.__program, + + realm_account: self + .instruction + .realm_account + .expect("realm_account is not set"), + + governance_account: self + .instruction + .governance_account + .expect("governance_account is not set"), + + proposal_account: self + .instruction + .proposal_account + .expect("proposal_account is not set"), + + token_owner_record: self + .instruction + .token_owner_record + .expect("token_owner_record is not set"), + + governance_authority: self + .instruction + .governance_authority + .expect("governance_authority is not set"), + }; + instruction.invoke_signed_with_remaining_accounts( + signers_seeds, + &self.instruction.__remaining_accounts, + ) + } +} + +#[derive(Clone, Debug)] +struct CancelProposalCpiBuilderInstruction<'a, 'b> { + __program: &'b solana_account_info::AccountInfo<'a>, + realm_account: Option<&'b solana_account_info::AccountInfo<'a>>, + governance_account: Option<&'b solana_account_info::AccountInfo<'a>>, + proposal_account: Option<&'b solana_account_info::AccountInfo<'a>>, + token_owner_record: Option<&'b solana_account_info::AccountInfo<'a>>, + governance_authority: Option<&'b solana_account_info::AccountInfo<'a>>, + /// Additional instruction accounts `(AccountInfo, is_writable, is_signer)`. + __remaining_accounts: Vec<(&'b solana_account_info::AccountInfo<'a>, bool, bool)>, +} diff --git a/e2e/governance/src/generated/instructions/cast_vote.rs b/e2e/governance/src/generated/instructions/cast_vote.rs new file mode 100644 index 0000000..79388f7 --- /dev/null +++ b/e2e/governance/src/generated/instructions/cast_vote.rs @@ -0,0 +1,896 @@ +//! This code was AUTOGENERATED using the codama library. +//! Please DO NOT EDIT THIS FILE, instead use visitors +//! to add features, then rerun codama to update it. +//! +//! +//! + +use crate::generated::types::Vote; +use borsh::BorshDeserialize; +use borsh::BorshSerialize; + +pub const CAST_VOTE_DISCRIMINATOR: u8 = 13; + +/// Accounts. +#[derive(Debug)] +pub struct CastVote { + pub realm_account: solana_pubkey::Pubkey, + + pub governance_account: solana_pubkey::Pubkey, + + pub proposal_account: solana_pubkey::Pubkey, + /// TokenOwnerRecord of the Proposal owner + pub proposal_token_owner_record: solana_pubkey::Pubkey, + /// TokenOwnerRecord of the voter. PDA seeds: ['governance',realm, vote_governing_token_mint, governing_token_owner] + pub voter_token_owner_record: solana_pubkey::Pubkey, + /// Governance Authority (Token Owner or Governance Delegate) + pub governance_authority: solana_pubkey::Pubkey, + /// Proposal VoteRecord account. PDA seeds: ['governance',proposal,token_owner_record] + pub proposal_vote_record: solana_pubkey::Pubkey, + /// The Governing Token Mint which is used to cast the vote (vote_governing_token_mint). + /// The voting token mint is the governing_token_mint of the Proposal for Approve, Deny and Abstain votes. + /// For Veto vote the voting token mint is the mint of the opposite voting population. + /// Council mint to veto Community proposals and Community mint to veto Council proposals + /// Note: In the current version only Council veto is supported + pub governing_token_mint: solana_pubkey::Pubkey, + + pub payer: solana_pubkey::Pubkey, + + pub system_program: solana_pubkey::Pubkey, + /// RealmConfig account. PDA seeds: ['realm-config', realm] + pub realm_config_account: solana_pubkey::Pubkey, + /// Optional Voter Weight Record + pub voter_weight_record: Option, + /// Optional Max Voter Weight Record + pub max_voter_weight_record: Option, +} + +impl CastVote { + pub fn instruction(&self, args: CastVoteInstructionArgs) -> solana_instruction::Instruction { + self.instruction_with_remaining_accounts(args, &[]) + } + #[allow(clippy::arithmetic_side_effects)] + #[allow(clippy::vec_init_then_push)] + pub fn instruction_with_remaining_accounts( + &self, + args: CastVoteInstructionArgs, + remaining_accounts: &[solana_instruction::AccountMeta], + ) -> solana_instruction::Instruction { + let mut accounts = Vec::with_capacity(13 + remaining_accounts.len()); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.realm_account, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + self.governance_account, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + self.proposal_account, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + self.proposal_token_owner_record, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + self.voter_token_owner_record, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.governance_authority, + true, + )); + accounts.push(solana_instruction::AccountMeta::new( + self.proposal_vote_record, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.governing_token_mint, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.payer, true, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.system_program, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.realm_config_account, + false, + )); + if let Some(voter_weight_record) = self.voter_weight_record { + accounts.push(solana_instruction::AccountMeta::new_readonly( + voter_weight_record, + false, + )); + } else { + accounts.push(solana_instruction::AccountMeta::new_readonly( + crate::SPL_GOVERNANCE_ID, + false, + )); + } + if let Some(max_voter_weight_record) = self.max_voter_weight_record { + accounts.push(solana_instruction::AccountMeta::new_readonly( + max_voter_weight_record, + false, + )); + } else { + accounts.push(solana_instruction::AccountMeta::new_readonly( + crate::SPL_GOVERNANCE_ID, + false, + )); + } + accounts.extend_from_slice(remaining_accounts); + let mut data = CastVoteInstructionData::new().try_to_vec().unwrap(); + let mut args = args.try_to_vec().unwrap(); + data.append(&mut args); + + solana_instruction::Instruction { + program_id: crate::SPL_GOVERNANCE_ID, + accounts, + data, + } + } +} + +#[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct CastVoteInstructionData { + discriminator: u8, +} + +impl CastVoteInstructionData { + pub fn new() -> Self { + Self { discriminator: 13 } + } + + pub(crate) fn try_to_vec(&self) -> Result, std::io::Error> { + borsh::to_vec(self) + } +} + +impl Default for CastVoteInstructionData { + fn default() -> Self { + Self::new() + } +} + +#[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct CastVoteInstructionArgs { + pub vote: Vote, +} + +impl CastVoteInstructionArgs { + pub(crate) fn try_to_vec(&self) -> Result, std::io::Error> { + borsh::to_vec(self) + } +} + +/// Instruction builder for `CastVote`. +/// +/// ### Accounts: +/// +/// 0. `[]` realm_account +/// 1. `[writable]` governance_account +/// 2. `[writable]` proposal_account +/// 3. `[writable]` proposal_token_owner_record +/// 4. `[writable]` voter_token_owner_record +/// 5. `[signer]` governance_authority +/// 6. `[writable]` proposal_vote_record +/// 7. `[]` governing_token_mint +/// 8. `[signer]` payer +/// 9. `[optional]` system_program (default to `11111111111111111111111111111111`) +/// 10. `[]` realm_config_account +/// 11. `[optional]` voter_weight_record +/// 12. `[optional]` max_voter_weight_record +#[derive(Clone, Debug, Default)] +pub struct CastVoteBuilder { + realm_account: Option, + governance_account: Option, + proposal_account: Option, + proposal_token_owner_record: Option, + voter_token_owner_record: Option, + governance_authority: Option, + proposal_vote_record: Option, + governing_token_mint: Option, + payer: Option, + system_program: Option, + realm_config_account: Option, + voter_weight_record: Option, + max_voter_weight_record: Option, + vote: Option, + __remaining_accounts: Vec, +} + +impl CastVoteBuilder { + pub fn new() -> Self { + Self::default() + } + #[inline(always)] + pub fn realm_account(&mut self, realm_account: solana_pubkey::Pubkey) -> &mut Self { + self.realm_account = Some(realm_account); + self + } + #[inline(always)] + pub fn governance_account(&mut self, governance_account: solana_pubkey::Pubkey) -> &mut Self { + self.governance_account = Some(governance_account); + self + } + #[inline(always)] + pub fn proposal_account(&mut self, proposal_account: solana_pubkey::Pubkey) -> &mut Self { + self.proposal_account = Some(proposal_account); + self + } + /// TokenOwnerRecord of the Proposal owner + #[inline(always)] + pub fn proposal_token_owner_record( + &mut self, + proposal_token_owner_record: solana_pubkey::Pubkey, + ) -> &mut Self { + self.proposal_token_owner_record = Some(proposal_token_owner_record); + self + } + /// TokenOwnerRecord of the voter. PDA seeds: ['governance',realm, vote_governing_token_mint, governing_token_owner] + #[inline(always)] + pub fn voter_token_owner_record( + &mut self, + voter_token_owner_record: solana_pubkey::Pubkey, + ) -> &mut Self { + self.voter_token_owner_record = Some(voter_token_owner_record); + self + } + /// Governance Authority (Token Owner or Governance Delegate) + #[inline(always)] + pub fn governance_authority( + &mut self, + governance_authority: solana_pubkey::Pubkey, + ) -> &mut Self { + self.governance_authority = Some(governance_authority); + self + } + /// Proposal VoteRecord account. PDA seeds: ['governance',proposal,token_owner_record] + #[inline(always)] + pub fn proposal_vote_record( + &mut self, + proposal_vote_record: solana_pubkey::Pubkey, + ) -> &mut Self { + self.proposal_vote_record = Some(proposal_vote_record); + self + } + /// The Governing Token Mint which is used to cast the vote (vote_governing_token_mint). + /// The voting token mint is the governing_token_mint of the Proposal for Approve, Deny and Abstain votes. + /// For Veto vote the voting token mint is the mint of the opposite voting population. + /// Council mint to veto Community proposals and Community mint to veto Council proposals + /// Note: In the current version only Council veto is supported + #[inline(always)] + pub fn governing_token_mint( + &mut self, + governing_token_mint: solana_pubkey::Pubkey, + ) -> &mut Self { + self.governing_token_mint = Some(governing_token_mint); + self + } + #[inline(always)] + pub fn payer(&mut self, payer: solana_pubkey::Pubkey) -> &mut Self { + self.payer = Some(payer); + self + } + /// `[optional account, default to '11111111111111111111111111111111']` + #[inline(always)] + pub fn system_program(&mut self, system_program: solana_pubkey::Pubkey) -> &mut Self { + self.system_program = Some(system_program); + self + } + /// RealmConfig account. PDA seeds: ['realm-config', realm] + #[inline(always)] + pub fn realm_config_account( + &mut self, + realm_config_account: solana_pubkey::Pubkey, + ) -> &mut Self { + self.realm_config_account = Some(realm_config_account); + self + } + /// `[optional account]` + /// Optional Voter Weight Record + #[inline(always)] + pub fn voter_weight_record( + &mut self, + voter_weight_record: Option, + ) -> &mut Self { + self.voter_weight_record = voter_weight_record; + self + } + /// `[optional account]` + /// Optional Max Voter Weight Record + #[inline(always)] + pub fn max_voter_weight_record( + &mut self, + max_voter_weight_record: Option, + ) -> &mut Self { + self.max_voter_weight_record = max_voter_weight_record; + self + } + #[inline(always)] + pub fn vote(&mut self, vote: Vote) -> &mut Self { + self.vote = Some(vote); + self + } + /// Add an additional account to the instruction. + #[inline(always)] + pub fn add_remaining_account(&mut self, account: solana_instruction::AccountMeta) -> &mut Self { + self.__remaining_accounts.push(account); + self + } + /// Add additional accounts to the instruction. + #[inline(always)] + pub fn add_remaining_accounts( + &mut self, + accounts: &[solana_instruction::AccountMeta], + ) -> &mut Self { + self.__remaining_accounts.extend_from_slice(accounts); + self + } + #[allow(clippy::clone_on_copy)] + pub fn instruction(&self) -> solana_instruction::Instruction { + let accounts = CastVote { + realm_account: self.realm_account.expect("realm_account is not set"), + governance_account: self + .governance_account + .expect("governance_account is not set"), + proposal_account: self.proposal_account.expect("proposal_account is not set"), + proposal_token_owner_record: self + .proposal_token_owner_record + .expect("proposal_token_owner_record is not set"), + voter_token_owner_record: self + .voter_token_owner_record + .expect("voter_token_owner_record is not set"), + governance_authority: self + .governance_authority + .expect("governance_authority is not set"), + proposal_vote_record: self + .proposal_vote_record + .expect("proposal_vote_record is not set"), + governing_token_mint: self + .governing_token_mint + .expect("governing_token_mint is not set"), + payer: self.payer.expect("payer is not set"), + system_program: self + .system_program + .unwrap_or(solana_pubkey::pubkey!("11111111111111111111111111111111")), + realm_config_account: self + .realm_config_account + .expect("realm_config_account is not set"), + voter_weight_record: self.voter_weight_record, + max_voter_weight_record: self.max_voter_weight_record, + }; + let args = CastVoteInstructionArgs { + vote: self.vote.clone().expect("vote is not set"), + }; + + accounts.instruction_with_remaining_accounts(args, &self.__remaining_accounts) + } +} + +/// `cast_vote` CPI accounts. +pub struct CastVoteCpiAccounts<'a, 'b> { + pub realm_account: &'b solana_account_info::AccountInfo<'a>, + + pub governance_account: &'b solana_account_info::AccountInfo<'a>, + + pub proposal_account: &'b solana_account_info::AccountInfo<'a>, + /// TokenOwnerRecord of the Proposal owner + pub proposal_token_owner_record: &'b solana_account_info::AccountInfo<'a>, + /// TokenOwnerRecord of the voter. PDA seeds: ['governance',realm, vote_governing_token_mint, governing_token_owner] + pub voter_token_owner_record: &'b solana_account_info::AccountInfo<'a>, + /// Governance Authority (Token Owner or Governance Delegate) + pub governance_authority: &'b solana_account_info::AccountInfo<'a>, + /// Proposal VoteRecord account. PDA seeds: ['governance',proposal,token_owner_record] + pub proposal_vote_record: &'b solana_account_info::AccountInfo<'a>, + /// The Governing Token Mint which is used to cast the vote (vote_governing_token_mint). + /// The voting token mint is the governing_token_mint of the Proposal for Approve, Deny and Abstain votes. + /// For Veto vote the voting token mint is the mint of the opposite voting population. + /// Council mint to veto Community proposals and Community mint to veto Council proposals + /// Note: In the current version only Council veto is supported + pub governing_token_mint: &'b solana_account_info::AccountInfo<'a>, + + pub payer: &'b solana_account_info::AccountInfo<'a>, + + pub system_program: &'b solana_account_info::AccountInfo<'a>, + /// RealmConfig account. PDA seeds: ['realm-config', realm] + pub realm_config_account: &'b solana_account_info::AccountInfo<'a>, + /// Optional Voter Weight Record + pub voter_weight_record: Option<&'b solana_account_info::AccountInfo<'a>>, + /// Optional Max Voter Weight Record + pub max_voter_weight_record: Option<&'b solana_account_info::AccountInfo<'a>>, +} + +/// `cast_vote` CPI instruction. +pub struct CastVoteCpi<'a, 'b> { + /// The program to invoke. + pub __program: &'b solana_account_info::AccountInfo<'a>, + + pub realm_account: &'b solana_account_info::AccountInfo<'a>, + + pub governance_account: &'b solana_account_info::AccountInfo<'a>, + + pub proposal_account: &'b solana_account_info::AccountInfo<'a>, + /// TokenOwnerRecord of the Proposal owner + pub proposal_token_owner_record: &'b solana_account_info::AccountInfo<'a>, + /// TokenOwnerRecord of the voter. PDA seeds: ['governance',realm, vote_governing_token_mint, governing_token_owner] + pub voter_token_owner_record: &'b solana_account_info::AccountInfo<'a>, + /// Governance Authority (Token Owner or Governance Delegate) + pub governance_authority: &'b solana_account_info::AccountInfo<'a>, + /// Proposal VoteRecord account. PDA seeds: ['governance',proposal,token_owner_record] + pub proposal_vote_record: &'b solana_account_info::AccountInfo<'a>, + /// The Governing Token Mint which is used to cast the vote (vote_governing_token_mint). + /// The voting token mint is the governing_token_mint of the Proposal for Approve, Deny and Abstain votes. + /// For Veto vote the voting token mint is the mint of the opposite voting population. + /// Council mint to veto Community proposals and Community mint to veto Council proposals + /// Note: In the current version only Council veto is supported + pub governing_token_mint: &'b solana_account_info::AccountInfo<'a>, + + pub payer: &'b solana_account_info::AccountInfo<'a>, + + pub system_program: &'b solana_account_info::AccountInfo<'a>, + /// RealmConfig account. PDA seeds: ['realm-config', realm] + pub realm_config_account: &'b solana_account_info::AccountInfo<'a>, + /// Optional Voter Weight Record + pub voter_weight_record: Option<&'b solana_account_info::AccountInfo<'a>>, + /// Optional Max Voter Weight Record + pub max_voter_weight_record: Option<&'b solana_account_info::AccountInfo<'a>>, + /// The arguments for the instruction. + pub __args: CastVoteInstructionArgs, +} + +impl<'a, 'b> CastVoteCpi<'a, 'b> { + pub fn new( + program: &'b solana_account_info::AccountInfo<'a>, + accounts: CastVoteCpiAccounts<'a, 'b>, + args: CastVoteInstructionArgs, + ) -> Self { + Self { + __program: program, + realm_account: accounts.realm_account, + governance_account: accounts.governance_account, + proposal_account: accounts.proposal_account, + proposal_token_owner_record: accounts.proposal_token_owner_record, + voter_token_owner_record: accounts.voter_token_owner_record, + governance_authority: accounts.governance_authority, + proposal_vote_record: accounts.proposal_vote_record, + governing_token_mint: accounts.governing_token_mint, + payer: accounts.payer, + system_program: accounts.system_program, + realm_config_account: accounts.realm_config_account, + voter_weight_record: accounts.voter_weight_record, + max_voter_weight_record: accounts.max_voter_weight_record, + __args: args, + } + } + #[inline(always)] + pub fn invoke(&self) -> solana_program_error::ProgramResult { + self.invoke_signed_with_remaining_accounts(&[], &[]) + } + #[inline(always)] + pub fn invoke_with_remaining_accounts( + &self, + remaining_accounts: &[(&'b solana_account_info::AccountInfo<'a>, bool, bool)], + ) -> solana_program_error::ProgramResult { + self.invoke_signed_with_remaining_accounts(&[], remaining_accounts) + } + #[inline(always)] + pub fn invoke_signed(&self, signers_seeds: &[&[&[u8]]]) -> solana_program_error::ProgramResult { + self.invoke_signed_with_remaining_accounts(signers_seeds, &[]) + } + #[allow(clippy::arithmetic_side_effects)] + #[allow(clippy::clone_on_copy)] + #[allow(clippy::vec_init_then_push)] + pub fn invoke_signed_with_remaining_accounts( + &self, + signers_seeds: &[&[&[u8]]], + remaining_accounts: &[(&'b solana_account_info::AccountInfo<'a>, bool, bool)], + ) -> solana_program_error::ProgramResult { + let mut accounts = Vec::with_capacity(13 + remaining_accounts.len()); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.realm_account.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + *self.governance_account.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + *self.proposal_account.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + *self.proposal_token_owner_record.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + *self.voter_token_owner_record.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.governance_authority.key, + true, + )); + accounts.push(solana_instruction::AccountMeta::new( + *self.proposal_vote_record.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.governing_token_mint.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.payer.key, + true, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.system_program.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.realm_config_account.key, + false, + )); + if let Some(voter_weight_record) = self.voter_weight_record { + accounts.push(solana_instruction::AccountMeta::new_readonly( + *voter_weight_record.key, + false, + )); + } else { + accounts.push(solana_instruction::AccountMeta::new_readonly( + crate::SPL_GOVERNANCE_ID, + false, + )); + } + if let Some(max_voter_weight_record) = self.max_voter_weight_record { + accounts.push(solana_instruction::AccountMeta::new_readonly( + *max_voter_weight_record.key, + false, + )); + } else { + accounts.push(solana_instruction::AccountMeta::new_readonly( + crate::SPL_GOVERNANCE_ID, + false, + )); + } + remaining_accounts.iter().for_each(|remaining_account| { + accounts.push(solana_instruction::AccountMeta { + pubkey: *remaining_account.0.key, + is_signer: remaining_account.1, + is_writable: remaining_account.2, + }) + }); + let mut data = CastVoteInstructionData::new().try_to_vec().unwrap(); + let mut args = self.__args.try_to_vec().unwrap(); + data.append(&mut args); + + let instruction = solana_instruction::Instruction { + program_id: crate::SPL_GOVERNANCE_ID, + accounts, + data, + }; + let mut account_infos = Vec::with_capacity(14 + remaining_accounts.len()); + account_infos.push(self.__program.clone()); + account_infos.push(self.realm_account.clone()); + account_infos.push(self.governance_account.clone()); + account_infos.push(self.proposal_account.clone()); + account_infos.push(self.proposal_token_owner_record.clone()); + account_infos.push(self.voter_token_owner_record.clone()); + account_infos.push(self.governance_authority.clone()); + account_infos.push(self.proposal_vote_record.clone()); + account_infos.push(self.governing_token_mint.clone()); + account_infos.push(self.payer.clone()); + account_infos.push(self.system_program.clone()); + account_infos.push(self.realm_config_account.clone()); + if let Some(voter_weight_record) = self.voter_weight_record { + account_infos.push(voter_weight_record.clone()); + } + if let Some(max_voter_weight_record) = self.max_voter_weight_record { + account_infos.push(max_voter_weight_record.clone()); + } + remaining_accounts + .iter() + .for_each(|remaining_account| account_infos.push(remaining_account.0.clone())); + + if signers_seeds.is_empty() { + solana_cpi::invoke(&instruction, &account_infos) + } else { + solana_cpi::invoke_signed(&instruction, &account_infos, signers_seeds) + } + } +} + +/// Instruction builder for `CastVote` via CPI. +/// +/// ### Accounts: +/// +/// 0. `[]` realm_account +/// 1. `[writable]` governance_account +/// 2. `[writable]` proposal_account +/// 3. `[writable]` proposal_token_owner_record +/// 4. `[writable]` voter_token_owner_record +/// 5. `[signer]` governance_authority +/// 6. `[writable]` proposal_vote_record +/// 7. `[]` governing_token_mint +/// 8. `[signer]` payer +/// 9. `[]` system_program +/// 10. `[]` realm_config_account +/// 11. `[optional]` voter_weight_record +/// 12. `[optional]` max_voter_weight_record +#[derive(Clone, Debug)] +pub struct CastVoteCpiBuilder<'a, 'b> { + instruction: Box>, +} + +impl<'a, 'b> CastVoteCpiBuilder<'a, 'b> { + pub fn new(program: &'b solana_account_info::AccountInfo<'a>) -> Self { + let instruction = Box::new(CastVoteCpiBuilderInstruction { + __program: program, + realm_account: None, + governance_account: None, + proposal_account: None, + proposal_token_owner_record: None, + voter_token_owner_record: None, + governance_authority: None, + proposal_vote_record: None, + governing_token_mint: None, + payer: None, + system_program: None, + realm_config_account: None, + voter_weight_record: None, + max_voter_weight_record: None, + vote: None, + __remaining_accounts: Vec::new(), + }); + Self { instruction } + } + #[inline(always)] + pub fn realm_account( + &mut self, + realm_account: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.realm_account = Some(realm_account); + self + } + #[inline(always)] + pub fn governance_account( + &mut self, + governance_account: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.governance_account = Some(governance_account); + self + } + #[inline(always)] + pub fn proposal_account( + &mut self, + proposal_account: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.proposal_account = Some(proposal_account); + self + } + /// TokenOwnerRecord of the Proposal owner + #[inline(always)] + pub fn proposal_token_owner_record( + &mut self, + proposal_token_owner_record: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.proposal_token_owner_record = Some(proposal_token_owner_record); + self + } + /// TokenOwnerRecord of the voter. PDA seeds: ['governance',realm, vote_governing_token_mint, governing_token_owner] + #[inline(always)] + pub fn voter_token_owner_record( + &mut self, + voter_token_owner_record: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.voter_token_owner_record = Some(voter_token_owner_record); + self + } + /// Governance Authority (Token Owner or Governance Delegate) + #[inline(always)] + pub fn governance_authority( + &mut self, + governance_authority: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.governance_authority = Some(governance_authority); + self + } + /// Proposal VoteRecord account. PDA seeds: ['governance',proposal,token_owner_record] + #[inline(always)] + pub fn proposal_vote_record( + &mut self, + proposal_vote_record: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.proposal_vote_record = Some(proposal_vote_record); + self + } + /// The Governing Token Mint which is used to cast the vote (vote_governing_token_mint). + /// The voting token mint is the governing_token_mint of the Proposal for Approve, Deny and Abstain votes. + /// For Veto vote the voting token mint is the mint of the opposite voting population. + /// Council mint to veto Community proposals and Community mint to veto Council proposals + /// Note: In the current version only Council veto is supported + #[inline(always)] + pub fn governing_token_mint( + &mut self, + governing_token_mint: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.governing_token_mint = Some(governing_token_mint); + self + } + #[inline(always)] + pub fn payer(&mut self, payer: &'b solana_account_info::AccountInfo<'a>) -> &mut Self { + self.instruction.payer = Some(payer); + self + } + #[inline(always)] + pub fn system_program( + &mut self, + system_program: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.system_program = Some(system_program); + self + } + /// RealmConfig account. PDA seeds: ['realm-config', realm] + #[inline(always)] + pub fn realm_config_account( + &mut self, + realm_config_account: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.realm_config_account = Some(realm_config_account); + self + } + /// `[optional account]` + /// Optional Voter Weight Record + #[inline(always)] + pub fn voter_weight_record( + &mut self, + voter_weight_record: Option<&'b solana_account_info::AccountInfo<'a>>, + ) -> &mut Self { + self.instruction.voter_weight_record = voter_weight_record; + self + } + /// `[optional account]` + /// Optional Max Voter Weight Record + #[inline(always)] + pub fn max_voter_weight_record( + &mut self, + max_voter_weight_record: Option<&'b solana_account_info::AccountInfo<'a>>, + ) -> &mut Self { + self.instruction.max_voter_weight_record = max_voter_weight_record; + self + } + #[inline(always)] + pub fn vote(&mut self, vote: Vote) -> &mut Self { + self.instruction.vote = Some(vote); + self + } + /// Add an additional account to the instruction. + #[inline(always)] + pub fn add_remaining_account( + &mut self, + account: &'b solana_account_info::AccountInfo<'a>, + is_writable: bool, + is_signer: bool, + ) -> &mut Self { + self.instruction + .__remaining_accounts + .push((account, is_writable, is_signer)); + self + } + /// Add additional accounts to the instruction. + /// + /// Each account is represented by a tuple of the `AccountInfo`, a `bool` indicating whether the account is writable or not, + /// and a `bool` indicating whether the account is a signer or not. + #[inline(always)] + pub fn add_remaining_accounts( + &mut self, + accounts: &[(&'b solana_account_info::AccountInfo<'a>, bool, bool)], + ) -> &mut Self { + self.instruction + .__remaining_accounts + .extend_from_slice(accounts); + self + } + #[inline(always)] + pub fn invoke(&self) -> solana_program_error::ProgramResult { + self.invoke_signed(&[]) + } + #[allow(clippy::clone_on_copy)] + #[allow(clippy::vec_init_then_push)] + pub fn invoke_signed(&self, signers_seeds: &[&[&[u8]]]) -> solana_program_error::ProgramResult { + let args = CastVoteInstructionArgs { + vote: self.instruction.vote.clone().expect("vote is not set"), + }; + let instruction = CastVoteCpi { + __program: self.instruction.__program, + + realm_account: self + .instruction + .realm_account + .expect("realm_account is not set"), + + governance_account: self + .instruction + .governance_account + .expect("governance_account is not set"), + + proposal_account: self + .instruction + .proposal_account + .expect("proposal_account is not set"), + + proposal_token_owner_record: self + .instruction + .proposal_token_owner_record + .expect("proposal_token_owner_record is not set"), + + voter_token_owner_record: self + .instruction + .voter_token_owner_record + .expect("voter_token_owner_record is not set"), + + governance_authority: self + .instruction + .governance_authority + .expect("governance_authority is not set"), + + proposal_vote_record: self + .instruction + .proposal_vote_record + .expect("proposal_vote_record is not set"), + + governing_token_mint: self + .instruction + .governing_token_mint + .expect("governing_token_mint is not set"), + + payer: self.instruction.payer.expect("payer is not set"), + + system_program: self + .instruction + .system_program + .expect("system_program is not set"), + + realm_config_account: self + .instruction + .realm_config_account + .expect("realm_config_account is not set"), + + voter_weight_record: self.instruction.voter_weight_record, + + max_voter_weight_record: self.instruction.max_voter_weight_record, + __args: args, + }; + instruction.invoke_signed_with_remaining_accounts( + signers_seeds, + &self.instruction.__remaining_accounts, + ) + } +} + +#[derive(Clone, Debug)] +struct CastVoteCpiBuilderInstruction<'a, 'b> { + __program: &'b solana_account_info::AccountInfo<'a>, + realm_account: Option<&'b solana_account_info::AccountInfo<'a>>, + governance_account: Option<&'b solana_account_info::AccountInfo<'a>>, + proposal_account: Option<&'b solana_account_info::AccountInfo<'a>>, + proposal_token_owner_record: Option<&'b solana_account_info::AccountInfo<'a>>, + voter_token_owner_record: Option<&'b solana_account_info::AccountInfo<'a>>, + governance_authority: Option<&'b solana_account_info::AccountInfo<'a>>, + proposal_vote_record: Option<&'b solana_account_info::AccountInfo<'a>>, + governing_token_mint: Option<&'b solana_account_info::AccountInfo<'a>>, + payer: Option<&'b solana_account_info::AccountInfo<'a>>, + system_program: Option<&'b solana_account_info::AccountInfo<'a>>, + realm_config_account: Option<&'b solana_account_info::AccountInfo<'a>>, + voter_weight_record: Option<&'b solana_account_info::AccountInfo<'a>>, + max_voter_weight_record: Option<&'b solana_account_info::AccountInfo<'a>>, + vote: Option, + /// Additional instruction accounts `(AccountInfo, is_writable, is_signer)`. + __remaining_accounts: Vec<(&'b solana_account_info::AccountInfo<'a>, bool, bool)>, +} diff --git a/e2e/governance/src/generated/instructions/complete_proposal.rs b/e2e/governance/src/generated/instructions/complete_proposal.rs new file mode 100644 index 0000000..2410dc2 --- /dev/null +++ b/e2e/governance/src/generated/instructions/complete_proposal.rs @@ -0,0 +1,365 @@ +//! This code was AUTOGENERATED using the codama library. +//! Please DO NOT EDIT THIS FILE, instead use visitors +//! to add features, then rerun codama to update it. +//! +//! +//! + +use borsh::BorshDeserialize; +use borsh::BorshSerialize; + +pub const COMPLETE_PROPOSAL_DISCRIMINATOR: u8 = 28; + +/// Accounts. +#[derive(Debug)] +pub struct CompleteProposal { + pub proposal_account: solana_pubkey::Pubkey, + /// TokenOwnerRecord account of the Proposal owner + pub token_owner_record: solana_pubkey::Pubkey, + /// Token Owner or Delegate + pub complete_proposal_authority: solana_pubkey::Pubkey, +} + +impl CompleteProposal { + pub fn instruction(&self) -> solana_instruction::Instruction { + self.instruction_with_remaining_accounts(&[]) + } + #[allow(clippy::arithmetic_side_effects)] + #[allow(clippy::vec_init_then_push)] + pub fn instruction_with_remaining_accounts( + &self, + remaining_accounts: &[solana_instruction::AccountMeta], + ) -> solana_instruction::Instruction { + let mut accounts = Vec::with_capacity(3 + remaining_accounts.len()); + accounts.push(solana_instruction::AccountMeta::new( + self.proposal_account, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.token_owner_record, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.complete_proposal_authority, + true, + )); + accounts.extend_from_slice(remaining_accounts); + let data = CompleteProposalInstructionData::new().try_to_vec().unwrap(); + + solana_instruction::Instruction { + program_id: crate::SPL_GOVERNANCE_ID, + accounts, + data, + } + } +} + +#[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct CompleteProposalInstructionData { + discriminator: u8, +} + +impl CompleteProposalInstructionData { + pub fn new() -> Self { + Self { discriminator: 28 } + } + + pub(crate) fn try_to_vec(&self) -> Result, std::io::Error> { + borsh::to_vec(self) + } +} + +impl Default for CompleteProposalInstructionData { + fn default() -> Self { + Self::new() + } +} + +/// Instruction builder for `CompleteProposal`. +/// +/// ### Accounts: +/// +/// 0. `[writable]` proposal_account +/// 1. `[]` token_owner_record +/// 2. `[signer]` complete_proposal_authority +#[derive(Clone, Debug, Default)] +pub struct CompleteProposalBuilder { + proposal_account: Option, + token_owner_record: Option, + complete_proposal_authority: Option, + __remaining_accounts: Vec, +} + +impl CompleteProposalBuilder { + pub fn new() -> Self { + Self::default() + } + #[inline(always)] + pub fn proposal_account(&mut self, proposal_account: solana_pubkey::Pubkey) -> &mut Self { + self.proposal_account = Some(proposal_account); + self + } + /// TokenOwnerRecord account of the Proposal owner + #[inline(always)] + pub fn token_owner_record(&mut self, token_owner_record: solana_pubkey::Pubkey) -> &mut Self { + self.token_owner_record = Some(token_owner_record); + self + } + /// Token Owner or Delegate + #[inline(always)] + pub fn complete_proposal_authority( + &mut self, + complete_proposal_authority: solana_pubkey::Pubkey, + ) -> &mut Self { + self.complete_proposal_authority = Some(complete_proposal_authority); + self + } + /// Add an additional account to the instruction. + #[inline(always)] + pub fn add_remaining_account(&mut self, account: solana_instruction::AccountMeta) -> &mut Self { + self.__remaining_accounts.push(account); + self + } + /// Add additional accounts to the instruction. + #[inline(always)] + pub fn add_remaining_accounts( + &mut self, + accounts: &[solana_instruction::AccountMeta], + ) -> &mut Self { + self.__remaining_accounts.extend_from_slice(accounts); + self + } + #[allow(clippy::clone_on_copy)] + pub fn instruction(&self) -> solana_instruction::Instruction { + let accounts = CompleteProposal { + proposal_account: self.proposal_account.expect("proposal_account is not set"), + token_owner_record: self + .token_owner_record + .expect("token_owner_record is not set"), + complete_proposal_authority: self + .complete_proposal_authority + .expect("complete_proposal_authority is not set"), + }; + + accounts.instruction_with_remaining_accounts(&self.__remaining_accounts) + } +} + +/// `complete_proposal` CPI accounts. +pub struct CompleteProposalCpiAccounts<'a, 'b> { + pub proposal_account: &'b solana_account_info::AccountInfo<'a>, + /// TokenOwnerRecord account of the Proposal owner + pub token_owner_record: &'b solana_account_info::AccountInfo<'a>, + /// Token Owner or Delegate + pub complete_proposal_authority: &'b solana_account_info::AccountInfo<'a>, +} + +/// `complete_proposal` CPI instruction. +pub struct CompleteProposalCpi<'a, 'b> { + /// The program to invoke. + pub __program: &'b solana_account_info::AccountInfo<'a>, + + pub proposal_account: &'b solana_account_info::AccountInfo<'a>, + /// TokenOwnerRecord account of the Proposal owner + pub token_owner_record: &'b solana_account_info::AccountInfo<'a>, + /// Token Owner or Delegate + pub complete_proposal_authority: &'b solana_account_info::AccountInfo<'a>, +} + +impl<'a, 'b> CompleteProposalCpi<'a, 'b> { + pub fn new( + program: &'b solana_account_info::AccountInfo<'a>, + accounts: CompleteProposalCpiAccounts<'a, 'b>, + ) -> Self { + Self { + __program: program, + proposal_account: accounts.proposal_account, + token_owner_record: accounts.token_owner_record, + complete_proposal_authority: accounts.complete_proposal_authority, + } + } + #[inline(always)] + pub fn invoke(&self) -> solana_program_error::ProgramResult { + self.invoke_signed_with_remaining_accounts(&[], &[]) + } + #[inline(always)] + pub fn invoke_with_remaining_accounts( + &self, + remaining_accounts: &[(&'b solana_account_info::AccountInfo<'a>, bool, bool)], + ) -> solana_program_error::ProgramResult { + self.invoke_signed_with_remaining_accounts(&[], remaining_accounts) + } + #[inline(always)] + pub fn invoke_signed(&self, signers_seeds: &[&[&[u8]]]) -> solana_program_error::ProgramResult { + self.invoke_signed_with_remaining_accounts(signers_seeds, &[]) + } + #[allow(clippy::arithmetic_side_effects)] + #[allow(clippy::clone_on_copy)] + #[allow(clippy::vec_init_then_push)] + pub fn invoke_signed_with_remaining_accounts( + &self, + signers_seeds: &[&[&[u8]]], + remaining_accounts: &[(&'b solana_account_info::AccountInfo<'a>, bool, bool)], + ) -> solana_program_error::ProgramResult { + let mut accounts = Vec::with_capacity(3 + remaining_accounts.len()); + accounts.push(solana_instruction::AccountMeta::new( + *self.proposal_account.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.token_owner_record.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.complete_proposal_authority.key, + true, + )); + remaining_accounts.iter().for_each(|remaining_account| { + accounts.push(solana_instruction::AccountMeta { + pubkey: *remaining_account.0.key, + is_signer: remaining_account.1, + is_writable: remaining_account.2, + }) + }); + let data = CompleteProposalInstructionData::new().try_to_vec().unwrap(); + + let instruction = solana_instruction::Instruction { + program_id: crate::SPL_GOVERNANCE_ID, + accounts, + data, + }; + let mut account_infos = Vec::with_capacity(4 + remaining_accounts.len()); + account_infos.push(self.__program.clone()); + account_infos.push(self.proposal_account.clone()); + account_infos.push(self.token_owner_record.clone()); + account_infos.push(self.complete_proposal_authority.clone()); + remaining_accounts + .iter() + .for_each(|remaining_account| account_infos.push(remaining_account.0.clone())); + + if signers_seeds.is_empty() { + solana_cpi::invoke(&instruction, &account_infos) + } else { + solana_cpi::invoke_signed(&instruction, &account_infos, signers_seeds) + } + } +} + +/// Instruction builder for `CompleteProposal` via CPI. +/// +/// ### Accounts: +/// +/// 0. `[writable]` proposal_account +/// 1. `[]` token_owner_record +/// 2. `[signer]` complete_proposal_authority +#[derive(Clone, Debug)] +pub struct CompleteProposalCpiBuilder<'a, 'b> { + instruction: Box>, +} + +impl<'a, 'b> CompleteProposalCpiBuilder<'a, 'b> { + pub fn new(program: &'b solana_account_info::AccountInfo<'a>) -> Self { + let instruction = Box::new(CompleteProposalCpiBuilderInstruction { + __program: program, + proposal_account: None, + token_owner_record: None, + complete_proposal_authority: None, + __remaining_accounts: Vec::new(), + }); + Self { instruction } + } + #[inline(always)] + pub fn proposal_account( + &mut self, + proposal_account: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.proposal_account = Some(proposal_account); + self + } + /// TokenOwnerRecord account of the Proposal owner + #[inline(always)] + pub fn token_owner_record( + &mut self, + token_owner_record: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.token_owner_record = Some(token_owner_record); + self + } + /// Token Owner or Delegate + #[inline(always)] + pub fn complete_proposal_authority( + &mut self, + complete_proposal_authority: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.complete_proposal_authority = Some(complete_proposal_authority); + self + } + /// Add an additional account to the instruction. + #[inline(always)] + pub fn add_remaining_account( + &mut self, + account: &'b solana_account_info::AccountInfo<'a>, + is_writable: bool, + is_signer: bool, + ) -> &mut Self { + self.instruction + .__remaining_accounts + .push((account, is_writable, is_signer)); + self + } + /// Add additional accounts to the instruction. + /// + /// Each account is represented by a tuple of the `AccountInfo`, a `bool` indicating whether the account is writable or not, + /// and a `bool` indicating whether the account is a signer or not. + #[inline(always)] + pub fn add_remaining_accounts( + &mut self, + accounts: &[(&'b solana_account_info::AccountInfo<'a>, bool, bool)], + ) -> &mut Self { + self.instruction + .__remaining_accounts + .extend_from_slice(accounts); + self + } + #[inline(always)] + pub fn invoke(&self) -> solana_program_error::ProgramResult { + self.invoke_signed(&[]) + } + #[allow(clippy::clone_on_copy)] + #[allow(clippy::vec_init_then_push)] + pub fn invoke_signed(&self, signers_seeds: &[&[&[u8]]]) -> solana_program_error::ProgramResult { + let instruction = CompleteProposalCpi { + __program: self.instruction.__program, + + proposal_account: self + .instruction + .proposal_account + .expect("proposal_account is not set"), + + token_owner_record: self + .instruction + .token_owner_record + .expect("token_owner_record is not set"), + + complete_proposal_authority: self + .instruction + .complete_proposal_authority + .expect("complete_proposal_authority is not set"), + }; + instruction.invoke_signed_with_remaining_accounts( + signers_seeds, + &self.instruction.__remaining_accounts, + ) + } +} + +#[derive(Clone, Debug)] +struct CompleteProposalCpiBuilderInstruction<'a, 'b> { + __program: &'b solana_account_info::AccountInfo<'a>, + proposal_account: Option<&'b solana_account_info::AccountInfo<'a>>, + token_owner_record: Option<&'b solana_account_info::AccountInfo<'a>>, + complete_proposal_authority: Option<&'b solana_account_info::AccountInfo<'a>>, + /// Additional instruction accounts `(AccountInfo, is_writable, is_signer)`. + __remaining_accounts: Vec<(&'b solana_account_info::AccountInfo<'a>, bool, bool)>, +} diff --git a/e2e/governance/src/generated/instructions/create_governance.rs b/e2e/governance/src/generated/instructions/create_governance.rs new file mode 100644 index 0000000..b9c2767 --- /dev/null +++ b/e2e/governance/src/generated/instructions/create_governance.rs @@ -0,0 +1,689 @@ +//! This code was AUTOGENERATED using the codama library. +//! Please DO NOT EDIT THIS FILE, instead use visitors +//! to add features, then rerun codama to update it. +//! +//! +//! + +use crate::generated::types::GovernanceConfig; +use borsh::BorshDeserialize; +use borsh::BorshSerialize; + +pub const CREATE_GOVERNANCE_DISCRIMINATOR: u8 = 4; + +/// Accounts. +#[derive(Debug)] +pub struct CreateGovernance { + /// Realm account the created governance belongs to + pub realm_account: solana_pubkey::Pubkey, + /// seeds=['account-governance', realm, governed_account] + pub governance_account: solana_pubkey::Pubkey, + /// Account governed by this Governance (governing_account). + /// Note: the account doesn't have to exist and can be used only as a unique identified for the Governance account + pub governed_account: solana_pubkey::Pubkey, + /// Used only if not signed by RealmAuthority + pub governing_token_owner_record: solana_pubkey::Pubkey, + + pub payer: solana_pubkey::Pubkey, + + pub system_program: solana_pubkey::Pubkey, + + pub governance_authority: solana_pubkey::Pubkey, + /// seeds=['realm-config', realm] + pub realm_config_account: solana_pubkey::Pubkey, + /// Optional Voter Weight Record + pub voter_weight_record: Option, +} + +impl CreateGovernance { + pub fn instruction( + &self, + args: CreateGovernanceInstructionArgs, + ) -> solana_instruction::Instruction { + self.instruction_with_remaining_accounts(args, &[]) + } + #[allow(clippy::arithmetic_side_effects)] + #[allow(clippy::vec_init_then_push)] + pub fn instruction_with_remaining_accounts( + &self, + args: CreateGovernanceInstructionArgs, + remaining_accounts: &[solana_instruction::AccountMeta], + ) -> solana_instruction::Instruction { + let mut accounts = Vec::with_capacity(9 + remaining_accounts.len()); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.realm_account, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + self.governance_account, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.governed_account, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.governing_token_owner_record, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.payer, true, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.system_program, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.governance_authority, + true, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.realm_config_account, + false, + )); + if let Some(voter_weight_record) = self.voter_weight_record { + accounts.push(solana_instruction::AccountMeta::new_readonly( + voter_weight_record, + false, + )); + } else { + accounts.push(solana_instruction::AccountMeta::new_readonly( + crate::SPL_GOVERNANCE_ID, + false, + )); + } + accounts.extend_from_slice(remaining_accounts); + let mut data = CreateGovernanceInstructionData::new().try_to_vec().unwrap(); + let mut args = args.try_to_vec().unwrap(); + data.append(&mut args); + + solana_instruction::Instruction { + program_id: crate::SPL_GOVERNANCE_ID, + accounts, + data, + } + } +} + +#[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct CreateGovernanceInstructionData { + discriminator: u8, +} + +impl CreateGovernanceInstructionData { + pub fn new() -> Self { + Self { discriminator: 4 } + } + + pub(crate) fn try_to_vec(&self) -> Result, std::io::Error> { + borsh::to_vec(self) + } +} + +impl Default for CreateGovernanceInstructionData { + fn default() -> Self { + Self::new() + } +} + +#[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct CreateGovernanceInstructionArgs { + pub config: GovernanceConfig, +} + +impl CreateGovernanceInstructionArgs { + pub(crate) fn try_to_vec(&self) -> Result, std::io::Error> { + borsh::to_vec(self) + } +} + +/// Instruction builder for `CreateGovernance`. +/// +/// ### Accounts: +/// +/// 0. `[]` realm_account +/// 1. `[writable]` governance_account +/// 2. `[]` governed_account +/// 3. `[]` governing_token_owner_record +/// 4. `[signer]` payer +/// 5. `[optional]` system_program (default to `11111111111111111111111111111111`) +/// 6. `[signer]` governance_authority +/// 7. `[]` realm_config_account +/// 8. `[optional]` voter_weight_record +#[derive(Clone, Debug, Default)] +pub struct CreateGovernanceBuilder { + realm_account: Option, + governance_account: Option, + governed_account: Option, + governing_token_owner_record: Option, + payer: Option, + system_program: Option, + governance_authority: Option, + realm_config_account: Option, + voter_weight_record: Option, + config: Option, + __remaining_accounts: Vec, +} + +impl CreateGovernanceBuilder { + pub fn new() -> Self { + Self::default() + } + /// Realm account the created governance belongs to + #[inline(always)] + pub fn realm_account(&mut self, realm_account: solana_pubkey::Pubkey) -> &mut Self { + self.realm_account = Some(realm_account); + self + } + /// seeds=['account-governance', realm, governed_account] + #[inline(always)] + pub fn governance_account(&mut self, governance_account: solana_pubkey::Pubkey) -> &mut Self { + self.governance_account = Some(governance_account); + self + } + /// Account governed by this Governance (governing_account). + /// Note: the account doesn't have to exist and can be used only as a unique identified for the Governance account + #[inline(always)] + pub fn governed_account(&mut self, governed_account: solana_pubkey::Pubkey) -> &mut Self { + self.governed_account = Some(governed_account); + self + } + /// Used only if not signed by RealmAuthority + #[inline(always)] + pub fn governing_token_owner_record( + &mut self, + governing_token_owner_record: solana_pubkey::Pubkey, + ) -> &mut Self { + self.governing_token_owner_record = Some(governing_token_owner_record); + self + } + #[inline(always)] + pub fn payer(&mut self, payer: solana_pubkey::Pubkey) -> &mut Self { + self.payer = Some(payer); + self + } + /// `[optional account, default to '11111111111111111111111111111111']` + #[inline(always)] + pub fn system_program(&mut self, system_program: solana_pubkey::Pubkey) -> &mut Self { + self.system_program = Some(system_program); + self + } + #[inline(always)] + pub fn governance_authority( + &mut self, + governance_authority: solana_pubkey::Pubkey, + ) -> &mut Self { + self.governance_authority = Some(governance_authority); + self + } + /// seeds=['realm-config', realm] + #[inline(always)] + pub fn realm_config_account( + &mut self, + realm_config_account: solana_pubkey::Pubkey, + ) -> &mut Self { + self.realm_config_account = Some(realm_config_account); + self + } + /// `[optional account]` + /// Optional Voter Weight Record + #[inline(always)] + pub fn voter_weight_record( + &mut self, + voter_weight_record: Option, + ) -> &mut Self { + self.voter_weight_record = voter_weight_record; + self + } + #[inline(always)] + pub fn config(&mut self, config: GovernanceConfig) -> &mut Self { + self.config = Some(config); + self + } + /// Add an additional account to the instruction. + #[inline(always)] + pub fn add_remaining_account(&mut self, account: solana_instruction::AccountMeta) -> &mut Self { + self.__remaining_accounts.push(account); + self + } + /// Add additional accounts to the instruction. + #[inline(always)] + pub fn add_remaining_accounts( + &mut self, + accounts: &[solana_instruction::AccountMeta], + ) -> &mut Self { + self.__remaining_accounts.extend_from_slice(accounts); + self + } + #[allow(clippy::clone_on_copy)] + pub fn instruction(&self) -> solana_instruction::Instruction { + let accounts = CreateGovernance { + realm_account: self.realm_account.expect("realm_account is not set"), + governance_account: self + .governance_account + .expect("governance_account is not set"), + governed_account: self.governed_account.expect("governed_account is not set"), + governing_token_owner_record: self + .governing_token_owner_record + .expect("governing_token_owner_record is not set"), + payer: self.payer.expect("payer is not set"), + system_program: self + .system_program + .unwrap_or(solana_pubkey::pubkey!("11111111111111111111111111111111")), + governance_authority: self + .governance_authority + .expect("governance_authority is not set"), + realm_config_account: self + .realm_config_account + .expect("realm_config_account is not set"), + voter_weight_record: self.voter_weight_record, + }; + let args = CreateGovernanceInstructionArgs { + config: self.config.clone().expect("config is not set"), + }; + + accounts.instruction_with_remaining_accounts(args, &self.__remaining_accounts) + } +} + +/// `create_governance` CPI accounts. +pub struct CreateGovernanceCpiAccounts<'a, 'b> { + /// Realm account the created governance belongs to + pub realm_account: &'b solana_account_info::AccountInfo<'a>, + /// seeds=['account-governance', realm, governed_account] + pub governance_account: &'b solana_account_info::AccountInfo<'a>, + /// Account governed by this Governance (governing_account). + /// Note: the account doesn't have to exist and can be used only as a unique identified for the Governance account + pub governed_account: &'b solana_account_info::AccountInfo<'a>, + /// Used only if not signed by RealmAuthority + pub governing_token_owner_record: &'b solana_account_info::AccountInfo<'a>, + + pub payer: &'b solana_account_info::AccountInfo<'a>, + + pub system_program: &'b solana_account_info::AccountInfo<'a>, + + pub governance_authority: &'b solana_account_info::AccountInfo<'a>, + /// seeds=['realm-config', realm] + pub realm_config_account: &'b solana_account_info::AccountInfo<'a>, + /// Optional Voter Weight Record + pub voter_weight_record: Option<&'b solana_account_info::AccountInfo<'a>>, +} + +/// `create_governance` CPI instruction. +pub struct CreateGovernanceCpi<'a, 'b> { + /// The program to invoke. + pub __program: &'b solana_account_info::AccountInfo<'a>, + /// Realm account the created governance belongs to + pub realm_account: &'b solana_account_info::AccountInfo<'a>, + /// seeds=['account-governance', realm, governed_account] + pub governance_account: &'b solana_account_info::AccountInfo<'a>, + /// Account governed by this Governance (governing_account). + /// Note: the account doesn't have to exist and can be used only as a unique identified for the Governance account + pub governed_account: &'b solana_account_info::AccountInfo<'a>, + /// Used only if not signed by RealmAuthority + pub governing_token_owner_record: &'b solana_account_info::AccountInfo<'a>, + + pub payer: &'b solana_account_info::AccountInfo<'a>, + + pub system_program: &'b solana_account_info::AccountInfo<'a>, + + pub governance_authority: &'b solana_account_info::AccountInfo<'a>, + /// seeds=['realm-config', realm] + pub realm_config_account: &'b solana_account_info::AccountInfo<'a>, + /// Optional Voter Weight Record + pub voter_weight_record: Option<&'b solana_account_info::AccountInfo<'a>>, + /// The arguments for the instruction. + pub __args: CreateGovernanceInstructionArgs, +} + +impl<'a, 'b> CreateGovernanceCpi<'a, 'b> { + pub fn new( + program: &'b solana_account_info::AccountInfo<'a>, + accounts: CreateGovernanceCpiAccounts<'a, 'b>, + args: CreateGovernanceInstructionArgs, + ) -> Self { + Self { + __program: program, + realm_account: accounts.realm_account, + governance_account: accounts.governance_account, + governed_account: accounts.governed_account, + governing_token_owner_record: accounts.governing_token_owner_record, + payer: accounts.payer, + system_program: accounts.system_program, + governance_authority: accounts.governance_authority, + realm_config_account: accounts.realm_config_account, + voter_weight_record: accounts.voter_weight_record, + __args: args, + } + } + #[inline(always)] + pub fn invoke(&self) -> solana_program_error::ProgramResult { + self.invoke_signed_with_remaining_accounts(&[], &[]) + } + #[inline(always)] + pub fn invoke_with_remaining_accounts( + &self, + remaining_accounts: &[(&'b solana_account_info::AccountInfo<'a>, bool, bool)], + ) -> solana_program_error::ProgramResult { + self.invoke_signed_with_remaining_accounts(&[], remaining_accounts) + } + #[inline(always)] + pub fn invoke_signed(&self, signers_seeds: &[&[&[u8]]]) -> solana_program_error::ProgramResult { + self.invoke_signed_with_remaining_accounts(signers_seeds, &[]) + } + #[allow(clippy::arithmetic_side_effects)] + #[allow(clippy::clone_on_copy)] + #[allow(clippy::vec_init_then_push)] + pub fn invoke_signed_with_remaining_accounts( + &self, + signers_seeds: &[&[&[u8]]], + remaining_accounts: &[(&'b solana_account_info::AccountInfo<'a>, bool, bool)], + ) -> solana_program_error::ProgramResult { + let mut accounts = Vec::with_capacity(9 + remaining_accounts.len()); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.realm_account.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + *self.governance_account.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.governed_account.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.governing_token_owner_record.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.payer.key, + true, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.system_program.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.governance_authority.key, + true, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.realm_config_account.key, + false, + )); + if let Some(voter_weight_record) = self.voter_weight_record { + accounts.push(solana_instruction::AccountMeta::new_readonly( + *voter_weight_record.key, + false, + )); + } else { + accounts.push(solana_instruction::AccountMeta::new_readonly( + crate::SPL_GOVERNANCE_ID, + false, + )); + } + remaining_accounts.iter().for_each(|remaining_account| { + accounts.push(solana_instruction::AccountMeta { + pubkey: *remaining_account.0.key, + is_signer: remaining_account.1, + is_writable: remaining_account.2, + }) + }); + let mut data = CreateGovernanceInstructionData::new().try_to_vec().unwrap(); + let mut args = self.__args.try_to_vec().unwrap(); + data.append(&mut args); + + let instruction = solana_instruction::Instruction { + program_id: crate::SPL_GOVERNANCE_ID, + accounts, + data, + }; + let mut account_infos = Vec::with_capacity(10 + remaining_accounts.len()); + account_infos.push(self.__program.clone()); + account_infos.push(self.realm_account.clone()); + account_infos.push(self.governance_account.clone()); + account_infos.push(self.governed_account.clone()); + account_infos.push(self.governing_token_owner_record.clone()); + account_infos.push(self.payer.clone()); + account_infos.push(self.system_program.clone()); + account_infos.push(self.governance_authority.clone()); + account_infos.push(self.realm_config_account.clone()); + if let Some(voter_weight_record) = self.voter_weight_record { + account_infos.push(voter_weight_record.clone()); + } + remaining_accounts + .iter() + .for_each(|remaining_account| account_infos.push(remaining_account.0.clone())); + + if signers_seeds.is_empty() { + solana_cpi::invoke(&instruction, &account_infos) + } else { + solana_cpi::invoke_signed(&instruction, &account_infos, signers_seeds) + } + } +} + +/// Instruction builder for `CreateGovernance` via CPI. +/// +/// ### Accounts: +/// +/// 0. `[]` realm_account +/// 1. `[writable]` governance_account +/// 2. `[]` governed_account +/// 3. `[]` governing_token_owner_record +/// 4. `[signer]` payer +/// 5. `[]` system_program +/// 6. `[signer]` governance_authority +/// 7. `[]` realm_config_account +/// 8. `[optional]` voter_weight_record +#[derive(Clone, Debug)] +pub struct CreateGovernanceCpiBuilder<'a, 'b> { + instruction: Box>, +} + +impl<'a, 'b> CreateGovernanceCpiBuilder<'a, 'b> { + pub fn new(program: &'b solana_account_info::AccountInfo<'a>) -> Self { + let instruction = Box::new(CreateGovernanceCpiBuilderInstruction { + __program: program, + realm_account: None, + governance_account: None, + governed_account: None, + governing_token_owner_record: None, + payer: None, + system_program: None, + governance_authority: None, + realm_config_account: None, + voter_weight_record: None, + config: None, + __remaining_accounts: Vec::new(), + }); + Self { instruction } + } + /// Realm account the created governance belongs to + #[inline(always)] + pub fn realm_account( + &mut self, + realm_account: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.realm_account = Some(realm_account); + self + } + /// seeds=['account-governance', realm, governed_account] + #[inline(always)] + pub fn governance_account( + &mut self, + governance_account: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.governance_account = Some(governance_account); + self + } + /// Account governed by this Governance (governing_account). + /// Note: the account doesn't have to exist and can be used only as a unique identified for the Governance account + #[inline(always)] + pub fn governed_account( + &mut self, + governed_account: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.governed_account = Some(governed_account); + self + } + /// Used only if not signed by RealmAuthority + #[inline(always)] + pub fn governing_token_owner_record( + &mut self, + governing_token_owner_record: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.governing_token_owner_record = Some(governing_token_owner_record); + self + } + #[inline(always)] + pub fn payer(&mut self, payer: &'b solana_account_info::AccountInfo<'a>) -> &mut Self { + self.instruction.payer = Some(payer); + self + } + #[inline(always)] + pub fn system_program( + &mut self, + system_program: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.system_program = Some(system_program); + self + } + #[inline(always)] + pub fn governance_authority( + &mut self, + governance_authority: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.governance_authority = Some(governance_authority); + self + } + /// seeds=['realm-config', realm] + #[inline(always)] + pub fn realm_config_account( + &mut self, + realm_config_account: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.realm_config_account = Some(realm_config_account); + self + } + /// `[optional account]` + /// Optional Voter Weight Record + #[inline(always)] + pub fn voter_weight_record( + &mut self, + voter_weight_record: Option<&'b solana_account_info::AccountInfo<'a>>, + ) -> &mut Self { + self.instruction.voter_weight_record = voter_weight_record; + self + } + #[inline(always)] + pub fn config(&mut self, config: GovernanceConfig) -> &mut Self { + self.instruction.config = Some(config); + self + } + /// Add an additional account to the instruction. + #[inline(always)] + pub fn add_remaining_account( + &mut self, + account: &'b solana_account_info::AccountInfo<'a>, + is_writable: bool, + is_signer: bool, + ) -> &mut Self { + self.instruction + .__remaining_accounts + .push((account, is_writable, is_signer)); + self + } + /// Add additional accounts to the instruction. + /// + /// Each account is represented by a tuple of the `AccountInfo`, a `bool` indicating whether the account is writable or not, + /// and a `bool` indicating whether the account is a signer or not. + #[inline(always)] + pub fn add_remaining_accounts( + &mut self, + accounts: &[(&'b solana_account_info::AccountInfo<'a>, bool, bool)], + ) -> &mut Self { + self.instruction + .__remaining_accounts + .extend_from_slice(accounts); + self + } + #[inline(always)] + pub fn invoke(&self) -> solana_program_error::ProgramResult { + self.invoke_signed(&[]) + } + #[allow(clippy::clone_on_copy)] + #[allow(clippy::vec_init_then_push)] + pub fn invoke_signed(&self, signers_seeds: &[&[&[u8]]]) -> solana_program_error::ProgramResult { + let args = CreateGovernanceInstructionArgs { + config: self.instruction.config.clone().expect("config is not set"), + }; + let instruction = CreateGovernanceCpi { + __program: self.instruction.__program, + + realm_account: self + .instruction + .realm_account + .expect("realm_account is not set"), + + governance_account: self + .instruction + .governance_account + .expect("governance_account is not set"), + + governed_account: self + .instruction + .governed_account + .expect("governed_account is not set"), + + governing_token_owner_record: self + .instruction + .governing_token_owner_record + .expect("governing_token_owner_record is not set"), + + payer: self.instruction.payer.expect("payer is not set"), + + system_program: self + .instruction + .system_program + .expect("system_program is not set"), + + governance_authority: self + .instruction + .governance_authority + .expect("governance_authority is not set"), + + realm_config_account: self + .instruction + .realm_config_account + .expect("realm_config_account is not set"), + + voter_weight_record: self.instruction.voter_weight_record, + __args: args, + }; + instruction.invoke_signed_with_remaining_accounts( + signers_seeds, + &self.instruction.__remaining_accounts, + ) + } +} + +#[derive(Clone, Debug)] +struct CreateGovernanceCpiBuilderInstruction<'a, 'b> { + __program: &'b solana_account_info::AccountInfo<'a>, + realm_account: Option<&'b solana_account_info::AccountInfo<'a>>, + governance_account: Option<&'b solana_account_info::AccountInfo<'a>>, + governed_account: Option<&'b solana_account_info::AccountInfo<'a>>, + governing_token_owner_record: Option<&'b solana_account_info::AccountInfo<'a>>, + payer: Option<&'b solana_account_info::AccountInfo<'a>>, + system_program: Option<&'b solana_account_info::AccountInfo<'a>>, + governance_authority: Option<&'b solana_account_info::AccountInfo<'a>>, + realm_config_account: Option<&'b solana_account_info::AccountInfo<'a>>, + voter_weight_record: Option<&'b solana_account_info::AccountInfo<'a>>, + config: Option, + /// Additional instruction accounts `(AccountInfo, is_writable, is_signer)`. + __remaining_accounts: Vec<(&'b solana_account_info::AccountInfo<'a>, bool, bool)>, +} diff --git a/e2e/governance/src/generated/instructions/create_mint_governance.rs b/e2e/governance/src/generated/instructions/create_mint_governance.rs new file mode 100644 index 0000000..221ea76 --- /dev/null +++ b/e2e/governance/src/generated/instructions/create_mint_governance.rs @@ -0,0 +1,794 @@ +//! This code was AUTOGENERATED using the codama library. +//! Please DO NOT EDIT THIS FILE, instead use visitors +//! to add features, then rerun codama to update it. +//! +//! +//! + +use crate::generated::types::GovernanceConfig; +use borsh::BorshDeserialize; +use borsh::BorshSerialize; + +pub const CREATE_MINT_GOVERNANCE_DISCRIMINATOR: u8 = 17; + +/// Accounts. +#[derive(Debug)] +pub struct CreateMintGovernance { + /// Realm account the created Governance belongs to + pub realm_account: solana_pubkey::Pubkey, + /// Mint Governance account. seeds=['mint-governance', realm, governed_mint] + pub mint_governance_account: solana_pubkey::Pubkey, + /// Mint governed by this Governance account + pub governed_mint: solana_pubkey::Pubkey, + /// Current Mint authority (MintTokens and optionally FreezeAccount) + pub mint_authority: solana_pubkey::Pubkey, + /// Governing TokenOwnerRecord account (Used only if not signed by RealmAuthority) + pub governing_token_owner_record: solana_pubkey::Pubkey, + + pub payer: solana_pubkey::Pubkey, + + pub token_program: solana_pubkey::Pubkey, + + pub system_program: solana_pubkey::Pubkey, + + pub governance_authority: solana_pubkey::Pubkey, + /// RealmConfig account. seeds=['realm-config', realm] + pub realm_config: solana_pubkey::Pubkey, + /// Optional Voter Weight Record + pub voter_weight_record: Option, +} + +impl CreateMintGovernance { + pub fn instruction( + &self, + args: CreateMintGovernanceInstructionArgs, + ) -> solana_instruction::Instruction { + self.instruction_with_remaining_accounts(args, &[]) + } + #[allow(clippy::arithmetic_side_effects)] + #[allow(clippy::vec_init_then_push)] + pub fn instruction_with_remaining_accounts( + &self, + args: CreateMintGovernanceInstructionArgs, + remaining_accounts: &[solana_instruction::AccountMeta], + ) -> solana_instruction::Instruction { + let mut accounts = Vec::with_capacity(11 + remaining_accounts.len()); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.realm_account, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + self.mint_governance_account, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + self.governed_mint, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.mint_authority, + true, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.governing_token_owner_record, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.payer, true, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.token_program, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.system_program, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.governance_authority, + true, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.realm_config, + false, + )); + if let Some(voter_weight_record) = self.voter_weight_record { + accounts.push(solana_instruction::AccountMeta::new_readonly( + voter_weight_record, + false, + )); + } else { + accounts.push(solana_instruction::AccountMeta::new_readonly( + crate::SPL_GOVERNANCE_ID, + false, + )); + } + accounts.extend_from_slice(remaining_accounts); + let mut data = CreateMintGovernanceInstructionData::new() + .try_to_vec() + .unwrap(); + let mut args = args.try_to_vec().unwrap(); + data.append(&mut args); + + solana_instruction::Instruction { + program_id: crate::SPL_GOVERNANCE_ID, + accounts, + data, + } + } +} + +#[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct CreateMintGovernanceInstructionData { + discriminator: u8, +} + +impl CreateMintGovernanceInstructionData { + pub fn new() -> Self { + Self { discriminator: 17 } + } + + pub(crate) fn try_to_vec(&self) -> Result, std::io::Error> { + borsh::to_vec(self) + } +} + +impl Default for CreateMintGovernanceInstructionData { + fn default() -> Self { + Self::new() + } +} + +#[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct CreateMintGovernanceInstructionArgs { + pub config: GovernanceConfig, + pub transfer_mint_authorities: bool, +} + +impl CreateMintGovernanceInstructionArgs { + pub(crate) fn try_to_vec(&self) -> Result, std::io::Error> { + borsh::to_vec(self) + } +} + +/// Instruction builder for `CreateMintGovernance`. +/// +/// ### Accounts: +/// +/// 0. `[]` realm_account +/// 1. `[writable]` mint_governance_account +/// 2. `[writable]` governed_mint +/// 3. `[signer]` mint_authority +/// 4. `[]` governing_token_owner_record +/// 5. `[signer]` payer +/// 6. `[optional]` token_program (default to `TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA`) +/// 7. `[optional]` system_program (default to `11111111111111111111111111111111`) +/// 8. `[signer]` governance_authority +/// 9. `[]` realm_config +/// 10. `[optional]` voter_weight_record +#[derive(Clone, Debug, Default)] +pub struct CreateMintGovernanceBuilder { + realm_account: Option, + mint_governance_account: Option, + governed_mint: Option, + mint_authority: Option, + governing_token_owner_record: Option, + payer: Option, + token_program: Option, + system_program: Option, + governance_authority: Option, + realm_config: Option, + voter_weight_record: Option, + config: Option, + transfer_mint_authorities: Option, + __remaining_accounts: Vec, +} + +impl CreateMintGovernanceBuilder { + pub fn new() -> Self { + Self::default() + } + /// Realm account the created Governance belongs to + #[inline(always)] + pub fn realm_account(&mut self, realm_account: solana_pubkey::Pubkey) -> &mut Self { + self.realm_account = Some(realm_account); + self + } + /// Mint Governance account. seeds=['mint-governance', realm, governed_mint] + #[inline(always)] + pub fn mint_governance_account( + &mut self, + mint_governance_account: solana_pubkey::Pubkey, + ) -> &mut Self { + self.mint_governance_account = Some(mint_governance_account); + self + } + /// Mint governed by this Governance account + #[inline(always)] + pub fn governed_mint(&mut self, governed_mint: solana_pubkey::Pubkey) -> &mut Self { + self.governed_mint = Some(governed_mint); + self + } + /// Current Mint authority (MintTokens and optionally FreezeAccount) + #[inline(always)] + pub fn mint_authority(&mut self, mint_authority: solana_pubkey::Pubkey) -> &mut Self { + self.mint_authority = Some(mint_authority); + self + } + /// Governing TokenOwnerRecord account (Used only if not signed by RealmAuthority) + #[inline(always)] + pub fn governing_token_owner_record( + &mut self, + governing_token_owner_record: solana_pubkey::Pubkey, + ) -> &mut Self { + self.governing_token_owner_record = Some(governing_token_owner_record); + self + } + #[inline(always)] + pub fn payer(&mut self, payer: solana_pubkey::Pubkey) -> &mut Self { + self.payer = Some(payer); + self + } + /// `[optional account, default to 'TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA']` + #[inline(always)] + pub fn token_program(&mut self, token_program: solana_pubkey::Pubkey) -> &mut Self { + self.token_program = Some(token_program); + self + } + /// `[optional account, default to '11111111111111111111111111111111']` + #[inline(always)] + pub fn system_program(&mut self, system_program: solana_pubkey::Pubkey) -> &mut Self { + self.system_program = Some(system_program); + self + } + #[inline(always)] + pub fn governance_authority( + &mut self, + governance_authority: solana_pubkey::Pubkey, + ) -> &mut Self { + self.governance_authority = Some(governance_authority); + self + } + /// RealmConfig account. seeds=['realm-config', realm] + #[inline(always)] + pub fn realm_config(&mut self, realm_config: solana_pubkey::Pubkey) -> &mut Self { + self.realm_config = Some(realm_config); + self + } + /// `[optional account]` + /// Optional Voter Weight Record + #[inline(always)] + pub fn voter_weight_record( + &mut self, + voter_weight_record: Option, + ) -> &mut Self { + self.voter_weight_record = voter_weight_record; + self + } + #[inline(always)] + pub fn config(&mut self, config: GovernanceConfig) -> &mut Self { + self.config = Some(config); + self + } + #[inline(always)] + pub fn transfer_mint_authorities(&mut self, transfer_mint_authorities: bool) -> &mut Self { + self.transfer_mint_authorities = Some(transfer_mint_authorities); + self + } + /// Add an additional account to the instruction. + #[inline(always)] + pub fn add_remaining_account(&mut self, account: solana_instruction::AccountMeta) -> &mut Self { + self.__remaining_accounts.push(account); + self + } + /// Add additional accounts to the instruction. + #[inline(always)] + pub fn add_remaining_accounts( + &mut self, + accounts: &[solana_instruction::AccountMeta], + ) -> &mut Self { + self.__remaining_accounts.extend_from_slice(accounts); + self + } + #[allow(clippy::clone_on_copy)] + pub fn instruction(&self) -> solana_instruction::Instruction { + let accounts = CreateMintGovernance { + realm_account: self.realm_account.expect("realm_account is not set"), + mint_governance_account: self + .mint_governance_account + .expect("mint_governance_account is not set"), + governed_mint: self.governed_mint.expect("governed_mint is not set"), + mint_authority: self.mint_authority.expect("mint_authority is not set"), + governing_token_owner_record: self + .governing_token_owner_record + .expect("governing_token_owner_record is not set"), + payer: self.payer.expect("payer is not set"), + token_program: self.token_program.unwrap_or(solana_pubkey::pubkey!( + "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA" + )), + system_program: self + .system_program + .unwrap_or(solana_pubkey::pubkey!("11111111111111111111111111111111")), + governance_authority: self + .governance_authority + .expect("governance_authority is not set"), + realm_config: self.realm_config.expect("realm_config is not set"), + voter_weight_record: self.voter_weight_record, + }; + let args = CreateMintGovernanceInstructionArgs { + config: self.config.clone().expect("config is not set"), + transfer_mint_authorities: self + .transfer_mint_authorities + .clone() + .expect("transfer_mint_authorities is not set"), + }; + + accounts.instruction_with_remaining_accounts(args, &self.__remaining_accounts) + } +} + +/// `create_mint_governance` CPI accounts. +pub struct CreateMintGovernanceCpiAccounts<'a, 'b> { + /// Realm account the created Governance belongs to + pub realm_account: &'b solana_account_info::AccountInfo<'a>, + /// Mint Governance account. seeds=['mint-governance', realm, governed_mint] + pub mint_governance_account: &'b solana_account_info::AccountInfo<'a>, + /// Mint governed by this Governance account + pub governed_mint: &'b solana_account_info::AccountInfo<'a>, + /// Current Mint authority (MintTokens and optionally FreezeAccount) + pub mint_authority: &'b solana_account_info::AccountInfo<'a>, + /// Governing TokenOwnerRecord account (Used only if not signed by RealmAuthority) + pub governing_token_owner_record: &'b solana_account_info::AccountInfo<'a>, + + pub payer: &'b solana_account_info::AccountInfo<'a>, + + pub token_program: &'b solana_account_info::AccountInfo<'a>, + + pub system_program: &'b solana_account_info::AccountInfo<'a>, + + pub governance_authority: &'b solana_account_info::AccountInfo<'a>, + /// RealmConfig account. seeds=['realm-config', realm] + pub realm_config: &'b solana_account_info::AccountInfo<'a>, + /// Optional Voter Weight Record + pub voter_weight_record: Option<&'b solana_account_info::AccountInfo<'a>>, +} + +/// `create_mint_governance` CPI instruction. +pub struct CreateMintGovernanceCpi<'a, 'b> { + /// The program to invoke. + pub __program: &'b solana_account_info::AccountInfo<'a>, + /// Realm account the created Governance belongs to + pub realm_account: &'b solana_account_info::AccountInfo<'a>, + /// Mint Governance account. seeds=['mint-governance', realm, governed_mint] + pub mint_governance_account: &'b solana_account_info::AccountInfo<'a>, + /// Mint governed by this Governance account + pub governed_mint: &'b solana_account_info::AccountInfo<'a>, + /// Current Mint authority (MintTokens and optionally FreezeAccount) + pub mint_authority: &'b solana_account_info::AccountInfo<'a>, + /// Governing TokenOwnerRecord account (Used only if not signed by RealmAuthority) + pub governing_token_owner_record: &'b solana_account_info::AccountInfo<'a>, + + pub payer: &'b solana_account_info::AccountInfo<'a>, + + pub token_program: &'b solana_account_info::AccountInfo<'a>, + + pub system_program: &'b solana_account_info::AccountInfo<'a>, + + pub governance_authority: &'b solana_account_info::AccountInfo<'a>, + /// RealmConfig account. seeds=['realm-config', realm] + pub realm_config: &'b solana_account_info::AccountInfo<'a>, + /// Optional Voter Weight Record + pub voter_weight_record: Option<&'b solana_account_info::AccountInfo<'a>>, + /// The arguments for the instruction. + pub __args: CreateMintGovernanceInstructionArgs, +} + +impl<'a, 'b> CreateMintGovernanceCpi<'a, 'b> { + pub fn new( + program: &'b solana_account_info::AccountInfo<'a>, + accounts: CreateMintGovernanceCpiAccounts<'a, 'b>, + args: CreateMintGovernanceInstructionArgs, + ) -> Self { + Self { + __program: program, + realm_account: accounts.realm_account, + mint_governance_account: accounts.mint_governance_account, + governed_mint: accounts.governed_mint, + mint_authority: accounts.mint_authority, + governing_token_owner_record: accounts.governing_token_owner_record, + payer: accounts.payer, + token_program: accounts.token_program, + system_program: accounts.system_program, + governance_authority: accounts.governance_authority, + realm_config: accounts.realm_config, + voter_weight_record: accounts.voter_weight_record, + __args: args, + } + } + #[inline(always)] + pub fn invoke(&self) -> solana_program_error::ProgramResult { + self.invoke_signed_with_remaining_accounts(&[], &[]) + } + #[inline(always)] + pub fn invoke_with_remaining_accounts( + &self, + remaining_accounts: &[(&'b solana_account_info::AccountInfo<'a>, bool, bool)], + ) -> solana_program_error::ProgramResult { + self.invoke_signed_with_remaining_accounts(&[], remaining_accounts) + } + #[inline(always)] + pub fn invoke_signed(&self, signers_seeds: &[&[&[u8]]]) -> solana_program_error::ProgramResult { + self.invoke_signed_with_remaining_accounts(signers_seeds, &[]) + } + #[allow(clippy::arithmetic_side_effects)] + #[allow(clippy::clone_on_copy)] + #[allow(clippy::vec_init_then_push)] + pub fn invoke_signed_with_remaining_accounts( + &self, + signers_seeds: &[&[&[u8]]], + remaining_accounts: &[(&'b solana_account_info::AccountInfo<'a>, bool, bool)], + ) -> solana_program_error::ProgramResult { + let mut accounts = Vec::with_capacity(11 + remaining_accounts.len()); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.realm_account.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + *self.mint_governance_account.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + *self.governed_mint.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.mint_authority.key, + true, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.governing_token_owner_record.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.payer.key, + true, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.token_program.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.system_program.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.governance_authority.key, + true, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.realm_config.key, + false, + )); + if let Some(voter_weight_record) = self.voter_weight_record { + accounts.push(solana_instruction::AccountMeta::new_readonly( + *voter_weight_record.key, + false, + )); + } else { + accounts.push(solana_instruction::AccountMeta::new_readonly( + crate::SPL_GOVERNANCE_ID, + false, + )); + } + remaining_accounts.iter().for_each(|remaining_account| { + accounts.push(solana_instruction::AccountMeta { + pubkey: *remaining_account.0.key, + is_signer: remaining_account.1, + is_writable: remaining_account.2, + }) + }); + let mut data = CreateMintGovernanceInstructionData::new() + .try_to_vec() + .unwrap(); + let mut args = self.__args.try_to_vec().unwrap(); + data.append(&mut args); + + let instruction = solana_instruction::Instruction { + program_id: crate::SPL_GOVERNANCE_ID, + accounts, + data, + }; + let mut account_infos = Vec::with_capacity(12 + remaining_accounts.len()); + account_infos.push(self.__program.clone()); + account_infos.push(self.realm_account.clone()); + account_infos.push(self.mint_governance_account.clone()); + account_infos.push(self.governed_mint.clone()); + account_infos.push(self.mint_authority.clone()); + account_infos.push(self.governing_token_owner_record.clone()); + account_infos.push(self.payer.clone()); + account_infos.push(self.token_program.clone()); + account_infos.push(self.system_program.clone()); + account_infos.push(self.governance_authority.clone()); + account_infos.push(self.realm_config.clone()); + if let Some(voter_weight_record) = self.voter_weight_record { + account_infos.push(voter_weight_record.clone()); + } + remaining_accounts + .iter() + .for_each(|remaining_account| account_infos.push(remaining_account.0.clone())); + + if signers_seeds.is_empty() { + solana_cpi::invoke(&instruction, &account_infos) + } else { + solana_cpi::invoke_signed(&instruction, &account_infos, signers_seeds) + } + } +} + +/// Instruction builder for `CreateMintGovernance` via CPI. +/// +/// ### Accounts: +/// +/// 0. `[]` realm_account +/// 1. `[writable]` mint_governance_account +/// 2. `[writable]` governed_mint +/// 3. `[signer]` mint_authority +/// 4. `[]` governing_token_owner_record +/// 5. `[signer]` payer +/// 6. `[]` token_program +/// 7. `[]` system_program +/// 8. `[signer]` governance_authority +/// 9. `[]` realm_config +/// 10. `[optional]` voter_weight_record +#[derive(Clone, Debug)] +pub struct CreateMintGovernanceCpiBuilder<'a, 'b> { + instruction: Box>, +} + +impl<'a, 'b> CreateMintGovernanceCpiBuilder<'a, 'b> { + pub fn new(program: &'b solana_account_info::AccountInfo<'a>) -> Self { + let instruction = Box::new(CreateMintGovernanceCpiBuilderInstruction { + __program: program, + realm_account: None, + mint_governance_account: None, + governed_mint: None, + mint_authority: None, + governing_token_owner_record: None, + payer: None, + token_program: None, + system_program: None, + governance_authority: None, + realm_config: None, + voter_weight_record: None, + config: None, + transfer_mint_authorities: None, + __remaining_accounts: Vec::new(), + }); + Self { instruction } + } + /// Realm account the created Governance belongs to + #[inline(always)] + pub fn realm_account( + &mut self, + realm_account: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.realm_account = Some(realm_account); + self + } + /// Mint Governance account. seeds=['mint-governance', realm, governed_mint] + #[inline(always)] + pub fn mint_governance_account( + &mut self, + mint_governance_account: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.mint_governance_account = Some(mint_governance_account); + self + } + /// Mint governed by this Governance account + #[inline(always)] + pub fn governed_mint( + &mut self, + governed_mint: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.governed_mint = Some(governed_mint); + self + } + /// Current Mint authority (MintTokens and optionally FreezeAccount) + #[inline(always)] + pub fn mint_authority( + &mut self, + mint_authority: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.mint_authority = Some(mint_authority); + self + } + /// Governing TokenOwnerRecord account (Used only if not signed by RealmAuthority) + #[inline(always)] + pub fn governing_token_owner_record( + &mut self, + governing_token_owner_record: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.governing_token_owner_record = Some(governing_token_owner_record); + self + } + #[inline(always)] + pub fn payer(&mut self, payer: &'b solana_account_info::AccountInfo<'a>) -> &mut Self { + self.instruction.payer = Some(payer); + self + } + #[inline(always)] + pub fn token_program( + &mut self, + token_program: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.token_program = Some(token_program); + self + } + #[inline(always)] + pub fn system_program( + &mut self, + system_program: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.system_program = Some(system_program); + self + } + #[inline(always)] + pub fn governance_authority( + &mut self, + governance_authority: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.governance_authority = Some(governance_authority); + self + } + /// RealmConfig account. seeds=['realm-config', realm] + #[inline(always)] + pub fn realm_config( + &mut self, + realm_config: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.realm_config = Some(realm_config); + self + } + /// `[optional account]` + /// Optional Voter Weight Record + #[inline(always)] + pub fn voter_weight_record( + &mut self, + voter_weight_record: Option<&'b solana_account_info::AccountInfo<'a>>, + ) -> &mut Self { + self.instruction.voter_weight_record = voter_weight_record; + self + } + #[inline(always)] + pub fn config(&mut self, config: GovernanceConfig) -> &mut Self { + self.instruction.config = Some(config); + self + } + #[inline(always)] + pub fn transfer_mint_authorities(&mut self, transfer_mint_authorities: bool) -> &mut Self { + self.instruction.transfer_mint_authorities = Some(transfer_mint_authorities); + self + } + /// Add an additional account to the instruction. + #[inline(always)] + pub fn add_remaining_account( + &mut self, + account: &'b solana_account_info::AccountInfo<'a>, + is_writable: bool, + is_signer: bool, + ) -> &mut Self { + self.instruction + .__remaining_accounts + .push((account, is_writable, is_signer)); + self + } + /// Add additional accounts to the instruction. + /// + /// Each account is represented by a tuple of the `AccountInfo`, a `bool` indicating whether the account is writable or not, + /// and a `bool` indicating whether the account is a signer or not. + #[inline(always)] + pub fn add_remaining_accounts( + &mut self, + accounts: &[(&'b solana_account_info::AccountInfo<'a>, bool, bool)], + ) -> &mut Self { + self.instruction + .__remaining_accounts + .extend_from_slice(accounts); + self + } + #[inline(always)] + pub fn invoke(&self) -> solana_program_error::ProgramResult { + self.invoke_signed(&[]) + } + #[allow(clippy::clone_on_copy)] + #[allow(clippy::vec_init_then_push)] + pub fn invoke_signed(&self, signers_seeds: &[&[&[u8]]]) -> solana_program_error::ProgramResult { + let args = CreateMintGovernanceInstructionArgs { + config: self.instruction.config.clone().expect("config is not set"), + transfer_mint_authorities: self + .instruction + .transfer_mint_authorities + .clone() + .expect("transfer_mint_authorities is not set"), + }; + let instruction = CreateMintGovernanceCpi { + __program: self.instruction.__program, + + realm_account: self + .instruction + .realm_account + .expect("realm_account is not set"), + + mint_governance_account: self + .instruction + .mint_governance_account + .expect("mint_governance_account is not set"), + + governed_mint: self + .instruction + .governed_mint + .expect("governed_mint is not set"), + + mint_authority: self + .instruction + .mint_authority + .expect("mint_authority is not set"), + + governing_token_owner_record: self + .instruction + .governing_token_owner_record + .expect("governing_token_owner_record is not set"), + + payer: self.instruction.payer.expect("payer is not set"), + + token_program: self + .instruction + .token_program + .expect("token_program is not set"), + + system_program: self + .instruction + .system_program + .expect("system_program is not set"), + + governance_authority: self + .instruction + .governance_authority + .expect("governance_authority is not set"), + + realm_config: self + .instruction + .realm_config + .expect("realm_config is not set"), + + voter_weight_record: self.instruction.voter_weight_record, + __args: args, + }; + instruction.invoke_signed_with_remaining_accounts( + signers_seeds, + &self.instruction.__remaining_accounts, + ) + } +} + +#[derive(Clone, Debug)] +struct CreateMintGovernanceCpiBuilderInstruction<'a, 'b> { + __program: &'b solana_account_info::AccountInfo<'a>, + realm_account: Option<&'b solana_account_info::AccountInfo<'a>>, + mint_governance_account: Option<&'b solana_account_info::AccountInfo<'a>>, + governed_mint: Option<&'b solana_account_info::AccountInfo<'a>>, + mint_authority: Option<&'b solana_account_info::AccountInfo<'a>>, + governing_token_owner_record: Option<&'b solana_account_info::AccountInfo<'a>>, + payer: Option<&'b solana_account_info::AccountInfo<'a>>, + token_program: Option<&'b solana_account_info::AccountInfo<'a>>, + system_program: Option<&'b solana_account_info::AccountInfo<'a>>, + governance_authority: Option<&'b solana_account_info::AccountInfo<'a>>, + realm_config: Option<&'b solana_account_info::AccountInfo<'a>>, + voter_weight_record: Option<&'b solana_account_info::AccountInfo<'a>>, + config: Option, + transfer_mint_authorities: Option, + /// Additional instruction accounts `(AccountInfo, is_writable, is_signer)`. + __remaining_accounts: Vec<(&'b solana_account_info::AccountInfo<'a>, bool, bool)>, +} diff --git a/e2e/governance/src/generated/instructions/create_native_treasury.rs b/e2e/governance/src/generated/instructions/create_native_treasury.rs new file mode 100644 index 0000000..35036e8 --- /dev/null +++ b/e2e/governance/src/generated/instructions/create_native_treasury.rs @@ -0,0 +1,407 @@ +//! This code was AUTOGENERATED using the codama library. +//! Please DO NOT EDIT THIS FILE, instead use visitors +//! to add features, then rerun codama to update it. +//! +//! +//! + +use borsh::BorshDeserialize; +use borsh::BorshSerialize; + +pub const CREATE_NATIVE_TREASURY_DISCRIMINATOR: u8 = 25; + +/// Accounts. +#[derive(Debug)] +pub struct CreateNativeTreasury { + /// Governance account the treasury account is for + pub governance_account: solana_pubkey::Pubkey, + /// seeds=['native-treasury', governance] + pub native_treasury_account: solana_pubkey::Pubkey, + + pub payer: solana_pubkey::Pubkey, + + pub system_program: solana_pubkey::Pubkey, +} + +impl CreateNativeTreasury { + pub fn instruction(&self) -> solana_instruction::Instruction { + self.instruction_with_remaining_accounts(&[]) + } + #[allow(clippy::arithmetic_side_effects)] + #[allow(clippy::vec_init_then_push)] + pub fn instruction_with_remaining_accounts( + &self, + remaining_accounts: &[solana_instruction::AccountMeta], + ) -> solana_instruction::Instruction { + let mut accounts = Vec::with_capacity(4 + remaining_accounts.len()); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.governance_account, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + self.native_treasury_account, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.payer, true, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.system_program, + false, + )); + accounts.extend_from_slice(remaining_accounts); + let data = CreateNativeTreasuryInstructionData::new() + .try_to_vec() + .unwrap(); + + solana_instruction::Instruction { + program_id: crate::SPL_GOVERNANCE_ID, + accounts, + data, + } + } +} + +#[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct CreateNativeTreasuryInstructionData { + discriminator: u8, +} + +impl CreateNativeTreasuryInstructionData { + pub fn new() -> Self { + Self { discriminator: 25 } + } + + pub(crate) fn try_to_vec(&self) -> Result, std::io::Error> { + borsh::to_vec(self) + } +} + +impl Default for CreateNativeTreasuryInstructionData { + fn default() -> Self { + Self::new() + } +} + +/// Instruction builder for `CreateNativeTreasury`. +/// +/// ### Accounts: +/// +/// 0. `[]` governance_account +/// 1. `[writable]` native_treasury_account +/// 2. `[signer]` payer +/// 3. `[optional]` system_program (default to `11111111111111111111111111111111`) +#[derive(Clone, Debug, Default)] +pub struct CreateNativeTreasuryBuilder { + governance_account: Option, + native_treasury_account: Option, + payer: Option, + system_program: Option, + __remaining_accounts: Vec, +} + +impl CreateNativeTreasuryBuilder { + pub fn new() -> Self { + Self::default() + } + /// Governance account the treasury account is for + #[inline(always)] + pub fn governance_account(&mut self, governance_account: solana_pubkey::Pubkey) -> &mut Self { + self.governance_account = Some(governance_account); + self + } + /// seeds=['native-treasury', governance] + #[inline(always)] + pub fn native_treasury_account( + &mut self, + native_treasury_account: solana_pubkey::Pubkey, + ) -> &mut Self { + self.native_treasury_account = Some(native_treasury_account); + self + } + #[inline(always)] + pub fn payer(&mut self, payer: solana_pubkey::Pubkey) -> &mut Self { + self.payer = Some(payer); + self + } + /// `[optional account, default to '11111111111111111111111111111111']` + #[inline(always)] + pub fn system_program(&mut self, system_program: solana_pubkey::Pubkey) -> &mut Self { + self.system_program = Some(system_program); + self + } + /// Add an additional account to the instruction. + #[inline(always)] + pub fn add_remaining_account(&mut self, account: solana_instruction::AccountMeta) -> &mut Self { + self.__remaining_accounts.push(account); + self + } + /// Add additional accounts to the instruction. + #[inline(always)] + pub fn add_remaining_accounts( + &mut self, + accounts: &[solana_instruction::AccountMeta], + ) -> &mut Self { + self.__remaining_accounts.extend_from_slice(accounts); + self + } + #[allow(clippy::clone_on_copy)] + pub fn instruction(&self) -> solana_instruction::Instruction { + let accounts = CreateNativeTreasury { + governance_account: self + .governance_account + .expect("governance_account is not set"), + native_treasury_account: self + .native_treasury_account + .expect("native_treasury_account is not set"), + payer: self.payer.expect("payer is not set"), + system_program: self + .system_program + .unwrap_or(solana_pubkey::pubkey!("11111111111111111111111111111111")), + }; + + accounts.instruction_with_remaining_accounts(&self.__remaining_accounts) + } +} + +/// `create_native_treasury` CPI accounts. +pub struct CreateNativeTreasuryCpiAccounts<'a, 'b> { + /// Governance account the treasury account is for + pub governance_account: &'b solana_account_info::AccountInfo<'a>, + /// seeds=['native-treasury', governance] + pub native_treasury_account: &'b solana_account_info::AccountInfo<'a>, + + pub payer: &'b solana_account_info::AccountInfo<'a>, + + pub system_program: &'b solana_account_info::AccountInfo<'a>, +} + +/// `create_native_treasury` CPI instruction. +pub struct CreateNativeTreasuryCpi<'a, 'b> { + /// The program to invoke. + pub __program: &'b solana_account_info::AccountInfo<'a>, + /// Governance account the treasury account is for + pub governance_account: &'b solana_account_info::AccountInfo<'a>, + /// seeds=['native-treasury', governance] + pub native_treasury_account: &'b solana_account_info::AccountInfo<'a>, + + pub payer: &'b solana_account_info::AccountInfo<'a>, + + pub system_program: &'b solana_account_info::AccountInfo<'a>, +} + +impl<'a, 'b> CreateNativeTreasuryCpi<'a, 'b> { + pub fn new( + program: &'b solana_account_info::AccountInfo<'a>, + accounts: CreateNativeTreasuryCpiAccounts<'a, 'b>, + ) -> Self { + Self { + __program: program, + governance_account: accounts.governance_account, + native_treasury_account: accounts.native_treasury_account, + payer: accounts.payer, + system_program: accounts.system_program, + } + } + #[inline(always)] + pub fn invoke(&self) -> solana_program_error::ProgramResult { + self.invoke_signed_with_remaining_accounts(&[], &[]) + } + #[inline(always)] + pub fn invoke_with_remaining_accounts( + &self, + remaining_accounts: &[(&'b solana_account_info::AccountInfo<'a>, bool, bool)], + ) -> solana_program_error::ProgramResult { + self.invoke_signed_with_remaining_accounts(&[], remaining_accounts) + } + #[inline(always)] + pub fn invoke_signed(&self, signers_seeds: &[&[&[u8]]]) -> solana_program_error::ProgramResult { + self.invoke_signed_with_remaining_accounts(signers_seeds, &[]) + } + #[allow(clippy::arithmetic_side_effects)] + #[allow(clippy::clone_on_copy)] + #[allow(clippy::vec_init_then_push)] + pub fn invoke_signed_with_remaining_accounts( + &self, + signers_seeds: &[&[&[u8]]], + remaining_accounts: &[(&'b solana_account_info::AccountInfo<'a>, bool, bool)], + ) -> solana_program_error::ProgramResult { + let mut accounts = Vec::with_capacity(4 + remaining_accounts.len()); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.governance_account.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + *self.native_treasury_account.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.payer.key, + true, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.system_program.key, + false, + )); + remaining_accounts.iter().for_each(|remaining_account| { + accounts.push(solana_instruction::AccountMeta { + pubkey: *remaining_account.0.key, + is_signer: remaining_account.1, + is_writable: remaining_account.2, + }) + }); + let data = CreateNativeTreasuryInstructionData::new() + .try_to_vec() + .unwrap(); + + let instruction = solana_instruction::Instruction { + program_id: crate::SPL_GOVERNANCE_ID, + accounts, + data, + }; + let mut account_infos = Vec::with_capacity(5 + remaining_accounts.len()); + account_infos.push(self.__program.clone()); + account_infos.push(self.governance_account.clone()); + account_infos.push(self.native_treasury_account.clone()); + account_infos.push(self.payer.clone()); + account_infos.push(self.system_program.clone()); + remaining_accounts + .iter() + .for_each(|remaining_account| account_infos.push(remaining_account.0.clone())); + + if signers_seeds.is_empty() { + solana_cpi::invoke(&instruction, &account_infos) + } else { + solana_cpi::invoke_signed(&instruction, &account_infos, signers_seeds) + } + } +} + +/// Instruction builder for `CreateNativeTreasury` via CPI. +/// +/// ### Accounts: +/// +/// 0. `[]` governance_account +/// 1. `[writable]` native_treasury_account +/// 2. `[signer]` payer +/// 3. `[]` system_program +#[derive(Clone, Debug)] +pub struct CreateNativeTreasuryCpiBuilder<'a, 'b> { + instruction: Box>, +} + +impl<'a, 'b> CreateNativeTreasuryCpiBuilder<'a, 'b> { + pub fn new(program: &'b solana_account_info::AccountInfo<'a>) -> Self { + let instruction = Box::new(CreateNativeTreasuryCpiBuilderInstruction { + __program: program, + governance_account: None, + native_treasury_account: None, + payer: None, + system_program: None, + __remaining_accounts: Vec::new(), + }); + Self { instruction } + } + /// Governance account the treasury account is for + #[inline(always)] + pub fn governance_account( + &mut self, + governance_account: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.governance_account = Some(governance_account); + self + } + /// seeds=['native-treasury', governance] + #[inline(always)] + pub fn native_treasury_account( + &mut self, + native_treasury_account: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.native_treasury_account = Some(native_treasury_account); + self + } + #[inline(always)] + pub fn payer(&mut self, payer: &'b solana_account_info::AccountInfo<'a>) -> &mut Self { + self.instruction.payer = Some(payer); + self + } + #[inline(always)] + pub fn system_program( + &mut self, + system_program: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.system_program = Some(system_program); + self + } + /// Add an additional account to the instruction. + #[inline(always)] + pub fn add_remaining_account( + &mut self, + account: &'b solana_account_info::AccountInfo<'a>, + is_writable: bool, + is_signer: bool, + ) -> &mut Self { + self.instruction + .__remaining_accounts + .push((account, is_writable, is_signer)); + self + } + /// Add additional accounts to the instruction. + /// + /// Each account is represented by a tuple of the `AccountInfo`, a `bool` indicating whether the account is writable or not, + /// and a `bool` indicating whether the account is a signer or not. + #[inline(always)] + pub fn add_remaining_accounts( + &mut self, + accounts: &[(&'b solana_account_info::AccountInfo<'a>, bool, bool)], + ) -> &mut Self { + self.instruction + .__remaining_accounts + .extend_from_slice(accounts); + self + } + #[inline(always)] + pub fn invoke(&self) -> solana_program_error::ProgramResult { + self.invoke_signed(&[]) + } + #[allow(clippy::clone_on_copy)] + #[allow(clippy::vec_init_then_push)] + pub fn invoke_signed(&self, signers_seeds: &[&[&[u8]]]) -> solana_program_error::ProgramResult { + let instruction = CreateNativeTreasuryCpi { + __program: self.instruction.__program, + + governance_account: self + .instruction + .governance_account + .expect("governance_account is not set"), + + native_treasury_account: self + .instruction + .native_treasury_account + .expect("native_treasury_account is not set"), + + payer: self.instruction.payer.expect("payer is not set"), + + system_program: self + .instruction + .system_program + .expect("system_program is not set"), + }; + instruction.invoke_signed_with_remaining_accounts( + signers_seeds, + &self.instruction.__remaining_accounts, + ) + } +} + +#[derive(Clone, Debug)] +struct CreateNativeTreasuryCpiBuilderInstruction<'a, 'b> { + __program: &'b solana_account_info::AccountInfo<'a>, + governance_account: Option<&'b solana_account_info::AccountInfo<'a>>, + native_treasury_account: Option<&'b solana_account_info::AccountInfo<'a>>, + payer: Option<&'b solana_account_info::AccountInfo<'a>>, + system_program: Option<&'b solana_account_info::AccountInfo<'a>>, + /// Additional instruction accounts `(AccountInfo, is_writable, is_signer)`. + __remaining_accounts: Vec<(&'b solana_account_info::AccountInfo<'a>, bool, bool)>, +} diff --git a/e2e/governance/src/generated/instructions/create_program_governance.rs b/e2e/governance/src/generated/instructions/create_program_governance.rs new file mode 100644 index 0000000..545e74e --- /dev/null +++ b/e2e/governance/src/generated/instructions/create_program_governance.rs @@ -0,0 +1,845 @@ +//! This code was AUTOGENERATED using the codama library. +//! Please DO NOT EDIT THIS FILE, instead use visitors +//! to add features, then rerun codama to update it. +//! +//! +//! + +use crate::generated::types::GovernanceConfig; +use borsh::BorshDeserialize; +use borsh::BorshSerialize; + +pub const CREATE_PROGRAM_GOVERNANCE_DISCRIMINATOR: u8 = 5; + +/// Accounts. +#[derive(Debug)] +pub struct CreateProgramGovernance { + /// Realm account the created Governance belongs to + pub realm_account: solana_pubkey::Pubkey, + /// Program Governance account. seeds: ['program-governance', realm, governed_program] + pub program_governance_account: solana_pubkey::Pubkey, + /// Program governed by this Governance account + pub governed_program: solana_pubkey::Pubkey, + /// Program Data account of the Program governed by this Governance account + pub program_data: solana_pubkey::Pubkey, + /// Current Upgrade Authority account of the Program governed by this Governance account + pub current_upgrade_authority: solana_pubkey::Pubkey, + /// Governing TokenOwnerRecord account (Used only if not signed by RealmAuthority) + pub governing_token_owner_record: solana_pubkey::Pubkey, + + pub payer: solana_pubkey::Pubkey, + /// bpf_upgradeable_loader_program program + pub bpf_upgradeable_loader_program: solana_pubkey::Pubkey, + + pub system_program: solana_pubkey::Pubkey, + + pub governance_authority: solana_pubkey::Pubkey, + /// RealmConfig account. seeds=['realm-config', realm] + pub realm_config: solana_pubkey::Pubkey, + /// Optional Voter Weight Record + pub voter_weight_record: Option, +} + +impl CreateProgramGovernance { + pub fn instruction( + &self, + args: CreateProgramGovernanceInstructionArgs, + ) -> solana_instruction::Instruction { + self.instruction_with_remaining_accounts(args, &[]) + } + #[allow(clippy::arithmetic_side_effects)] + #[allow(clippy::vec_init_then_push)] + pub fn instruction_with_remaining_accounts( + &self, + args: CreateProgramGovernanceInstructionArgs, + remaining_accounts: &[solana_instruction::AccountMeta], + ) -> solana_instruction::Instruction { + let mut accounts = Vec::with_capacity(12 + remaining_accounts.len()); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.realm_account, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + self.program_governance_account, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.governed_program, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + self.program_data, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.current_upgrade_authority, + true, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.governing_token_owner_record, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.payer, true, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.bpf_upgradeable_loader_program, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.system_program, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.governance_authority, + true, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.realm_config, + false, + )); + if let Some(voter_weight_record) = self.voter_weight_record { + accounts.push(solana_instruction::AccountMeta::new_readonly( + voter_weight_record, + false, + )); + } else { + accounts.push(solana_instruction::AccountMeta::new_readonly( + crate::SPL_GOVERNANCE_ID, + false, + )); + } + accounts.extend_from_slice(remaining_accounts); + let mut data = CreateProgramGovernanceInstructionData::new() + .try_to_vec() + .unwrap(); + let mut args = args.try_to_vec().unwrap(); + data.append(&mut args); + + solana_instruction::Instruction { + program_id: crate::SPL_GOVERNANCE_ID, + accounts, + data, + } + } +} + +#[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct CreateProgramGovernanceInstructionData { + discriminator: u8, +} + +impl CreateProgramGovernanceInstructionData { + pub fn new() -> Self { + Self { discriminator: 5 } + } + + pub(crate) fn try_to_vec(&self) -> Result, std::io::Error> { + borsh::to_vec(self) + } +} + +impl Default for CreateProgramGovernanceInstructionData { + fn default() -> Self { + Self::new() + } +} + +#[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct CreateProgramGovernanceInstructionArgs { + pub config: GovernanceConfig, + pub transfer_upgrade_authority: bool, +} + +impl CreateProgramGovernanceInstructionArgs { + pub(crate) fn try_to_vec(&self) -> Result, std::io::Error> { + borsh::to_vec(self) + } +} + +/// Instruction builder for `CreateProgramGovernance`. +/// +/// ### Accounts: +/// +/// 0. `[]` realm_account +/// 1. `[writable]` program_governance_account +/// 2. `[]` governed_program +/// 3. `[writable]` program_data +/// 4. `[signer]` current_upgrade_authority +/// 5. `[]` governing_token_owner_record +/// 6. `[signer]` payer +/// 7. `[]` bpf_upgradeable_loader_program +/// 8. `[optional]` system_program (default to `11111111111111111111111111111111`) +/// 9. `[signer]` governance_authority +/// 10. `[]` realm_config +/// 11. `[optional]` voter_weight_record +#[derive(Clone, Debug, Default)] +pub struct CreateProgramGovernanceBuilder { + realm_account: Option, + program_governance_account: Option, + governed_program: Option, + program_data: Option, + current_upgrade_authority: Option, + governing_token_owner_record: Option, + payer: Option, + bpf_upgradeable_loader_program: Option, + system_program: Option, + governance_authority: Option, + realm_config: Option, + voter_weight_record: Option, + config: Option, + transfer_upgrade_authority: Option, + __remaining_accounts: Vec, +} + +impl CreateProgramGovernanceBuilder { + pub fn new() -> Self { + Self::default() + } + /// Realm account the created Governance belongs to + #[inline(always)] + pub fn realm_account(&mut self, realm_account: solana_pubkey::Pubkey) -> &mut Self { + self.realm_account = Some(realm_account); + self + } + /// Program Governance account. seeds: ['program-governance', realm, governed_program] + #[inline(always)] + pub fn program_governance_account( + &mut self, + program_governance_account: solana_pubkey::Pubkey, + ) -> &mut Self { + self.program_governance_account = Some(program_governance_account); + self + } + /// Program governed by this Governance account + #[inline(always)] + pub fn governed_program(&mut self, governed_program: solana_pubkey::Pubkey) -> &mut Self { + self.governed_program = Some(governed_program); + self + } + /// Program Data account of the Program governed by this Governance account + #[inline(always)] + pub fn program_data(&mut self, program_data: solana_pubkey::Pubkey) -> &mut Self { + self.program_data = Some(program_data); + self + } + /// Current Upgrade Authority account of the Program governed by this Governance account + #[inline(always)] + pub fn current_upgrade_authority( + &mut self, + current_upgrade_authority: solana_pubkey::Pubkey, + ) -> &mut Self { + self.current_upgrade_authority = Some(current_upgrade_authority); + self + } + /// Governing TokenOwnerRecord account (Used only if not signed by RealmAuthority) + #[inline(always)] + pub fn governing_token_owner_record( + &mut self, + governing_token_owner_record: solana_pubkey::Pubkey, + ) -> &mut Self { + self.governing_token_owner_record = Some(governing_token_owner_record); + self + } + #[inline(always)] + pub fn payer(&mut self, payer: solana_pubkey::Pubkey) -> &mut Self { + self.payer = Some(payer); + self + } + /// bpf_upgradeable_loader_program program + #[inline(always)] + pub fn bpf_upgradeable_loader_program( + &mut self, + bpf_upgradeable_loader_program: solana_pubkey::Pubkey, + ) -> &mut Self { + self.bpf_upgradeable_loader_program = Some(bpf_upgradeable_loader_program); + self + } + /// `[optional account, default to '11111111111111111111111111111111']` + #[inline(always)] + pub fn system_program(&mut self, system_program: solana_pubkey::Pubkey) -> &mut Self { + self.system_program = Some(system_program); + self + } + #[inline(always)] + pub fn governance_authority( + &mut self, + governance_authority: solana_pubkey::Pubkey, + ) -> &mut Self { + self.governance_authority = Some(governance_authority); + self + } + /// RealmConfig account. seeds=['realm-config', realm] + #[inline(always)] + pub fn realm_config(&mut self, realm_config: solana_pubkey::Pubkey) -> &mut Self { + self.realm_config = Some(realm_config); + self + } + /// `[optional account]` + /// Optional Voter Weight Record + #[inline(always)] + pub fn voter_weight_record( + &mut self, + voter_weight_record: Option, + ) -> &mut Self { + self.voter_weight_record = voter_weight_record; + self + } + #[inline(always)] + pub fn config(&mut self, config: GovernanceConfig) -> &mut Self { + self.config = Some(config); + self + } + #[inline(always)] + pub fn transfer_upgrade_authority(&mut self, transfer_upgrade_authority: bool) -> &mut Self { + self.transfer_upgrade_authority = Some(transfer_upgrade_authority); + self + } + /// Add an additional account to the instruction. + #[inline(always)] + pub fn add_remaining_account(&mut self, account: solana_instruction::AccountMeta) -> &mut Self { + self.__remaining_accounts.push(account); + self + } + /// Add additional accounts to the instruction. + #[inline(always)] + pub fn add_remaining_accounts( + &mut self, + accounts: &[solana_instruction::AccountMeta], + ) -> &mut Self { + self.__remaining_accounts.extend_from_slice(accounts); + self + } + #[allow(clippy::clone_on_copy)] + pub fn instruction(&self) -> solana_instruction::Instruction { + let accounts = CreateProgramGovernance { + realm_account: self.realm_account.expect("realm_account is not set"), + program_governance_account: self + .program_governance_account + .expect("program_governance_account is not set"), + governed_program: self.governed_program.expect("governed_program is not set"), + program_data: self.program_data.expect("program_data is not set"), + current_upgrade_authority: self + .current_upgrade_authority + .expect("current_upgrade_authority is not set"), + governing_token_owner_record: self + .governing_token_owner_record + .expect("governing_token_owner_record is not set"), + payer: self.payer.expect("payer is not set"), + bpf_upgradeable_loader_program: self + .bpf_upgradeable_loader_program + .expect("bpf_upgradeable_loader_program is not set"), + system_program: self + .system_program + .unwrap_or(solana_pubkey::pubkey!("11111111111111111111111111111111")), + governance_authority: self + .governance_authority + .expect("governance_authority is not set"), + realm_config: self.realm_config.expect("realm_config is not set"), + voter_weight_record: self.voter_weight_record, + }; + let args = CreateProgramGovernanceInstructionArgs { + config: self.config.clone().expect("config is not set"), + transfer_upgrade_authority: self + .transfer_upgrade_authority + .clone() + .expect("transfer_upgrade_authority is not set"), + }; + + accounts.instruction_with_remaining_accounts(args, &self.__remaining_accounts) + } +} + +/// `create_program_governance` CPI accounts. +pub struct CreateProgramGovernanceCpiAccounts<'a, 'b> { + /// Realm account the created Governance belongs to + pub realm_account: &'b solana_account_info::AccountInfo<'a>, + /// Program Governance account. seeds: ['program-governance', realm, governed_program] + pub program_governance_account: &'b solana_account_info::AccountInfo<'a>, + /// Program governed by this Governance account + pub governed_program: &'b solana_account_info::AccountInfo<'a>, + /// Program Data account of the Program governed by this Governance account + pub program_data: &'b solana_account_info::AccountInfo<'a>, + /// Current Upgrade Authority account of the Program governed by this Governance account + pub current_upgrade_authority: &'b solana_account_info::AccountInfo<'a>, + /// Governing TokenOwnerRecord account (Used only if not signed by RealmAuthority) + pub governing_token_owner_record: &'b solana_account_info::AccountInfo<'a>, + + pub payer: &'b solana_account_info::AccountInfo<'a>, + /// bpf_upgradeable_loader_program program + pub bpf_upgradeable_loader_program: &'b solana_account_info::AccountInfo<'a>, + + pub system_program: &'b solana_account_info::AccountInfo<'a>, + + pub governance_authority: &'b solana_account_info::AccountInfo<'a>, + /// RealmConfig account. seeds=['realm-config', realm] + pub realm_config: &'b solana_account_info::AccountInfo<'a>, + /// Optional Voter Weight Record + pub voter_weight_record: Option<&'b solana_account_info::AccountInfo<'a>>, +} + +/// `create_program_governance` CPI instruction. +pub struct CreateProgramGovernanceCpi<'a, 'b> { + /// The program to invoke. + pub __program: &'b solana_account_info::AccountInfo<'a>, + /// Realm account the created Governance belongs to + pub realm_account: &'b solana_account_info::AccountInfo<'a>, + /// Program Governance account. seeds: ['program-governance', realm, governed_program] + pub program_governance_account: &'b solana_account_info::AccountInfo<'a>, + /// Program governed by this Governance account + pub governed_program: &'b solana_account_info::AccountInfo<'a>, + /// Program Data account of the Program governed by this Governance account + pub program_data: &'b solana_account_info::AccountInfo<'a>, + /// Current Upgrade Authority account of the Program governed by this Governance account + pub current_upgrade_authority: &'b solana_account_info::AccountInfo<'a>, + /// Governing TokenOwnerRecord account (Used only if not signed by RealmAuthority) + pub governing_token_owner_record: &'b solana_account_info::AccountInfo<'a>, + + pub payer: &'b solana_account_info::AccountInfo<'a>, + /// bpf_upgradeable_loader_program program + pub bpf_upgradeable_loader_program: &'b solana_account_info::AccountInfo<'a>, + + pub system_program: &'b solana_account_info::AccountInfo<'a>, + + pub governance_authority: &'b solana_account_info::AccountInfo<'a>, + /// RealmConfig account. seeds=['realm-config', realm] + pub realm_config: &'b solana_account_info::AccountInfo<'a>, + /// Optional Voter Weight Record + pub voter_weight_record: Option<&'b solana_account_info::AccountInfo<'a>>, + /// The arguments for the instruction. + pub __args: CreateProgramGovernanceInstructionArgs, +} + +impl<'a, 'b> CreateProgramGovernanceCpi<'a, 'b> { + pub fn new( + program: &'b solana_account_info::AccountInfo<'a>, + accounts: CreateProgramGovernanceCpiAccounts<'a, 'b>, + args: CreateProgramGovernanceInstructionArgs, + ) -> Self { + Self { + __program: program, + realm_account: accounts.realm_account, + program_governance_account: accounts.program_governance_account, + governed_program: accounts.governed_program, + program_data: accounts.program_data, + current_upgrade_authority: accounts.current_upgrade_authority, + governing_token_owner_record: accounts.governing_token_owner_record, + payer: accounts.payer, + bpf_upgradeable_loader_program: accounts.bpf_upgradeable_loader_program, + system_program: accounts.system_program, + governance_authority: accounts.governance_authority, + realm_config: accounts.realm_config, + voter_weight_record: accounts.voter_weight_record, + __args: args, + } + } + #[inline(always)] + pub fn invoke(&self) -> solana_program_error::ProgramResult { + self.invoke_signed_with_remaining_accounts(&[], &[]) + } + #[inline(always)] + pub fn invoke_with_remaining_accounts( + &self, + remaining_accounts: &[(&'b solana_account_info::AccountInfo<'a>, bool, bool)], + ) -> solana_program_error::ProgramResult { + self.invoke_signed_with_remaining_accounts(&[], remaining_accounts) + } + #[inline(always)] + pub fn invoke_signed(&self, signers_seeds: &[&[&[u8]]]) -> solana_program_error::ProgramResult { + self.invoke_signed_with_remaining_accounts(signers_seeds, &[]) + } + #[allow(clippy::arithmetic_side_effects)] + #[allow(clippy::clone_on_copy)] + #[allow(clippy::vec_init_then_push)] + pub fn invoke_signed_with_remaining_accounts( + &self, + signers_seeds: &[&[&[u8]]], + remaining_accounts: &[(&'b solana_account_info::AccountInfo<'a>, bool, bool)], + ) -> solana_program_error::ProgramResult { + let mut accounts = Vec::with_capacity(12 + remaining_accounts.len()); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.realm_account.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + *self.program_governance_account.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.governed_program.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + *self.program_data.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.current_upgrade_authority.key, + true, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.governing_token_owner_record.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.payer.key, + true, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.bpf_upgradeable_loader_program.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.system_program.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.governance_authority.key, + true, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.realm_config.key, + false, + )); + if let Some(voter_weight_record) = self.voter_weight_record { + accounts.push(solana_instruction::AccountMeta::new_readonly( + *voter_weight_record.key, + false, + )); + } else { + accounts.push(solana_instruction::AccountMeta::new_readonly( + crate::SPL_GOVERNANCE_ID, + false, + )); + } + remaining_accounts.iter().for_each(|remaining_account| { + accounts.push(solana_instruction::AccountMeta { + pubkey: *remaining_account.0.key, + is_signer: remaining_account.1, + is_writable: remaining_account.2, + }) + }); + let mut data = CreateProgramGovernanceInstructionData::new() + .try_to_vec() + .unwrap(); + let mut args = self.__args.try_to_vec().unwrap(); + data.append(&mut args); + + let instruction = solana_instruction::Instruction { + program_id: crate::SPL_GOVERNANCE_ID, + accounts, + data, + }; + let mut account_infos = Vec::with_capacity(13 + remaining_accounts.len()); + account_infos.push(self.__program.clone()); + account_infos.push(self.realm_account.clone()); + account_infos.push(self.program_governance_account.clone()); + account_infos.push(self.governed_program.clone()); + account_infos.push(self.program_data.clone()); + account_infos.push(self.current_upgrade_authority.clone()); + account_infos.push(self.governing_token_owner_record.clone()); + account_infos.push(self.payer.clone()); + account_infos.push(self.bpf_upgradeable_loader_program.clone()); + account_infos.push(self.system_program.clone()); + account_infos.push(self.governance_authority.clone()); + account_infos.push(self.realm_config.clone()); + if let Some(voter_weight_record) = self.voter_weight_record { + account_infos.push(voter_weight_record.clone()); + } + remaining_accounts + .iter() + .for_each(|remaining_account| account_infos.push(remaining_account.0.clone())); + + if signers_seeds.is_empty() { + solana_cpi::invoke(&instruction, &account_infos) + } else { + solana_cpi::invoke_signed(&instruction, &account_infos, signers_seeds) + } + } +} + +/// Instruction builder for `CreateProgramGovernance` via CPI. +/// +/// ### Accounts: +/// +/// 0. `[]` realm_account +/// 1. `[writable]` program_governance_account +/// 2. `[]` governed_program +/// 3. `[writable]` program_data +/// 4. `[signer]` current_upgrade_authority +/// 5. `[]` governing_token_owner_record +/// 6. `[signer]` payer +/// 7. `[]` bpf_upgradeable_loader_program +/// 8. `[]` system_program +/// 9. `[signer]` governance_authority +/// 10. `[]` realm_config +/// 11. `[optional]` voter_weight_record +#[derive(Clone, Debug)] +pub struct CreateProgramGovernanceCpiBuilder<'a, 'b> { + instruction: Box>, +} + +impl<'a, 'b> CreateProgramGovernanceCpiBuilder<'a, 'b> { + pub fn new(program: &'b solana_account_info::AccountInfo<'a>) -> Self { + let instruction = Box::new(CreateProgramGovernanceCpiBuilderInstruction { + __program: program, + realm_account: None, + program_governance_account: None, + governed_program: None, + program_data: None, + current_upgrade_authority: None, + governing_token_owner_record: None, + payer: None, + bpf_upgradeable_loader_program: None, + system_program: None, + governance_authority: None, + realm_config: None, + voter_weight_record: None, + config: None, + transfer_upgrade_authority: None, + __remaining_accounts: Vec::new(), + }); + Self { instruction } + } + /// Realm account the created Governance belongs to + #[inline(always)] + pub fn realm_account( + &mut self, + realm_account: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.realm_account = Some(realm_account); + self + } + /// Program Governance account. seeds: ['program-governance', realm, governed_program] + #[inline(always)] + pub fn program_governance_account( + &mut self, + program_governance_account: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.program_governance_account = Some(program_governance_account); + self + } + /// Program governed by this Governance account + #[inline(always)] + pub fn governed_program( + &mut self, + governed_program: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.governed_program = Some(governed_program); + self + } + /// Program Data account of the Program governed by this Governance account + #[inline(always)] + pub fn program_data( + &mut self, + program_data: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.program_data = Some(program_data); + self + } + /// Current Upgrade Authority account of the Program governed by this Governance account + #[inline(always)] + pub fn current_upgrade_authority( + &mut self, + current_upgrade_authority: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.current_upgrade_authority = Some(current_upgrade_authority); + self + } + /// Governing TokenOwnerRecord account (Used only if not signed by RealmAuthority) + #[inline(always)] + pub fn governing_token_owner_record( + &mut self, + governing_token_owner_record: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.governing_token_owner_record = Some(governing_token_owner_record); + self + } + #[inline(always)] + pub fn payer(&mut self, payer: &'b solana_account_info::AccountInfo<'a>) -> &mut Self { + self.instruction.payer = Some(payer); + self + } + /// bpf_upgradeable_loader_program program + #[inline(always)] + pub fn bpf_upgradeable_loader_program( + &mut self, + bpf_upgradeable_loader_program: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.bpf_upgradeable_loader_program = Some(bpf_upgradeable_loader_program); + self + } + #[inline(always)] + pub fn system_program( + &mut self, + system_program: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.system_program = Some(system_program); + self + } + #[inline(always)] + pub fn governance_authority( + &mut self, + governance_authority: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.governance_authority = Some(governance_authority); + self + } + /// RealmConfig account. seeds=['realm-config', realm] + #[inline(always)] + pub fn realm_config( + &mut self, + realm_config: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.realm_config = Some(realm_config); + self + } + /// `[optional account]` + /// Optional Voter Weight Record + #[inline(always)] + pub fn voter_weight_record( + &mut self, + voter_weight_record: Option<&'b solana_account_info::AccountInfo<'a>>, + ) -> &mut Self { + self.instruction.voter_weight_record = voter_weight_record; + self + } + #[inline(always)] + pub fn config(&mut self, config: GovernanceConfig) -> &mut Self { + self.instruction.config = Some(config); + self + } + #[inline(always)] + pub fn transfer_upgrade_authority(&mut self, transfer_upgrade_authority: bool) -> &mut Self { + self.instruction.transfer_upgrade_authority = Some(transfer_upgrade_authority); + self + } + /// Add an additional account to the instruction. + #[inline(always)] + pub fn add_remaining_account( + &mut self, + account: &'b solana_account_info::AccountInfo<'a>, + is_writable: bool, + is_signer: bool, + ) -> &mut Self { + self.instruction + .__remaining_accounts + .push((account, is_writable, is_signer)); + self + } + /// Add additional accounts to the instruction. + /// + /// Each account is represented by a tuple of the `AccountInfo`, a `bool` indicating whether the account is writable or not, + /// and a `bool` indicating whether the account is a signer or not. + #[inline(always)] + pub fn add_remaining_accounts( + &mut self, + accounts: &[(&'b solana_account_info::AccountInfo<'a>, bool, bool)], + ) -> &mut Self { + self.instruction + .__remaining_accounts + .extend_from_slice(accounts); + self + } + #[inline(always)] + pub fn invoke(&self) -> solana_program_error::ProgramResult { + self.invoke_signed(&[]) + } + #[allow(clippy::clone_on_copy)] + #[allow(clippy::vec_init_then_push)] + pub fn invoke_signed(&self, signers_seeds: &[&[&[u8]]]) -> solana_program_error::ProgramResult { + let args = CreateProgramGovernanceInstructionArgs { + config: self.instruction.config.clone().expect("config is not set"), + transfer_upgrade_authority: self + .instruction + .transfer_upgrade_authority + .clone() + .expect("transfer_upgrade_authority is not set"), + }; + let instruction = CreateProgramGovernanceCpi { + __program: self.instruction.__program, + + realm_account: self + .instruction + .realm_account + .expect("realm_account is not set"), + + program_governance_account: self + .instruction + .program_governance_account + .expect("program_governance_account is not set"), + + governed_program: self + .instruction + .governed_program + .expect("governed_program is not set"), + + program_data: self + .instruction + .program_data + .expect("program_data is not set"), + + current_upgrade_authority: self + .instruction + .current_upgrade_authority + .expect("current_upgrade_authority is not set"), + + governing_token_owner_record: self + .instruction + .governing_token_owner_record + .expect("governing_token_owner_record is not set"), + + payer: self.instruction.payer.expect("payer is not set"), + + bpf_upgradeable_loader_program: self + .instruction + .bpf_upgradeable_loader_program + .expect("bpf_upgradeable_loader_program is not set"), + + system_program: self + .instruction + .system_program + .expect("system_program is not set"), + + governance_authority: self + .instruction + .governance_authority + .expect("governance_authority is not set"), + + realm_config: self + .instruction + .realm_config + .expect("realm_config is not set"), + + voter_weight_record: self.instruction.voter_weight_record, + __args: args, + }; + instruction.invoke_signed_with_remaining_accounts( + signers_seeds, + &self.instruction.__remaining_accounts, + ) + } +} + +#[derive(Clone, Debug)] +struct CreateProgramGovernanceCpiBuilderInstruction<'a, 'b> { + __program: &'b solana_account_info::AccountInfo<'a>, + realm_account: Option<&'b solana_account_info::AccountInfo<'a>>, + program_governance_account: Option<&'b solana_account_info::AccountInfo<'a>>, + governed_program: Option<&'b solana_account_info::AccountInfo<'a>>, + program_data: Option<&'b solana_account_info::AccountInfo<'a>>, + current_upgrade_authority: Option<&'b solana_account_info::AccountInfo<'a>>, + governing_token_owner_record: Option<&'b solana_account_info::AccountInfo<'a>>, + payer: Option<&'b solana_account_info::AccountInfo<'a>>, + bpf_upgradeable_loader_program: Option<&'b solana_account_info::AccountInfo<'a>>, + system_program: Option<&'b solana_account_info::AccountInfo<'a>>, + governance_authority: Option<&'b solana_account_info::AccountInfo<'a>>, + realm_config: Option<&'b solana_account_info::AccountInfo<'a>>, + voter_weight_record: Option<&'b solana_account_info::AccountInfo<'a>>, + config: Option, + transfer_upgrade_authority: Option, + /// Additional instruction accounts `(AccountInfo, is_writable, is_signer)`. + __remaining_accounts: Vec<(&'b solana_account_info::AccountInfo<'a>, bool, bool)>, +} diff --git a/e2e/governance/src/generated/instructions/create_proposal.rs b/e2e/governance/src/generated/instructions/create_proposal.rs new file mode 100644 index 0000000..02d16d8 --- /dev/null +++ b/e2e/governance/src/generated/instructions/create_proposal.rs @@ -0,0 +1,905 @@ +//! This code was AUTOGENERATED using the codama library. +//! Please DO NOT EDIT THIS FILE, instead use visitors +//! to add features, then rerun codama to update it. +//! +//! +//! + +use crate::generated::types::VoteType; +use borsh::BorshDeserialize; +use borsh::BorshSerialize; +use solana_pubkey::Pubkey; + +pub const CREATE_PROPOSAL_DISCRIMINATOR: u8 = 6; + +/// Accounts. +#[derive(Debug)] +pub struct CreateProposal { + /// Realm account the created Proposal belongs to + pub realm_account: solana_pubkey::Pubkey, + /// Proposal account. PDA seeds ['governance',governance, governing_token_mint, proposal_index] + pub proposal_account: solana_pubkey::Pubkey, + /// Governance account + pub governance_account: solana_pubkey::Pubkey, + /// TokenOwnerRecord account of the Proposal owner + pub token_owner_record: solana_pubkey::Pubkey, + /// Token Mint the Proposal is created for + pub governing_token_mint: solana_pubkey::Pubkey, + /// Governance Authority (Token Owner or Governance Delegate) + pub governance_authority: solana_pubkey::Pubkey, + + pub payer: solana_pubkey::Pubkey, + + pub system_program: solana_pubkey::Pubkey, + /// RealmConfig account. PDA seeds: ['realm-config', realm] + pub realm_config: solana_pubkey::Pubkey, + /// Optional Voter Weight Record + pub voter_weight_record: Option, + /// Optional Proposal deposit is required when there are more active + /// proposals than the configured deposit exempt amount. + /// PDA seeds: ['proposal-deposit', proposal, deposit payer] + pub proposal_deposit_account: Option, +} + +impl CreateProposal { + pub fn instruction( + &self, + args: CreateProposalInstructionArgs, + ) -> solana_instruction::Instruction { + self.instruction_with_remaining_accounts(args, &[]) + } + #[allow(clippy::arithmetic_side_effects)] + #[allow(clippy::vec_init_then_push)] + pub fn instruction_with_remaining_accounts( + &self, + args: CreateProposalInstructionArgs, + remaining_accounts: &[solana_instruction::AccountMeta], + ) -> solana_instruction::Instruction { + let mut accounts = Vec::with_capacity(11 + remaining_accounts.len()); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.realm_account, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + self.proposal_account, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + self.governance_account, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + self.token_owner_record, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.governing_token_mint, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.governance_authority, + true, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.payer, true, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.system_program, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.realm_config, + false, + )); + if let Some(voter_weight_record) = self.voter_weight_record { + accounts.push(solana_instruction::AccountMeta::new( + voter_weight_record, + false, + )); + } else { + accounts.push(solana_instruction::AccountMeta::new_readonly( + crate::SPL_GOVERNANCE_ID, + false, + )); + } + if let Some(proposal_deposit_account) = self.proposal_deposit_account { + accounts.push(solana_instruction::AccountMeta::new_readonly( + proposal_deposit_account, + false, + )); + } else { + accounts.push(solana_instruction::AccountMeta::new_readonly( + crate::SPL_GOVERNANCE_ID, + false, + )); + } + accounts.extend_from_slice(remaining_accounts); + let mut data = CreateProposalInstructionData::new().try_to_vec().unwrap(); + let mut args = args.try_to_vec().unwrap(); + data.append(&mut args); + + solana_instruction::Instruction { + program_id: crate::SPL_GOVERNANCE_ID, + accounts, + data, + } + } +} + +#[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct CreateProposalInstructionData { + discriminator: u8, +} + +impl CreateProposalInstructionData { + pub fn new() -> Self { + Self { discriminator: 6 } + } + + pub(crate) fn try_to_vec(&self) -> Result, std::io::Error> { + borsh::to_vec(self) + } +} + +impl Default for CreateProposalInstructionData { + fn default() -> Self { + Self::new() + } +} + +#[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct CreateProposalInstructionArgs { + pub name: String, + pub description_link: String, + pub vote_type: VoteType, + pub options: Vec, + pub use_deny_option: bool, + pub proposal_seed: Pubkey, +} + +impl CreateProposalInstructionArgs { + pub(crate) fn try_to_vec(&self) -> Result, std::io::Error> { + borsh::to_vec(self) + } +} + +/// Instruction builder for `CreateProposal`. +/// +/// ### Accounts: +/// +/// 0. `[]` realm_account +/// 1. `[writable]` proposal_account +/// 2. `[writable]` governance_account +/// 3. `[writable]` token_owner_record +/// 4. `[]` governing_token_mint +/// 5. `[signer]` governance_authority +/// 6. `[signer]` payer +/// 7. `[optional]` system_program (default to `11111111111111111111111111111111`) +/// 8. `[]` realm_config +/// 9. `[writable, optional]` voter_weight_record +/// 10. `[optional]` proposal_deposit_account +#[derive(Clone, Debug, Default)] +pub struct CreateProposalBuilder { + realm_account: Option, + proposal_account: Option, + governance_account: Option, + token_owner_record: Option, + governing_token_mint: Option, + governance_authority: Option, + payer: Option, + system_program: Option, + realm_config: Option, + voter_weight_record: Option, + proposal_deposit_account: Option, + name: Option, + description_link: Option, + vote_type: Option, + options: Option>, + use_deny_option: Option, + proposal_seed: Option, + __remaining_accounts: Vec, +} + +impl CreateProposalBuilder { + pub fn new() -> Self { + Self::default() + } + /// Realm account the created Proposal belongs to + #[inline(always)] + pub fn realm_account(&mut self, realm_account: solana_pubkey::Pubkey) -> &mut Self { + self.realm_account = Some(realm_account); + self + } + /// Proposal account. PDA seeds ['governance',governance, governing_token_mint, proposal_index] + #[inline(always)] + pub fn proposal_account(&mut self, proposal_account: solana_pubkey::Pubkey) -> &mut Self { + self.proposal_account = Some(proposal_account); + self + } + /// Governance account + #[inline(always)] + pub fn governance_account(&mut self, governance_account: solana_pubkey::Pubkey) -> &mut Self { + self.governance_account = Some(governance_account); + self + } + /// TokenOwnerRecord account of the Proposal owner + #[inline(always)] + pub fn token_owner_record(&mut self, token_owner_record: solana_pubkey::Pubkey) -> &mut Self { + self.token_owner_record = Some(token_owner_record); + self + } + /// Token Mint the Proposal is created for + #[inline(always)] + pub fn governing_token_mint( + &mut self, + governing_token_mint: solana_pubkey::Pubkey, + ) -> &mut Self { + self.governing_token_mint = Some(governing_token_mint); + self + } + /// Governance Authority (Token Owner or Governance Delegate) + #[inline(always)] + pub fn governance_authority( + &mut self, + governance_authority: solana_pubkey::Pubkey, + ) -> &mut Self { + self.governance_authority = Some(governance_authority); + self + } + #[inline(always)] + pub fn payer(&mut self, payer: solana_pubkey::Pubkey) -> &mut Self { + self.payer = Some(payer); + self + } + /// `[optional account, default to '11111111111111111111111111111111']` + #[inline(always)] + pub fn system_program(&mut self, system_program: solana_pubkey::Pubkey) -> &mut Self { + self.system_program = Some(system_program); + self + } + /// RealmConfig account. PDA seeds: ['realm-config', realm] + #[inline(always)] + pub fn realm_config(&mut self, realm_config: solana_pubkey::Pubkey) -> &mut Self { + self.realm_config = Some(realm_config); + self + } + /// `[optional account]` + /// Optional Voter Weight Record + #[inline(always)] + pub fn voter_weight_record( + &mut self, + voter_weight_record: Option, + ) -> &mut Self { + self.voter_weight_record = voter_weight_record; + self + } + /// `[optional account]` + /// Optional Proposal deposit is required when there are more active + /// proposals than the configured deposit exempt amount. + /// PDA seeds: ['proposal-deposit', proposal, deposit payer] + #[inline(always)] + pub fn proposal_deposit_account( + &mut self, + proposal_deposit_account: Option, + ) -> &mut Self { + self.proposal_deposit_account = proposal_deposit_account; + self + } + #[inline(always)] + pub fn name(&mut self, name: String) -> &mut Self { + self.name = Some(name); + self + } + #[inline(always)] + pub fn description_link(&mut self, description_link: String) -> &mut Self { + self.description_link = Some(description_link); + self + } + #[inline(always)] + pub fn vote_type(&mut self, vote_type: VoteType) -> &mut Self { + self.vote_type = Some(vote_type); + self + } + #[inline(always)] + pub fn options(&mut self, options: Vec) -> &mut Self { + self.options = Some(options); + self + } + #[inline(always)] + pub fn use_deny_option(&mut self, use_deny_option: bool) -> &mut Self { + self.use_deny_option = Some(use_deny_option); + self + } + #[inline(always)] + pub fn proposal_seed(&mut self, proposal_seed: Pubkey) -> &mut Self { + self.proposal_seed = Some(proposal_seed); + self + } + /// Add an additional account to the instruction. + #[inline(always)] + pub fn add_remaining_account(&mut self, account: solana_instruction::AccountMeta) -> &mut Self { + self.__remaining_accounts.push(account); + self + } + /// Add additional accounts to the instruction. + #[inline(always)] + pub fn add_remaining_accounts( + &mut self, + accounts: &[solana_instruction::AccountMeta], + ) -> &mut Self { + self.__remaining_accounts.extend_from_slice(accounts); + self + } + #[allow(clippy::clone_on_copy)] + pub fn instruction(&self) -> solana_instruction::Instruction { + let accounts = CreateProposal { + realm_account: self.realm_account.expect("realm_account is not set"), + proposal_account: self.proposal_account.expect("proposal_account is not set"), + governance_account: self + .governance_account + .expect("governance_account is not set"), + token_owner_record: self + .token_owner_record + .expect("token_owner_record is not set"), + governing_token_mint: self + .governing_token_mint + .expect("governing_token_mint is not set"), + governance_authority: self + .governance_authority + .expect("governance_authority is not set"), + payer: self.payer.expect("payer is not set"), + system_program: self + .system_program + .unwrap_or(solana_pubkey::pubkey!("11111111111111111111111111111111")), + realm_config: self.realm_config.expect("realm_config is not set"), + voter_weight_record: self.voter_weight_record, + proposal_deposit_account: self.proposal_deposit_account, + }; + let args = CreateProposalInstructionArgs { + name: self.name.clone().expect("name is not set"), + description_link: self + .description_link + .clone() + .expect("description_link is not set"), + vote_type: self.vote_type.clone().expect("vote_type is not set"), + options: self.options.clone().expect("options is not set"), + use_deny_option: self + .use_deny_option + .clone() + .expect("use_deny_option is not set"), + proposal_seed: self + .proposal_seed + .clone() + .expect("proposal_seed is not set"), + }; + + accounts.instruction_with_remaining_accounts(args, &self.__remaining_accounts) + } +} + +/// `create_proposal` CPI accounts. +pub struct CreateProposalCpiAccounts<'a, 'b> { + /// Realm account the created Proposal belongs to + pub realm_account: &'b solana_account_info::AccountInfo<'a>, + /// Proposal account. PDA seeds ['governance',governance, governing_token_mint, proposal_index] + pub proposal_account: &'b solana_account_info::AccountInfo<'a>, + /// Governance account + pub governance_account: &'b solana_account_info::AccountInfo<'a>, + /// TokenOwnerRecord account of the Proposal owner + pub token_owner_record: &'b solana_account_info::AccountInfo<'a>, + /// Token Mint the Proposal is created for + pub governing_token_mint: &'b solana_account_info::AccountInfo<'a>, + /// Governance Authority (Token Owner or Governance Delegate) + pub governance_authority: &'b solana_account_info::AccountInfo<'a>, + + pub payer: &'b solana_account_info::AccountInfo<'a>, + + pub system_program: &'b solana_account_info::AccountInfo<'a>, + /// RealmConfig account. PDA seeds: ['realm-config', realm] + pub realm_config: &'b solana_account_info::AccountInfo<'a>, + /// Optional Voter Weight Record + pub voter_weight_record: Option<&'b solana_account_info::AccountInfo<'a>>, + /// Optional Proposal deposit is required when there are more active + /// proposals than the configured deposit exempt amount. + /// PDA seeds: ['proposal-deposit', proposal, deposit payer] + pub proposal_deposit_account: Option<&'b solana_account_info::AccountInfo<'a>>, +} + +/// `create_proposal` CPI instruction. +pub struct CreateProposalCpi<'a, 'b> { + /// The program to invoke. + pub __program: &'b solana_account_info::AccountInfo<'a>, + /// Realm account the created Proposal belongs to + pub realm_account: &'b solana_account_info::AccountInfo<'a>, + /// Proposal account. PDA seeds ['governance',governance, governing_token_mint, proposal_index] + pub proposal_account: &'b solana_account_info::AccountInfo<'a>, + /// Governance account + pub governance_account: &'b solana_account_info::AccountInfo<'a>, + /// TokenOwnerRecord account of the Proposal owner + pub token_owner_record: &'b solana_account_info::AccountInfo<'a>, + /// Token Mint the Proposal is created for + pub governing_token_mint: &'b solana_account_info::AccountInfo<'a>, + /// Governance Authority (Token Owner or Governance Delegate) + pub governance_authority: &'b solana_account_info::AccountInfo<'a>, + + pub payer: &'b solana_account_info::AccountInfo<'a>, + + pub system_program: &'b solana_account_info::AccountInfo<'a>, + /// RealmConfig account. PDA seeds: ['realm-config', realm] + pub realm_config: &'b solana_account_info::AccountInfo<'a>, + /// Optional Voter Weight Record + pub voter_weight_record: Option<&'b solana_account_info::AccountInfo<'a>>, + /// Optional Proposal deposit is required when there are more active + /// proposals than the configured deposit exempt amount. + /// PDA seeds: ['proposal-deposit', proposal, deposit payer] + pub proposal_deposit_account: Option<&'b solana_account_info::AccountInfo<'a>>, + /// The arguments for the instruction. + pub __args: CreateProposalInstructionArgs, +} + +impl<'a, 'b> CreateProposalCpi<'a, 'b> { + pub fn new( + program: &'b solana_account_info::AccountInfo<'a>, + accounts: CreateProposalCpiAccounts<'a, 'b>, + args: CreateProposalInstructionArgs, + ) -> Self { + Self { + __program: program, + realm_account: accounts.realm_account, + proposal_account: accounts.proposal_account, + governance_account: accounts.governance_account, + token_owner_record: accounts.token_owner_record, + governing_token_mint: accounts.governing_token_mint, + governance_authority: accounts.governance_authority, + payer: accounts.payer, + system_program: accounts.system_program, + realm_config: accounts.realm_config, + voter_weight_record: accounts.voter_weight_record, + proposal_deposit_account: accounts.proposal_deposit_account, + __args: args, + } + } + #[inline(always)] + pub fn invoke(&self) -> solana_program_error::ProgramResult { + self.invoke_signed_with_remaining_accounts(&[], &[]) + } + #[inline(always)] + pub fn invoke_with_remaining_accounts( + &self, + remaining_accounts: &[(&'b solana_account_info::AccountInfo<'a>, bool, bool)], + ) -> solana_program_error::ProgramResult { + self.invoke_signed_with_remaining_accounts(&[], remaining_accounts) + } + #[inline(always)] + pub fn invoke_signed(&self, signers_seeds: &[&[&[u8]]]) -> solana_program_error::ProgramResult { + self.invoke_signed_with_remaining_accounts(signers_seeds, &[]) + } + #[allow(clippy::arithmetic_side_effects)] + #[allow(clippy::clone_on_copy)] + #[allow(clippy::vec_init_then_push)] + pub fn invoke_signed_with_remaining_accounts( + &self, + signers_seeds: &[&[&[u8]]], + remaining_accounts: &[(&'b solana_account_info::AccountInfo<'a>, bool, bool)], + ) -> solana_program_error::ProgramResult { + let mut accounts = Vec::with_capacity(11 + remaining_accounts.len()); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.realm_account.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + *self.proposal_account.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + *self.governance_account.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + *self.token_owner_record.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.governing_token_mint.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.governance_authority.key, + true, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.payer.key, + true, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.system_program.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.realm_config.key, + false, + )); + if let Some(voter_weight_record) = self.voter_weight_record { + accounts.push(solana_instruction::AccountMeta::new( + *voter_weight_record.key, + false, + )); + } else { + accounts.push(solana_instruction::AccountMeta::new_readonly( + crate::SPL_GOVERNANCE_ID, + false, + )); + } + if let Some(proposal_deposit_account) = self.proposal_deposit_account { + accounts.push(solana_instruction::AccountMeta::new_readonly( + *proposal_deposit_account.key, + false, + )); + } else { + accounts.push(solana_instruction::AccountMeta::new_readonly( + crate::SPL_GOVERNANCE_ID, + false, + )); + } + remaining_accounts.iter().for_each(|remaining_account| { + accounts.push(solana_instruction::AccountMeta { + pubkey: *remaining_account.0.key, + is_signer: remaining_account.1, + is_writable: remaining_account.2, + }) + }); + let mut data = CreateProposalInstructionData::new().try_to_vec().unwrap(); + let mut args = self.__args.try_to_vec().unwrap(); + data.append(&mut args); + + let instruction = solana_instruction::Instruction { + program_id: crate::SPL_GOVERNANCE_ID, + accounts, + data, + }; + let mut account_infos = Vec::with_capacity(12 + remaining_accounts.len()); + account_infos.push(self.__program.clone()); + account_infos.push(self.realm_account.clone()); + account_infos.push(self.proposal_account.clone()); + account_infos.push(self.governance_account.clone()); + account_infos.push(self.token_owner_record.clone()); + account_infos.push(self.governing_token_mint.clone()); + account_infos.push(self.governance_authority.clone()); + account_infos.push(self.payer.clone()); + account_infos.push(self.system_program.clone()); + account_infos.push(self.realm_config.clone()); + if let Some(voter_weight_record) = self.voter_weight_record { + account_infos.push(voter_weight_record.clone()); + } + if let Some(proposal_deposit_account) = self.proposal_deposit_account { + account_infos.push(proposal_deposit_account.clone()); + } + remaining_accounts + .iter() + .for_each(|remaining_account| account_infos.push(remaining_account.0.clone())); + + if signers_seeds.is_empty() { + solana_cpi::invoke(&instruction, &account_infos) + } else { + solana_cpi::invoke_signed(&instruction, &account_infos, signers_seeds) + } + } +} + +/// Instruction builder for `CreateProposal` via CPI. +/// +/// ### Accounts: +/// +/// 0. `[]` realm_account +/// 1. `[writable]` proposal_account +/// 2. `[writable]` governance_account +/// 3. `[writable]` token_owner_record +/// 4. `[]` governing_token_mint +/// 5. `[signer]` governance_authority +/// 6. `[signer]` payer +/// 7. `[]` system_program +/// 8. `[]` realm_config +/// 9. `[writable, optional]` voter_weight_record +/// 10. `[optional]` proposal_deposit_account +#[derive(Clone, Debug)] +pub struct CreateProposalCpiBuilder<'a, 'b> { + instruction: Box>, +} + +impl<'a, 'b> CreateProposalCpiBuilder<'a, 'b> { + pub fn new(program: &'b solana_account_info::AccountInfo<'a>) -> Self { + let instruction = Box::new(CreateProposalCpiBuilderInstruction { + __program: program, + realm_account: None, + proposal_account: None, + governance_account: None, + token_owner_record: None, + governing_token_mint: None, + governance_authority: None, + payer: None, + system_program: None, + realm_config: None, + voter_weight_record: None, + proposal_deposit_account: None, + name: None, + description_link: None, + vote_type: None, + options: None, + use_deny_option: None, + proposal_seed: None, + __remaining_accounts: Vec::new(), + }); + Self { instruction } + } + /// Realm account the created Proposal belongs to + #[inline(always)] + pub fn realm_account( + &mut self, + realm_account: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.realm_account = Some(realm_account); + self + } + /// Proposal account. PDA seeds ['governance',governance, governing_token_mint, proposal_index] + #[inline(always)] + pub fn proposal_account( + &mut self, + proposal_account: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.proposal_account = Some(proposal_account); + self + } + /// Governance account + #[inline(always)] + pub fn governance_account( + &mut self, + governance_account: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.governance_account = Some(governance_account); + self + } + /// TokenOwnerRecord account of the Proposal owner + #[inline(always)] + pub fn token_owner_record( + &mut self, + token_owner_record: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.token_owner_record = Some(token_owner_record); + self + } + /// Token Mint the Proposal is created for + #[inline(always)] + pub fn governing_token_mint( + &mut self, + governing_token_mint: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.governing_token_mint = Some(governing_token_mint); + self + } + /// Governance Authority (Token Owner or Governance Delegate) + #[inline(always)] + pub fn governance_authority( + &mut self, + governance_authority: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.governance_authority = Some(governance_authority); + self + } + #[inline(always)] + pub fn payer(&mut self, payer: &'b solana_account_info::AccountInfo<'a>) -> &mut Self { + self.instruction.payer = Some(payer); + self + } + #[inline(always)] + pub fn system_program( + &mut self, + system_program: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.system_program = Some(system_program); + self + } + /// RealmConfig account. PDA seeds: ['realm-config', realm] + #[inline(always)] + pub fn realm_config( + &mut self, + realm_config: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.realm_config = Some(realm_config); + self + } + /// `[optional account]` + /// Optional Voter Weight Record + #[inline(always)] + pub fn voter_weight_record( + &mut self, + voter_weight_record: Option<&'b solana_account_info::AccountInfo<'a>>, + ) -> &mut Self { + self.instruction.voter_weight_record = voter_weight_record; + self + } + /// `[optional account]` + /// Optional Proposal deposit is required when there are more active + /// proposals than the configured deposit exempt amount. + /// PDA seeds: ['proposal-deposit', proposal, deposit payer] + #[inline(always)] + pub fn proposal_deposit_account( + &mut self, + proposal_deposit_account: Option<&'b solana_account_info::AccountInfo<'a>>, + ) -> &mut Self { + self.instruction.proposal_deposit_account = proposal_deposit_account; + self + } + #[inline(always)] + pub fn name(&mut self, name: String) -> &mut Self { + self.instruction.name = Some(name); + self + } + #[inline(always)] + pub fn description_link(&mut self, description_link: String) -> &mut Self { + self.instruction.description_link = Some(description_link); + self + } + #[inline(always)] + pub fn vote_type(&mut self, vote_type: VoteType) -> &mut Self { + self.instruction.vote_type = Some(vote_type); + self + } + #[inline(always)] + pub fn options(&mut self, options: Vec) -> &mut Self { + self.instruction.options = Some(options); + self + } + #[inline(always)] + pub fn use_deny_option(&mut self, use_deny_option: bool) -> &mut Self { + self.instruction.use_deny_option = Some(use_deny_option); + self + } + #[inline(always)] + pub fn proposal_seed(&mut self, proposal_seed: Pubkey) -> &mut Self { + self.instruction.proposal_seed = Some(proposal_seed); + self + } + /// Add an additional account to the instruction. + #[inline(always)] + pub fn add_remaining_account( + &mut self, + account: &'b solana_account_info::AccountInfo<'a>, + is_writable: bool, + is_signer: bool, + ) -> &mut Self { + self.instruction + .__remaining_accounts + .push((account, is_writable, is_signer)); + self + } + /// Add additional accounts to the instruction. + /// + /// Each account is represented by a tuple of the `AccountInfo`, a `bool` indicating whether the account is writable or not, + /// and a `bool` indicating whether the account is a signer or not. + #[inline(always)] + pub fn add_remaining_accounts( + &mut self, + accounts: &[(&'b solana_account_info::AccountInfo<'a>, bool, bool)], + ) -> &mut Self { + self.instruction + .__remaining_accounts + .extend_from_slice(accounts); + self + } + #[inline(always)] + pub fn invoke(&self) -> solana_program_error::ProgramResult { + self.invoke_signed(&[]) + } + #[allow(clippy::clone_on_copy)] + #[allow(clippy::vec_init_then_push)] + pub fn invoke_signed(&self, signers_seeds: &[&[&[u8]]]) -> solana_program_error::ProgramResult { + let args = CreateProposalInstructionArgs { + name: self.instruction.name.clone().expect("name is not set"), + description_link: self + .instruction + .description_link + .clone() + .expect("description_link is not set"), + vote_type: self + .instruction + .vote_type + .clone() + .expect("vote_type is not set"), + options: self + .instruction + .options + .clone() + .expect("options is not set"), + use_deny_option: self + .instruction + .use_deny_option + .clone() + .expect("use_deny_option is not set"), + proposal_seed: self + .instruction + .proposal_seed + .clone() + .expect("proposal_seed is not set"), + }; + let instruction = CreateProposalCpi { + __program: self.instruction.__program, + + realm_account: self + .instruction + .realm_account + .expect("realm_account is not set"), + + proposal_account: self + .instruction + .proposal_account + .expect("proposal_account is not set"), + + governance_account: self + .instruction + .governance_account + .expect("governance_account is not set"), + + token_owner_record: self + .instruction + .token_owner_record + .expect("token_owner_record is not set"), + + governing_token_mint: self + .instruction + .governing_token_mint + .expect("governing_token_mint is not set"), + + governance_authority: self + .instruction + .governance_authority + .expect("governance_authority is not set"), + + payer: self.instruction.payer.expect("payer is not set"), + + system_program: self + .instruction + .system_program + .expect("system_program is not set"), + + realm_config: self + .instruction + .realm_config + .expect("realm_config is not set"), + + voter_weight_record: self.instruction.voter_weight_record, + + proposal_deposit_account: self.instruction.proposal_deposit_account, + __args: args, + }; + instruction.invoke_signed_with_remaining_accounts( + signers_seeds, + &self.instruction.__remaining_accounts, + ) + } +} + +#[derive(Clone, Debug)] +struct CreateProposalCpiBuilderInstruction<'a, 'b> { + __program: &'b solana_account_info::AccountInfo<'a>, + realm_account: Option<&'b solana_account_info::AccountInfo<'a>>, + proposal_account: Option<&'b solana_account_info::AccountInfo<'a>>, + governance_account: Option<&'b solana_account_info::AccountInfo<'a>>, + token_owner_record: Option<&'b solana_account_info::AccountInfo<'a>>, + governing_token_mint: Option<&'b solana_account_info::AccountInfo<'a>>, + governance_authority: Option<&'b solana_account_info::AccountInfo<'a>>, + payer: Option<&'b solana_account_info::AccountInfo<'a>>, + system_program: Option<&'b solana_account_info::AccountInfo<'a>>, + realm_config: Option<&'b solana_account_info::AccountInfo<'a>>, + voter_weight_record: Option<&'b solana_account_info::AccountInfo<'a>>, + proposal_deposit_account: Option<&'b solana_account_info::AccountInfo<'a>>, + name: Option, + description_link: Option, + vote_type: Option, + options: Option>, + use_deny_option: Option, + proposal_seed: Option, + /// Additional instruction accounts `(AccountInfo, is_writable, is_signer)`. + __remaining_accounts: Vec<(&'b solana_account_info::AccountInfo<'a>, bool, bool)>, +} diff --git a/e2e/governance/src/generated/instructions/create_realm.rs b/e2e/governance/src/generated/instructions/create_realm.rs new file mode 100644 index 0000000..6b8e8cc --- /dev/null +++ b/e2e/governance/src/generated/instructions/create_realm.rs @@ -0,0 +1,1051 @@ +//! This code was AUTOGENERATED using the codama library. +//! Please DO NOT EDIT THIS FILE, instead use visitors +//! to add features, then rerun codama to update it. +//! +//! +//! + +use crate::generated::types::RealmConfigParams; +use borsh::BorshDeserialize; +use borsh::BorshSerialize; + +pub const CREATE_REALM_DISCRIMINATOR: u8 = 0; + +/// Accounts. +#[derive(Debug)] +pub struct CreateRealm { + /// Governance Realm account + pub realm_account: solana_pubkey::Pubkey, + /// The authority of the Realm + pub realm_authority: solana_pubkey::Pubkey, + /// The mint address of the token to be used as the community mint + pub community_token_mint: solana_pubkey::Pubkey, + /// The account to hold the community tokens. + /// PDA seeds=['governance', realm, community_mint] + pub community_token_holding_account: solana_pubkey::Pubkey, + /// the payer of this transaction + pub payer: solana_pubkey::Pubkey, + /// System Program + pub system_program: solana_pubkey::Pubkey, + /// SPL Token Program + pub token_program: solana_pubkey::Pubkey, + /// SysVar Rent + pub rent: solana_pubkey::Pubkey, + /// The mint address of the token to be used as the council mint + pub council_token_mint: Option, + /// The account to hold the council tokens. + /// PDA seeds: ['governance',realm,council_mint] + /// + pub council_token_holding_account: Option, + /// Realm Config account + pub realm_config: solana_pubkey::Pubkey, + /// Optional Community Voter Weight Addin Program Id + pub community_voter_weight_addin: Option, + /// Optional Max Community Voter Weight Addin Program Id + pub max_community_voter_weight_addin: Option, + /// Optional Council Voter Weight Addin Program Id + pub council_voter_weight_addin: Option, + /// Optional Max Council Voter Weight Addin Program Id + pub max_council_voter_weight_addin: Option, +} + +impl CreateRealm { + pub fn instruction(&self, args: CreateRealmInstructionArgs) -> solana_instruction::Instruction { + self.instruction_with_remaining_accounts(args, &[]) + } + #[allow(clippy::arithmetic_side_effects)] + #[allow(clippy::vec_init_then_push)] + pub fn instruction_with_remaining_accounts( + &self, + args: CreateRealmInstructionArgs, + remaining_accounts: &[solana_instruction::AccountMeta], + ) -> solana_instruction::Instruction { + let mut accounts = Vec::with_capacity(15 + remaining_accounts.len()); + accounts.push(solana_instruction::AccountMeta::new( + self.realm_account, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.realm_authority, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.community_token_mint, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + self.community_token_holding_account, + false, + )); + accounts.push(solana_instruction::AccountMeta::new(self.payer, true)); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.system_program, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.token_program, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.rent, false, + )); + if let Some(council_token_mint) = self.council_token_mint { + accounts.push(solana_instruction::AccountMeta::new_readonly( + council_token_mint, + false, + )); + } else { + accounts.push(solana_instruction::AccountMeta::new_readonly( + crate::SPL_GOVERNANCE_ID, + false, + )); + } + if let Some(council_token_holding_account) = self.council_token_holding_account { + accounts.push(solana_instruction::AccountMeta::new( + council_token_holding_account, + false, + )); + } else { + accounts.push(solana_instruction::AccountMeta::new_readonly( + crate::SPL_GOVERNANCE_ID, + false, + )); + } + accounts.push(solana_instruction::AccountMeta::new( + self.realm_config, + false, + )); + if let Some(community_voter_weight_addin) = self.community_voter_weight_addin { + accounts.push(solana_instruction::AccountMeta::new_readonly( + community_voter_weight_addin, + false, + )); + } else { + accounts.push(solana_instruction::AccountMeta::new_readonly( + crate::SPL_GOVERNANCE_ID, + false, + )); + } + if let Some(max_community_voter_weight_addin) = self.max_community_voter_weight_addin { + accounts.push(solana_instruction::AccountMeta::new_readonly( + max_community_voter_weight_addin, + false, + )); + } else { + accounts.push(solana_instruction::AccountMeta::new_readonly( + crate::SPL_GOVERNANCE_ID, + false, + )); + } + if let Some(council_voter_weight_addin) = self.council_voter_weight_addin { + accounts.push(solana_instruction::AccountMeta::new_readonly( + council_voter_weight_addin, + false, + )); + } else { + accounts.push(solana_instruction::AccountMeta::new_readonly( + crate::SPL_GOVERNANCE_ID, + false, + )); + } + if let Some(max_council_voter_weight_addin) = self.max_council_voter_weight_addin { + accounts.push(solana_instruction::AccountMeta::new_readonly( + max_council_voter_weight_addin, + false, + )); + } else { + accounts.push(solana_instruction::AccountMeta::new_readonly( + crate::SPL_GOVERNANCE_ID, + false, + )); + } + accounts.extend_from_slice(remaining_accounts); + let mut data = CreateRealmInstructionData::new().try_to_vec().unwrap(); + let mut args = args.try_to_vec().unwrap(); + data.append(&mut args); + + solana_instruction::Instruction { + program_id: crate::SPL_GOVERNANCE_ID, + accounts, + data, + } + } +} + +#[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct CreateRealmInstructionData { + discriminator: u8, +} + +impl CreateRealmInstructionData { + pub fn new() -> Self { + Self { discriminator: 0 } + } + + pub(crate) fn try_to_vec(&self) -> Result, std::io::Error> { + borsh::to_vec(self) + } +} + +impl Default for CreateRealmInstructionData { + fn default() -> Self { + Self::new() + } +} + +#[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct CreateRealmInstructionArgs { + pub name: String, + pub config_args: RealmConfigParams, +} + +impl CreateRealmInstructionArgs { + pub(crate) fn try_to_vec(&self) -> Result, std::io::Error> { + borsh::to_vec(self) + } +} + +/// Instruction builder for `CreateRealm`. +/// +/// ### Accounts: +/// +/// 0. `[writable]` realm_account +/// 1. `[]` realm_authority +/// 2. `[]` community_token_mint +/// 3. `[writable]` community_token_holding_account +/// 4. `[writable, signer]` payer +/// 5. `[optional]` system_program (default to `11111111111111111111111111111111`) +/// 6. `[optional]` token_program (default to `TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA`) +/// 7. `[optional]` rent (default to `SysvarRent111111111111111111111111111111111`) +/// 8. `[optional]` council_token_mint +/// 9. `[writable, optional]` council_token_holding_account +/// 10. `[writable]` realm_config +/// 11. `[optional]` community_voter_weight_addin +/// 12. `[optional]` max_community_voter_weight_addin +/// 13. `[optional]` council_voter_weight_addin +/// 14. `[optional]` max_council_voter_weight_addin +#[derive(Clone, Debug, Default)] +pub struct CreateRealmBuilder { + realm_account: Option, + realm_authority: Option, + community_token_mint: Option, + community_token_holding_account: Option, + payer: Option, + system_program: Option, + token_program: Option, + rent: Option, + council_token_mint: Option, + council_token_holding_account: Option, + realm_config: Option, + community_voter_weight_addin: Option, + max_community_voter_weight_addin: Option, + council_voter_weight_addin: Option, + max_council_voter_weight_addin: Option, + name: Option, + config_args: Option, + __remaining_accounts: Vec, +} + +impl CreateRealmBuilder { + pub fn new() -> Self { + Self::default() + } + /// Governance Realm account + #[inline(always)] + pub fn realm_account(&mut self, realm_account: solana_pubkey::Pubkey) -> &mut Self { + self.realm_account = Some(realm_account); + self + } + /// The authority of the Realm + #[inline(always)] + pub fn realm_authority(&mut self, realm_authority: solana_pubkey::Pubkey) -> &mut Self { + self.realm_authority = Some(realm_authority); + self + } + /// The mint address of the token to be used as the community mint + #[inline(always)] + pub fn community_token_mint( + &mut self, + community_token_mint: solana_pubkey::Pubkey, + ) -> &mut Self { + self.community_token_mint = Some(community_token_mint); + self + } + /// The account to hold the community tokens. + /// PDA seeds=['governance', realm, community_mint] + #[inline(always)] + pub fn community_token_holding_account( + &mut self, + community_token_holding_account: solana_pubkey::Pubkey, + ) -> &mut Self { + self.community_token_holding_account = Some(community_token_holding_account); + self + } + /// the payer of this transaction + #[inline(always)] + pub fn payer(&mut self, payer: solana_pubkey::Pubkey) -> &mut Self { + self.payer = Some(payer); + self + } + /// `[optional account, default to '11111111111111111111111111111111']` + /// System Program + #[inline(always)] + pub fn system_program(&mut self, system_program: solana_pubkey::Pubkey) -> &mut Self { + self.system_program = Some(system_program); + self + } + /// `[optional account, default to 'TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA']` + /// SPL Token Program + #[inline(always)] + pub fn token_program(&mut self, token_program: solana_pubkey::Pubkey) -> &mut Self { + self.token_program = Some(token_program); + self + } + /// `[optional account, default to 'SysvarRent111111111111111111111111111111111']` + /// SysVar Rent + #[inline(always)] + pub fn rent(&mut self, rent: solana_pubkey::Pubkey) -> &mut Self { + self.rent = Some(rent); + self + } + /// `[optional account]` + /// The mint address of the token to be used as the council mint + #[inline(always)] + pub fn council_token_mint( + &mut self, + council_token_mint: Option, + ) -> &mut Self { + self.council_token_mint = council_token_mint; + self + } + /// `[optional account]` + /// The account to hold the council tokens. + /// PDA seeds: ['governance',realm,council_mint] + /// + #[inline(always)] + pub fn council_token_holding_account( + &mut self, + council_token_holding_account: Option, + ) -> &mut Self { + self.council_token_holding_account = council_token_holding_account; + self + } + /// Realm Config account + #[inline(always)] + pub fn realm_config(&mut self, realm_config: solana_pubkey::Pubkey) -> &mut Self { + self.realm_config = Some(realm_config); + self + } + /// `[optional account]` + /// Optional Community Voter Weight Addin Program Id + #[inline(always)] + pub fn community_voter_weight_addin( + &mut self, + community_voter_weight_addin: Option, + ) -> &mut Self { + self.community_voter_weight_addin = community_voter_weight_addin; + self + } + /// `[optional account]` + /// Optional Max Community Voter Weight Addin Program Id + #[inline(always)] + pub fn max_community_voter_weight_addin( + &mut self, + max_community_voter_weight_addin: Option, + ) -> &mut Self { + self.max_community_voter_weight_addin = max_community_voter_weight_addin; + self + } + /// `[optional account]` + /// Optional Council Voter Weight Addin Program Id + #[inline(always)] + pub fn council_voter_weight_addin( + &mut self, + council_voter_weight_addin: Option, + ) -> &mut Self { + self.council_voter_weight_addin = council_voter_weight_addin; + self + } + /// `[optional account]` + /// Optional Max Council Voter Weight Addin Program Id + #[inline(always)] + pub fn max_council_voter_weight_addin( + &mut self, + max_council_voter_weight_addin: Option, + ) -> &mut Self { + self.max_council_voter_weight_addin = max_council_voter_weight_addin; + self + } + #[inline(always)] + pub fn name(&mut self, name: String) -> &mut Self { + self.name = Some(name); + self + } + #[inline(always)] + pub fn config_args(&mut self, config_args: RealmConfigParams) -> &mut Self { + self.config_args = Some(config_args); + self + } + /// Add an additional account to the instruction. + #[inline(always)] + pub fn add_remaining_account(&mut self, account: solana_instruction::AccountMeta) -> &mut Self { + self.__remaining_accounts.push(account); + self + } + /// Add additional accounts to the instruction. + #[inline(always)] + pub fn add_remaining_accounts( + &mut self, + accounts: &[solana_instruction::AccountMeta], + ) -> &mut Self { + self.__remaining_accounts.extend_from_slice(accounts); + self + } + #[allow(clippy::clone_on_copy)] + pub fn instruction(&self) -> solana_instruction::Instruction { + let accounts = CreateRealm { + realm_account: self.realm_account.expect("realm_account is not set"), + realm_authority: self.realm_authority.expect("realm_authority is not set"), + community_token_mint: self + .community_token_mint + .expect("community_token_mint is not set"), + community_token_holding_account: self + .community_token_holding_account + .expect("community_token_holding_account is not set"), + payer: self.payer.expect("payer is not set"), + system_program: self + .system_program + .unwrap_or(solana_pubkey::pubkey!("11111111111111111111111111111111")), + token_program: self.token_program.unwrap_or(solana_pubkey::pubkey!( + "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA" + )), + rent: self.rent.unwrap_or(solana_pubkey::pubkey!( + "SysvarRent111111111111111111111111111111111" + )), + council_token_mint: self.council_token_mint, + council_token_holding_account: self.council_token_holding_account, + realm_config: self.realm_config.expect("realm_config is not set"), + community_voter_weight_addin: self.community_voter_weight_addin, + max_community_voter_weight_addin: self.max_community_voter_weight_addin, + council_voter_weight_addin: self.council_voter_weight_addin, + max_council_voter_weight_addin: self.max_council_voter_weight_addin, + }; + let args = CreateRealmInstructionArgs { + name: self.name.clone().expect("name is not set"), + config_args: self.config_args.clone().expect("config_args is not set"), + }; + + accounts.instruction_with_remaining_accounts(args, &self.__remaining_accounts) + } +} + +/// `create_realm` CPI accounts. +pub struct CreateRealmCpiAccounts<'a, 'b> { + /// Governance Realm account + pub realm_account: &'b solana_account_info::AccountInfo<'a>, + /// The authority of the Realm + pub realm_authority: &'b solana_account_info::AccountInfo<'a>, + /// The mint address of the token to be used as the community mint + pub community_token_mint: &'b solana_account_info::AccountInfo<'a>, + /// The account to hold the community tokens. + /// PDA seeds=['governance', realm, community_mint] + pub community_token_holding_account: &'b solana_account_info::AccountInfo<'a>, + /// the payer of this transaction + pub payer: &'b solana_account_info::AccountInfo<'a>, + /// System Program + pub system_program: &'b solana_account_info::AccountInfo<'a>, + /// SPL Token Program + pub token_program: &'b solana_account_info::AccountInfo<'a>, + /// SysVar Rent + pub rent: &'b solana_account_info::AccountInfo<'a>, + /// The mint address of the token to be used as the council mint + pub council_token_mint: Option<&'b solana_account_info::AccountInfo<'a>>, + /// The account to hold the council tokens. + /// PDA seeds: ['governance',realm,council_mint] + /// + pub council_token_holding_account: Option<&'b solana_account_info::AccountInfo<'a>>, + /// Realm Config account + pub realm_config: &'b solana_account_info::AccountInfo<'a>, + /// Optional Community Voter Weight Addin Program Id + pub community_voter_weight_addin: Option<&'b solana_account_info::AccountInfo<'a>>, + /// Optional Max Community Voter Weight Addin Program Id + pub max_community_voter_weight_addin: Option<&'b solana_account_info::AccountInfo<'a>>, + /// Optional Council Voter Weight Addin Program Id + pub council_voter_weight_addin: Option<&'b solana_account_info::AccountInfo<'a>>, + /// Optional Max Council Voter Weight Addin Program Id + pub max_council_voter_weight_addin: Option<&'b solana_account_info::AccountInfo<'a>>, +} + +/// `create_realm` CPI instruction. +pub struct CreateRealmCpi<'a, 'b> { + /// The program to invoke. + pub __program: &'b solana_account_info::AccountInfo<'a>, + /// Governance Realm account + pub realm_account: &'b solana_account_info::AccountInfo<'a>, + /// The authority of the Realm + pub realm_authority: &'b solana_account_info::AccountInfo<'a>, + /// The mint address of the token to be used as the community mint + pub community_token_mint: &'b solana_account_info::AccountInfo<'a>, + /// The account to hold the community tokens. + /// PDA seeds=['governance', realm, community_mint] + pub community_token_holding_account: &'b solana_account_info::AccountInfo<'a>, + /// the payer of this transaction + pub payer: &'b solana_account_info::AccountInfo<'a>, + /// System Program + pub system_program: &'b solana_account_info::AccountInfo<'a>, + /// SPL Token Program + pub token_program: &'b solana_account_info::AccountInfo<'a>, + /// SysVar Rent + pub rent: &'b solana_account_info::AccountInfo<'a>, + /// The mint address of the token to be used as the council mint + pub council_token_mint: Option<&'b solana_account_info::AccountInfo<'a>>, + /// The account to hold the council tokens. + /// PDA seeds: ['governance',realm,council_mint] + /// + pub council_token_holding_account: Option<&'b solana_account_info::AccountInfo<'a>>, + /// Realm Config account + pub realm_config: &'b solana_account_info::AccountInfo<'a>, + /// Optional Community Voter Weight Addin Program Id + pub community_voter_weight_addin: Option<&'b solana_account_info::AccountInfo<'a>>, + /// Optional Max Community Voter Weight Addin Program Id + pub max_community_voter_weight_addin: Option<&'b solana_account_info::AccountInfo<'a>>, + /// Optional Council Voter Weight Addin Program Id + pub council_voter_weight_addin: Option<&'b solana_account_info::AccountInfo<'a>>, + /// Optional Max Council Voter Weight Addin Program Id + pub max_council_voter_weight_addin: Option<&'b solana_account_info::AccountInfo<'a>>, + /// The arguments for the instruction. + pub __args: CreateRealmInstructionArgs, +} + +impl<'a, 'b> CreateRealmCpi<'a, 'b> { + pub fn new( + program: &'b solana_account_info::AccountInfo<'a>, + accounts: CreateRealmCpiAccounts<'a, 'b>, + args: CreateRealmInstructionArgs, + ) -> Self { + Self { + __program: program, + realm_account: accounts.realm_account, + realm_authority: accounts.realm_authority, + community_token_mint: accounts.community_token_mint, + community_token_holding_account: accounts.community_token_holding_account, + payer: accounts.payer, + system_program: accounts.system_program, + token_program: accounts.token_program, + rent: accounts.rent, + council_token_mint: accounts.council_token_mint, + council_token_holding_account: accounts.council_token_holding_account, + realm_config: accounts.realm_config, + community_voter_weight_addin: accounts.community_voter_weight_addin, + max_community_voter_weight_addin: accounts.max_community_voter_weight_addin, + council_voter_weight_addin: accounts.council_voter_weight_addin, + max_council_voter_weight_addin: accounts.max_council_voter_weight_addin, + __args: args, + } + } + #[inline(always)] + pub fn invoke(&self) -> solana_program_error::ProgramResult { + self.invoke_signed_with_remaining_accounts(&[], &[]) + } + #[inline(always)] + pub fn invoke_with_remaining_accounts( + &self, + remaining_accounts: &[(&'b solana_account_info::AccountInfo<'a>, bool, bool)], + ) -> solana_program_error::ProgramResult { + self.invoke_signed_with_remaining_accounts(&[], remaining_accounts) + } + #[inline(always)] + pub fn invoke_signed(&self, signers_seeds: &[&[&[u8]]]) -> solana_program_error::ProgramResult { + self.invoke_signed_with_remaining_accounts(signers_seeds, &[]) + } + #[allow(clippy::arithmetic_side_effects)] + #[allow(clippy::clone_on_copy)] + #[allow(clippy::vec_init_then_push)] + pub fn invoke_signed_with_remaining_accounts( + &self, + signers_seeds: &[&[&[u8]]], + remaining_accounts: &[(&'b solana_account_info::AccountInfo<'a>, bool, bool)], + ) -> solana_program_error::ProgramResult { + let mut accounts = Vec::with_capacity(15 + remaining_accounts.len()); + accounts.push(solana_instruction::AccountMeta::new( + *self.realm_account.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.realm_authority.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.community_token_mint.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + *self.community_token_holding_account.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new(*self.payer.key, true)); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.system_program.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.token_program.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.rent.key, + false, + )); + if let Some(council_token_mint) = self.council_token_mint { + accounts.push(solana_instruction::AccountMeta::new_readonly( + *council_token_mint.key, + false, + )); + } else { + accounts.push(solana_instruction::AccountMeta::new_readonly( + crate::SPL_GOVERNANCE_ID, + false, + )); + } + if let Some(council_token_holding_account) = self.council_token_holding_account { + accounts.push(solana_instruction::AccountMeta::new( + *council_token_holding_account.key, + false, + )); + } else { + accounts.push(solana_instruction::AccountMeta::new_readonly( + crate::SPL_GOVERNANCE_ID, + false, + )); + } + accounts.push(solana_instruction::AccountMeta::new( + *self.realm_config.key, + false, + )); + if let Some(community_voter_weight_addin) = self.community_voter_weight_addin { + accounts.push(solana_instruction::AccountMeta::new_readonly( + *community_voter_weight_addin.key, + false, + )); + } else { + accounts.push(solana_instruction::AccountMeta::new_readonly( + crate::SPL_GOVERNANCE_ID, + false, + )); + } + if let Some(max_community_voter_weight_addin) = self.max_community_voter_weight_addin { + accounts.push(solana_instruction::AccountMeta::new_readonly( + *max_community_voter_weight_addin.key, + false, + )); + } else { + accounts.push(solana_instruction::AccountMeta::new_readonly( + crate::SPL_GOVERNANCE_ID, + false, + )); + } + if let Some(council_voter_weight_addin) = self.council_voter_weight_addin { + accounts.push(solana_instruction::AccountMeta::new_readonly( + *council_voter_weight_addin.key, + false, + )); + } else { + accounts.push(solana_instruction::AccountMeta::new_readonly( + crate::SPL_GOVERNANCE_ID, + false, + )); + } + if let Some(max_council_voter_weight_addin) = self.max_council_voter_weight_addin { + accounts.push(solana_instruction::AccountMeta::new_readonly( + *max_council_voter_weight_addin.key, + false, + )); + } else { + accounts.push(solana_instruction::AccountMeta::new_readonly( + crate::SPL_GOVERNANCE_ID, + false, + )); + } + remaining_accounts.iter().for_each(|remaining_account| { + accounts.push(solana_instruction::AccountMeta { + pubkey: *remaining_account.0.key, + is_signer: remaining_account.1, + is_writable: remaining_account.2, + }) + }); + let mut data = CreateRealmInstructionData::new().try_to_vec().unwrap(); + let mut args = self.__args.try_to_vec().unwrap(); + data.append(&mut args); + + let instruction = solana_instruction::Instruction { + program_id: crate::SPL_GOVERNANCE_ID, + accounts, + data, + }; + let mut account_infos = Vec::with_capacity(16 + remaining_accounts.len()); + account_infos.push(self.__program.clone()); + account_infos.push(self.realm_account.clone()); + account_infos.push(self.realm_authority.clone()); + account_infos.push(self.community_token_mint.clone()); + account_infos.push(self.community_token_holding_account.clone()); + account_infos.push(self.payer.clone()); + account_infos.push(self.system_program.clone()); + account_infos.push(self.token_program.clone()); + account_infos.push(self.rent.clone()); + if let Some(council_token_mint) = self.council_token_mint { + account_infos.push(council_token_mint.clone()); + } + if let Some(council_token_holding_account) = self.council_token_holding_account { + account_infos.push(council_token_holding_account.clone()); + } + account_infos.push(self.realm_config.clone()); + if let Some(community_voter_weight_addin) = self.community_voter_weight_addin { + account_infos.push(community_voter_weight_addin.clone()); + } + if let Some(max_community_voter_weight_addin) = self.max_community_voter_weight_addin { + account_infos.push(max_community_voter_weight_addin.clone()); + } + if let Some(council_voter_weight_addin) = self.council_voter_weight_addin { + account_infos.push(council_voter_weight_addin.clone()); + } + if let Some(max_council_voter_weight_addin) = self.max_council_voter_weight_addin { + account_infos.push(max_council_voter_weight_addin.clone()); + } + remaining_accounts + .iter() + .for_each(|remaining_account| account_infos.push(remaining_account.0.clone())); + + if signers_seeds.is_empty() { + solana_cpi::invoke(&instruction, &account_infos) + } else { + solana_cpi::invoke_signed(&instruction, &account_infos, signers_seeds) + } + } +} + +/// Instruction builder for `CreateRealm` via CPI. +/// +/// ### Accounts: +/// +/// 0. `[writable]` realm_account +/// 1. `[]` realm_authority +/// 2. `[]` community_token_mint +/// 3. `[writable]` community_token_holding_account +/// 4. `[writable, signer]` payer +/// 5. `[]` system_program +/// 6. `[]` token_program +/// 7. `[]` rent +/// 8. `[optional]` council_token_mint +/// 9. `[writable, optional]` council_token_holding_account +/// 10. `[writable]` realm_config +/// 11. `[optional]` community_voter_weight_addin +/// 12. `[optional]` max_community_voter_weight_addin +/// 13. `[optional]` council_voter_weight_addin +/// 14. `[optional]` max_council_voter_weight_addin +#[derive(Clone, Debug)] +pub struct CreateRealmCpiBuilder<'a, 'b> { + instruction: Box>, +} + +impl<'a, 'b> CreateRealmCpiBuilder<'a, 'b> { + pub fn new(program: &'b solana_account_info::AccountInfo<'a>) -> Self { + let instruction = Box::new(CreateRealmCpiBuilderInstruction { + __program: program, + realm_account: None, + realm_authority: None, + community_token_mint: None, + community_token_holding_account: None, + payer: None, + system_program: None, + token_program: None, + rent: None, + council_token_mint: None, + council_token_holding_account: None, + realm_config: None, + community_voter_weight_addin: None, + max_community_voter_weight_addin: None, + council_voter_weight_addin: None, + max_council_voter_weight_addin: None, + name: None, + config_args: None, + __remaining_accounts: Vec::new(), + }); + Self { instruction } + } + /// Governance Realm account + #[inline(always)] + pub fn realm_account( + &mut self, + realm_account: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.realm_account = Some(realm_account); + self + } + /// The authority of the Realm + #[inline(always)] + pub fn realm_authority( + &mut self, + realm_authority: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.realm_authority = Some(realm_authority); + self + } + /// The mint address of the token to be used as the community mint + #[inline(always)] + pub fn community_token_mint( + &mut self, + community_token_mint: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.community_token_mint = Some(community_token_mint); + self + } + /// The account to hold the community tokens. + /// PDA seeds=['governance', realm, community_mint] + #[inline(always)] + pub fn community_token_holding_account( + &mut self, + community_token_holding_account: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.community_token_holding_account = Some(community_token_holding_account); + self + } + /// the payer of this transaction + #[inline(always)] + pub fn payer(&mut self, payer: &'b solana_account_info::AccountInfo<'a>) -> &mut Self { + self.instruction.payer = Some(payer); + self + } + /// System Program + #[inline(always)] + pub fn system_program( + &mut self, + system_program: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.system_program = Some(system_program); + self + } + /// SPL Token Program + #[inline(always)] + pub fn token_program( + &mut self, + token_program: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.token_program = Some(token_program); + self + } + /// SysVar Rent + #[inline(always)] + pub fn rent(&mut self, rent: &'b solana_account_info::AccountInfo<'a>) -> &mut Self { + self.instruction.rent = Some(rent); + self + } + /// `[optional account]` + /// The mint address of the token to be used as the council mint + #[inline(always)] + pub fn council_token_mint( + &mut self, + council_token_mint: Option<&'b solana_account_info::AccountInfo<'a>>, + ) -> &mut Self { + self.instruction.council_token_mint = council_token_mint; + self + } + /// `[optional account]` + /// The account to hold the council tokens. + /// PDA seeds: ['governance',realm,council_mint] + /// + #[inline(always)] + pub fn council_token_holding_account( + &mut self, + council_token_holding_account: Option<&'b solana_account_info::AccountInfo<'a>>, + ) -> &mut Self { + self.instruction.council_token_holding_account = council_token_holding_account; + self + } + /// Realm Config account + #[inline(always)] + pub fn realm_config( + &mut self, + realm_config: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.realm_config = Some(realm_config); + self + } + /// `[optional account]` + /// Optional Community Voter Weight Addin Program Id + #[inline(always)] + pub fn community_voter_weight_addin( + &mut self, + community_voter_weight_addin: Option<&'b solana_account_info::AccountInfo<'a>>, + ) -> &mut Self { + self.instruction.community_voter_weight_addin = community_voter_weight_addin; + self + } + /// `[optional account]` + /// Optional Max Community Voter Weight Addin Program Id + #[inline(always)] + pub fn max_community_voter_weight_addin( + &mut self, + max_community_voter_weight_addin: Option<&'b solana_account_info::AccountInfo<'a>>, + ) -> &mut Self { + self.instruction.max_community_voter_weight_addin = max_community_voter_weight_addin; + self + } + /// `[optional account]` + /// Optional Council Voter Weight Addin Program Id + #[inline(always)] + pub fn council_voter_weight_addin( + &mut self, + council_voter_weight_addin: Option<&'b solana_account_info::AccountInfo<'a>>, + ) -> &mut Self { + self.instruction.council_voter_weight_addin = council_voter_weight_addin; + self + } + /// `[optional account]` + /// Optional Max Council Voter Weight Addin Program Id + #[inline(always)] + pub fn max_council_voter_weight_addin( + &mut self, + max_council_voter_weight_addin: Option<&'b solana_account_info::AccountInfo<'a>>, + ) -> &mut Self { + self.instruction.max_council_voter_weight_addin = max_council_voter_weight_addin; + self + } + #[inline(always)] + pub fn name(&mut self, name: String) -> &mut Self { + self.instruction.name = Some(name); + self + } + #[inline(always)] + pub fn config_args(&mut self, config_args: RealmConfigParams) -> &mut Self { + self.instruction.config_args = Some(config_args); + self + } + /// Add an additional account to the instruction. + #[inline(always)] + pub fn add_remaining_account( + &mut self, + account: &'b solana_account_info::AccountInfo<'a>, + is_writable: bool, + is_signer: bool, + ) -> &mut Self { + self.instruction + .__remaining_accounts + .push((account, is_writable, is_signer)); + self + } + /// Add additional accounts to the instruction. + /// + /// Each account is represented by a tuple of the `AccountInfo`, a `bool` indicating whether the account is writable or not, + /// and a `bool` indicating whether the account is a signer or not. + #[inline(always)] + pub fn add_remaining_accounts( + &mut self, + accounts: &[(&'b solana_account_info::AccountInfo<'a>, bool, bool)], + ) -> &mut Self { + self.instruction + .__remaining_accounts + .extend_from_slice(accounts); + self + } + #[inline(always)] + pub fn invoke(&self) -> solana_program_error::ProgramResult { + self.invoke_signed(&[]) + } + #[allow(clippy::clone_on_copy)] + #[allow(clippy::vec_init_then_push)] + pub fn invoke_signed(&self, signers_seeds: &[&[&[u8]]]) -> solana_program_error::ProgramResult { + let args = CreateRealmInstructionArgs { + name: self.instruction.name.clone().expect("name is not set"), + config_args: self + .instruction + .config_args + .clone() + .expect("config_args is not set"), + }; + let instruction = CreateRealmCpi { + __program: self.instruction.__program, + + realm_account: self + .instruction + .realm_account + .expect("realm_account is not set"), + + realm_authority: self + .instruction + .realm_authority + .expect("realm_authority is not set"), + + community_token_mint: self + .instruction + .community_token_mint + .expect("community_token_mint is not set"), + + community_token_holding_account: self + .instruction + .community_token_holding_account + .expect("community_token_holding_account is not set"), + + payer: self.instruction.payer.expect("payer is not set"), + + system_program: self + .instruction + .system_program + .expect("system_program is not set"), + + token_program: self + .instruction + .token_program + .expect("token_program is not set"), + + rent: self.instruction.rent.expect("rent is not set"), + + council_token_mint: self.instruction.council_token_mint, + + council_token_holding_account: self.instruction.council_token_holding_account, + + realm_config: self + .instruction + .realm_config + .expect("realm_config is not set"), + + community_voter_weight_addin: self.instruction.community_voter_weight_addin, + + max_community_voter_weight_addin: self.instruction.max_community_voter_weight_addin, + + council_voter_weight_addin: self.instruction.council_voter_weight_addin, + + max_council_voter_weight_addin: self.instruction.max_council_voter_weight_addin, + __args: args, + }; + instruction.invoke_signed_with_remaining_accounts( + signers_seeds, + &self.instruction.__remaining_accounts, + ) + } +} + +#[derive(Clone, Debug)] +struct CreateRealmCpiBuilderInstruction<'a, 'b> { + __program: &'b solana_account_info::AccountInfo<'a>, + realm_account: Option<&'b solana_account_info::AccountInfo<'a>>, + realm_authority: Option<&'b solana_account_info::AccountInfo<'a>>, + community_token_mint: Option<&'b solana_account_info::AccountInfo<'a>>, + community_token_holding_account: Option<&'b solana_account_info::AccountInfo<'a>>, + payer: Option<&'b solana_account_info::AccountInfo<'a>>, + system_program: Option<&'b solana_account_info::AccountInfo<'a>>, + token_program: Option<&'b solana_account_info::AccountInfo<'a>>, + rent: Option<&'b solana_account_info::AccountInfo<'a>>, + council_token_mint: Option<&'b solana_account_info::AccountInfo<'a>>, + council_token_holding_account: Option<&'b solana_account_info::AccountInfo<'a>>, + realm_config: Option<&'b solana_account_info::AccountInfo<'a>>, + community_voter_weight_addin: Option<&'b solana_account_info::AccountInfo<'a>>, + max_community_voter_weight_addin: Option<&'b solana_account_info::AccountInfo<'a>>, + council_voter_weight_addin: Option<&'b solana_account_info::AccountInfo<'a>>, + max_council_voter_weight_addin: Option<&'b solana_account_info::AccountInfo<'a>>, + name: Option, + config_args: Option, + /// Additional instruction accounts `(AccountInfo, is_writable, is_signer)`. + __remaining_accounts: Vec<(&'b solana_account_info::AccountInfo<'a>, bool, bool)>, +} diff --git a/e2e/governance/src/generated/instructions/create_token_governance.rs b/e2e/governance/src/generated/instructions/create_token_governance.rs new file mode 100644 index 0000000..50425d3 --- /dev/null +++ b/e2e/governance/src/generated/instructions/create_token_governance.rs @@ -0,0 +1,805 @@ +//! This code was AUTOGENERATED using the codama library. +//! Please DO NOT EDIT THIS FILE, instead use visitors +//! to add features, then rerun codama to update it. +//! +//! +//! + +use crate::generated::types::GovernanceConfig; +use borsh::BorshDeserialize; +use borsh::BorshSerialize; + +pub const CREATE_TOKEN_GOVERNANCE_DISCRIMINATOR: u8 = 18; + +/// Accounts. +#[derive(Debug)] +pub struct CreateTokenGovernance { + /// Realm account the created Governance belongs to + pub realm_account: solana_pubkey::Pubkey, + /// Token Governance account. seeds=['token-governance', realm, governed_token] + pub token_governance_account: solana_pubkey::Pubkey, + /// Token account governed by this Governance account + pub token_account: solana_pubkey::Pubkey, + /// Current token account authority (AccountOwner and optionally CloseAccount + pub token_account_authority: solana_pubkey::Pubkey, + /// Governing TokenOwnerRecord account (Used only if not signed by RealmAuthority + pub governing_token_owner_record: solana_pubkey::Pubkey, + + pub payer: solana_pubkey::Pubkey, + + pub token_program: solana_pubkey::Pubkey, + + pub system_program: solana_pubkey::Pubkey, + + pub governance_authority: solana_pubkey::Pubkey, + /// seeds=['realm-config', realm] + pub realm_config: solana_pubkey::Pubkey, + /// Optional Voter Weight Record + pub voter_weight_record: Option, +} + +impl CreateTokenGovernance { + pub fn instruction( + &self, + args: CreateTokenGovernanceInstructionArgs, + ) -> solana_instruction::Instruction { + self.instruction_with_remaining_accounts(args, &[]) + } + #[allow(clippy::arithmetic_side_effects)] + #[allow(clippy::vec_init_then_push)] + pub fn instruction_with_remaining_accounts( + &self, + args: CreateTokenGovernanceInstructionArgs, + remaining_accounts: &[solana_instruction::AccountMeta], + ) -> solana_instruction::Instruction { + let mut accounts = Vec::with_capacity(11 + remaining_accounts.len()); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.realm_account, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + self.token_governance_account, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + self.token_account, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.token_account_authority, + true, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.governing_token_owner_record, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.payer, true, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.token_program, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.system_program, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.governance_authority, + true, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.realm_config, + false, + )); + if let Some(voter_weight_record) = self.voter_weight_record { + accounts.push(solana_instruction::AccountMeta::new_readonly( + voter_weight_record, + false, + )); + } else { + accounts.push(solana_instruction::AccountMeta::new_readonly( + crate::SPL_GOVERNANCE_ID, + false, + )); + } + accounts.extend_from_slice(remaining_accounts); + let mut data = CreateTokenGovernanceInstructionData::new() + .try_to_vec() + .unwrap(); + let mut args = args.try_to_vec().unwrap(); + data.append(&mut args); + + solana_instruction::Instruction { + program_id: crate::SPL_GOVERNANCE_ID, + accounts, + data, + } + } +} + +#[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct CreateTokenGovernanceInstructionData { + discriminator: u8, +} + +impl CreateTokenGovernanceInstructionData { + pub fn new() -> Self { + Self { discriminator: 18 } + } + + pub(crate) fn try_to_vec(&self) -> Result, std::io::Error> { + borsh::to_vec(self) + } +} + +impl Default for CreateTokenGovernanceInstructionData { + fn default() -> Self { + Self::new() + } +} + +#[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct CreateTokenGovernanceInstructionArgs { + pub config: GovernanceConfig, + pub transfer_account_authorities: bool, +} + +impl CreateTokenGovernanceInstructionArgs { + pub(crate) fn try_to_vec(&self) -> Result, std::io::Error> { + borsh::to_vec(self) + } +} + +/// Instruction builder for `CreateTokenGovernance`. +/// +/// ### Accounts: +/// +/// 0. `[]` realm_account +/// 1. `[writable]` token_governance_account +/// 2. `[writable]` token_account +/// 3. `[signer]` token_account_authority +/// 4. `[]` governing_token_owner_record +/// 5. `[signer]` payer +/// 6. `[optional]` token_program (default to `TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA`) +/// 7. `[optional]` system_program (default to `11111111111111111111111111111111`) +/// 8. `[signer]` governance_authority +/// 9. `[]` realm_config +/// 10. `[optional]` voter_weight_record +#[derive(Clone, Debug, Default)] +pub struct CreateTokenGovernanceBuilder { + realm_account: Option, + token_governance_account: Option, + token_account: Option, + token_account_authority: Option, + governing_token_owner_record: Option, + payer: Option, + token_program: Option, + system_program: Option, + governance_authority: Option, + realm_config: Option, + voter_weight_record: Option, + config: Option, + transfer_account_authorities: Option, + __remaining_accounts: Vec, +} + +impl CreateTokenGovernanceBuilder { + pub fn new() -> Self { + Self::default() + } + /// Realm account the created Governance belongs to + #[inline(always)] + pub fn realm_account(&mut self, realm_account: solana_pubkey::Pubkey) -> &mut Self { + self.realm_account = Some(realm_account); + self + } + /// Token Governance account. seeds=['token-governance', realm, governed_token] + #[inline(always)] + pub fn token_governance_account( + &mut self, + token_governance_account: solana_pubkey::Pubkey, + ) -> &mut Self { + self.token_governance_account = Some(token_governance_account); + self + } + /// Token account governed by this Governance account + #[inline(always)] + pub fn token_account(&mut self, token_account: solana_pubkey::Pubkey) -> &mut Self { + self.token_account = Some(token_account); + self + } + /// Current token account authority (AccountOwner and optionally CloseAccount + #[inline(always)] + pub fn token_account_authority( + &mut self, + token_account_authority: solana_pubkey::Pubkey, + ) -> &mut Self { + self.token_account_authority = Some(token_account_authority); + self + } + /// Governing TokenOwnerRecord account (Used only if not signed by RealmAuthority + #[inline(always)] + pub fn governing_token_owner_record( + &mut self, + governing_token_owner_record: solana_pubkey::Pubkey, + ) -> &mut Self { + self.governing_token_owner_record = Some(governing_token_owner_record); + self + } + #[inline(always)] + pub fn payer(&mut self, payer: solana_pubkey::Pubkey) -> &mut Self { + self.payer = Some(payer); + self + } + /// `[optional account, default to 'TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA']` + #[inline(always)] + pub fn token_program(&mut self, token_program: solana_pubkey::Pubkey) -> &mut Self { + self.token_program = Some(token_program); + self + } + /// `[optional account, default to '11111111111111111111111111111111']` + #[inline(always)] + pub fn system_program(&mut self, system_program: solana_pubkey::Pubkey) -> &mut Self { + self.system_program = Some(system_program); + self + } + #[inline(always)] + pub fn governance_authority( + &mut self, + governance_authority: solana_pubkey::Pubkey, + ) -> &mut Self { + self.governance_authority = Some(governance_authority); + self + } + /// seeds=['realm-config', realm] + #[inline(always)] + pub fn realm_config(&mut self, realm_config: solana_pubkey::Pubkey) -> &mut Self { + self.realm_config = Some(realm_config); + self + } + /// `[optional account]` + /// Optional Voter Weight Record + #[inline(always)] + pub fn voter_weight_record( + &mut self, + voter_weight_record: Option, + ) -> &mut Self { + self.voter_weight_record = voter_weight_record; + self + } + #[inline(always)] + pub fn config(&mut self, config: GovernanceConfig) -> &mut Self { + self.config = Some(config); + self + } + #[inline(always)] + pub fn transfer_account_authorities( + &mut self, + transfer_account_authorities: bool, + ) -> &mut Self { + self.transfer_account_authorities = Some(transfer_account_authorities); + self + } + /// Add an additional account to the instruction. + #[inline(always)] + pub fn add_remaining_account(&mut self, account: solana_instruction::AccountMeta) -> &mut Self { + self.__remaining_accounts.push(account); + self + } + /// Add additional accounts to the instruction. + #[inline(always)] + pub fn add_remaining_accounts( + &mut self, + accounts: &[solana_instruction::AccountMeta], + ) -> &mut Self { + self.__remaining_accounts.extend_from_slice(accounts); + self + } + #[allow(clippy::clone_on_copy)] + pub fn instruction(&self) -> solana_instruction::Instruction { + let accounts = CreateTokenGovernance { + realm_account: self.realm_account.expect("realm_account is not set"), + token_governance_account: self + .token_governance_account + .expect("token_governance_account is not set"), + token_account: self.token_account.expect("token_account is not set"), + token_account_authority: self + .token_account_authority + .expect("token_account_authority is not set"), + governing_token_owner_record: self + .governing_token_owner_record + .expect("governing_token_owner_record is not set"), + payer: self.payer.expect("payer is not set"), + token_program: self.token_program.unwrap_or(solana_pubkey::pubkey!( + "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA" + )), + system_program: self + .system_program + .unwrap_or(solana_pubkey::pubkey!("11111111111111111111111111111111")), + governance_authority: self + .governance_authority + .expect("governance_authority is not set"), + realm_config: self.realm_config.expect("realm_config is not set"), + voter_weight_record: self.voter_weight_record, + }; + let args = CreateTokenGovernanceInstructionArgs { + config: self.config.clone().expect("config is not set"), + transfer_account_authorities: self + .transfer_account_authorities + .clone() + .expect("transfer_account_authorities is not set"), + }; + + accounts.instruction_with_remaining_accounts(args, &self.__remaining_accounts) + } +} + +/// `create_token_governance` CPI accounts. +pub struct CreateTokenGovernanceCpiAccounts<'a, 'b> { + /// Realm account the created Governance belongs to + pub realm_account: &'b solana_account_info::AccountInfo<'a>, + /// Token Governance account. seeds=['token-governance', realm, governed_token] + pub token_governance_account: &'b solana_account_info::AccountInfo<'a>, + /// Token account governed by this Governance account + pub token_account: &'b solana_account_info::AccountInfo<'a>, + /// Current token account authority (AccountOwner and optionally CloseAccount + pub token_account_authority: &'b solana_account_info::AccountInfo<'a>, + /// Governing TokenOwnerRecord account (Used only if not signed by RealmAuthority + pub governing_token_owner_record: &'b solana_account_info::AccountInfo<'a>, + + pub payer: &'b solana_account_info::AccountInfo<'a>, + + pub token_program: &'b solana_account_info::AccountInfo<'a>, + + pub system_program: &'b solana_account_info::AccountInfo<'a>, + + pub governance_authority: &'b solana_account_info::AccountInfo<'a>, + /// seeds=['realm-config', realm] + pub realm_config: &'b solana_account_info::AccountInfo<'a>, + /// Optional Voter Weight Record + pub voter_weight_record: Option<&'b solana_account_info::AccountInfo<'a>>, +} + +/// `create_token_governance` CPI instruction. +pub struct CreateTokenGovernanceCpi<'a, 'b> { + /// The program to invoke. + pub __program: &'b solana_account_info::AccountInfo<'a>, + /// Realm account the created Governance belongs to + pub realm_account: &'b solana_account_info::AccountInfo<'a>, + /// Token Governance account. seeds=['token-governance', realm, governed_token] + pub token_governance_account: &'b solana_account_info::AccountInfo<'a>, + /// Token account governed by this Governance account + pub token_account: &'b solana_account_info::AccountInfo<'a>, + /// Current token account authority (AccountOwner and optionally CloseAccount + pub token_account_authority: &'b solana_account_info::AccountInfo<'a>, + /// Governing TokenOwnerRecord account (Used only if not signed by RealmAuthority + pub governing_token_owner_record: &'b solana_account_info::AccountInfo<'a>, + + pub payer: &'b solana_account_info::AccountInfo<'a>, + + pub token_program: &'b solana_account_info::AccountInfo<'a>, + + pub system_program: &'b solana_account_info::AccountInfo<'a>, + + pub governance_authority: &'b solana_account_info::AccountInfo<'a>, + /// seeds=['realm-config', realm] + pub realm_config: &'b solana_account_info::AccountInfo<'a>, + /// Optional Voter Weight Record + pub voter_weight_record: Option<&'b solana_account_info::AccountInfo<'a>>, + /// The arguments for the instruction. + pub __args: CreateTokenGovernanceInstructionArgs, +} + +impl<'a, 'b> CreateTokenGovernanceCpi<'a, 'b> { + pub fn new( + program: &'b solana_account_info::AccountInfo<'a>, + accounts: CreateTokenGovernanceCpiAccounts<'a, 'b>, + args: CreateTokenGovernanceInstructionArgs, + ) -> Self { + Self { + __program: program, + realm_account: accounts.realm_account, + token_governance_account: accounts.token_governance_account, + token_account: accounts.token_account, + token_account_authority: accounts.token_account_authority, + governing_token_owner_record: accounts.governing_token_owner_record, + payer: accounts.payer, + token_program: accounts.token_program, + system_program: accounts.system_program, + governance_authority: accounts.governance_authority, + realm_config: accounts.realm_config, + voter_weight_record: accounts.voter_weight_record, + __args: args, + } + } + #[inline(always)] + pub fn invoke(&self) -> solana_program_error::ProgramResult { + self.invoke_signed_with_remaining_accounts(&[], &[]) + } + #[inline(always)] + pub fn invoke_with_remaining_accounts( + &self, + remaining_accounts: &[(&'b solana_account_info::AccountInfo<'a>, bool, bool)], + ) -> solana_program_error::ProgramResult { + self.invoke_signed_with_remaining_accounts(&[], remaining_accounts) + } + #[inline(always)] + pub fn invoke_signed(&self, signers_seeds: &[&[&[u8]]]) -> solana_program_error::ProgramResult { + self.invoke_signed_with_remaining_accounts(signers_seeds, &[]) + } + #[allow(clippy::arithmetic_side_effects)] + #[allow(clippy::clone_on_copy)] + #[allow(clippy::vec_init_then_push)] + pub fn invoke_signed_with_remaining_accounts( + &self, + signers_seeds: &[&[&[u8]]], + remaining_accounts: &[(&'b solana_account_info::AccountInfo<'a>, bool, bool)], + ) -> solana_program_error::ProgramResult { + let mut accounts = Vec::with_capacity(11 + remaining_accounts.len()); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.realm_account.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + *self.token_governance_account.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + *self.token_account.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.token_account_authority.key, + true, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.governing_token_owner_record.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.payer.key, + true, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.token_program.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.system_program.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.governance_authority.key, + true, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.realm_config.key, + false, + )); + if let Some(voter_weight_record) = self.voter_weight_record { + accounts.push(solana_instruction::AccountMeta::new_readonly( + *voter_weight_record.key, + false, + )); + } else { + accounts.push(solana_instruction::AccountMeta::new_readonly( + crate::SPL_GOVERNANCE_ID, + false, + )); + } + remaining_accounts.iter().for_each(|remaining_account| { + accounts.push(solana_instruction::AccountMeta { + pubkey: *remaining_account.0.key, + is_signer: remaining_account.1, + is_writable: remaining_account.2, + }) + }); + let mut data = CreateTokenGovernanceInstructionData::new() + .try_to_vec() + .unwrap(); + let mut args = self.__args.try_to_vec().unwrap(); + data.append(&mut args); + + let instruction = solana_instruction::Instruction { + program_id: crate::SPL_GOVERNANCE_ID, + accounts, + data, + }; + let mut account_infos = Vec::with_capacity(12 + remaining_accounts.len()); + account_infos.push(self.__program.clone()); + account_infos.push(self.realm_account.clone()); + account_infos.push(self.token_governance_account.clone()); + account_infos.push(self.token_account.clone()); + account_infos.push(self.token_account_authority.clone()); + account_infos.push(self.governing_token_owner_record.clone()); + account_infos.push(self.payer.clone()); + account_infos.push(self.token_program.clone()); + account_infos.push(self.system_program.clone()); + account_infos.push(self.governance_authority.clone()); + account_infos.push(self.realm_config.clone()); + if let Some(voter_weight_record) = self.voter_weight_record { + account_infos.push(voter_weight_record.clone()); + } + remaining_accounts + .iter() + .for_each(|remaining_account| account_infos.push(remaining_account.0.clone())); + + if signers_seeds.is_empty() { + solana_cpi::invoke(&instruction, &account_infos) + } else { + solana_cpi::invoke_signed(&instruction, &account_infos, signers_seeds) + } + } +} + +/// Instruction builder for `CreateTokenGovernance` via CPI. +/// +/// ### Accounts: +/// +/// 0. `[]` realm_account +/// 1. `[writable]` token_governance_account +/// 2. `[writable]` token_account +/// 3. `[signer]` token_account_authority +/// 4. `[]` governing_token_owner_record +/// 5. `[signer]` payer +/// 6. `[]` token_program +/// 7. `[]` system_program +/// 8. `[signer]` governance_authority +/// 9. `[]` realm_config +/// 10. `[optional]` voter_weight_record +#[derive(Clone, Debug)] +pub struct CreateTokenGovernanceCpiBuilder<'a, 'b> { + instruction: Box>, +} + +impl<'a, 'b> CreateTokenGovernanceCpiBuilder<'a, 'b> { + pub fn new(program: &'b solana_account_info::AccountInfo<'a>) -> Self { + let instruction = Box::new(CreateTokenGovernanceCpiBuilderInstruction { + __program: program, + realm_account: None, + token_governance_account: None, + token_account: None, + token_account_authority: None, + governing_token_owner_record: None, + payer: None, + token_program: None, + system_program: None, + governance_authority: None, + realm_config: None, + voter_weight_record: None, + config: None, + transfer_account_authorities: None, + __remaining_accounts: Vec::new(), + }); + Self { instruction } + } + /// Realm account the created Governance belongs to + #[inline(always)] + pub fn realm_account( + &mut self, + realm_account: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.realm_account = Some(realm_account); + self + } + /// Token Governance account. seeds=['token-governance', realm, governed_token] + #[inline(always)] + pub fn token_governance_account( + &mut self, + token_governance_account: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.token_governance_account = Some(token_governance_account); + self + } + /// Token account governed by this Governance account + #[inline(always)] + pub fn token_account( + &mut self, + token_account: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.token_account = Some(token_account); + self + } + /// Current token account authority (AccountOwner and optionally CloseAccount + #[inline(always)] + pub fn token_account_authority( + &mut self, + token_account_authority: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.token_account_authority = Some(token_account_authority); + self + } + /// Governing TokenOwnerRecord account (Used only if not signed by RealmAuthority + #[inline(always)] + pub fn governing_token_owner_record( + &mut self, + governing_token_owner_record: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.governing_token_owner_record = Some(governing_token_owner_record); + self + } + #[inline(always)] + pub fn payer(&mut self, payer: &'b solana_account_info::AccountInfo<'a>) -> &mut Self { + self.instruction.payer = Some(payer); + self + } + #[inline(always)] + pub fn token_program( + &mut self, + token_program: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.token_program = Some(token_program); + self + } + #[inline(always)] + pub fn system_program( + &mut self, + system_program: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.system_program = Some(system_program); + self + } + #[inline(always)] + pub fn governance_authority( + &mut self, + governance_authority: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.governance_authority = Some(governance_authority); + self + } + /// seeds=['realm-config', realm] + #[inline(always)] + pub fn realm_config( + &mut self, + realm_config: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.realm_config = Some(realm_config); + self + } + /// `[optional account]` + /// Optional Voter Weight Record + #[inline(always)] + pub fn voter_weight_record( + &mut self, + voter_weight_record: Option<&'b solana_account_info::AccountInfo<'a>>, + ) -> &mut Self { + self.instruction.voter_weight_record = voter_weight_record; + self + } + #[inline(always)] + pub fn config(&mut self, config: GovernanceConfig) -> &mut Self { + self.instruction.config = Some(config); + self + } + #[inline(always)] + pub fn transfer_account_authorities( + &mut self, + transfer_account_authorities: bool, + ) -> &mut Self { + self.instruction.transfer_account_authorities = Some(transfer_account_authorities); + self + } + /// Add an additional account to the instruction. + #[inline(always)] + pub fn add_remaining_account( + &mut self, + account: &'b solana_account_info::AccountInfo<'a>, + is_writable: bool, + is_signer: bool, + ) -> &mut Self { + self.instruction + .__remaining_accounts + .push((account, is_writable, is_signer)); + self + } + /// Add additional accounts to the instruction. + /// + /// Each account is represented by a tuple of the `AccountInfo`, a `bool` indicating whether the account is writable or not, + /// and a `bool` indicating whether the account is a signer or not. + #[inline(always)] + pub fn add_remaining_accounts( + &mut self, + accounts: &[(&'b solana_account_info::AccountInfo<'a>, bool, bool)], + ) -> &mut Self { + self.instruction + .__remaining_accounts + .extend_from_slice(accounts); + self + } + #[inline(always)] + pub fn invoke(&self) -> solana_program_error::ProgramResult { + self.invoke_signed(&[]) + } + #[allow(clippy::clone_on_copy)] + #[allow(clippy::vec_init_then_push)] + pub fn invoke_signed(&self, signers_seeds: &[&[&[u8]]]) -> solana_program_error::ProgramResult { + let args = CreateTokenGovernanceInstructionArgs { + config: self.instruction.config.clone().expect("config is not set"), + transfer_account_authorities: self + .instruction + .transfer_account_authorities + .clone() + .expect("transfer_account_authorities is not set"), + }; + let instruction = CreateTokenGovernanceCpi { + __program: self.instruction.__program, + + realm_account: self + .instruction + .realm_account + .expect("realm_account is not set"), + + token_governance_account: self + .instruction + .token_governance_account + .expect("token_governance_account is not set"), + + token_account: self + .instruction + .token_account + .expect("token_account is not set"), + + token_account_authority: self + .instruction + .token_account_authority + .expect("token_account_authority is not set"), + + governing_token_owner_record: self + .instruction + .governing_token_owner_record + .expect("governing_token_owner_record is not set"), + + payer: self.instruction.payer.expect("payer is not set"), + + token_program: self + .instruction + .token_program + .expect("token_program is not set"), + + system_program: self + .instruction + .system_program + .expect("system_program is not set"), + + governance_authority: self + .instruction + .governance_authority + .expect("governance_authority is not set"), + + realm_config: self + .instruction + .realm_config + .expect("realm_config is not set"), + + voter_weight_record: self.instruction.voter_weight_record, + __args: args, + }; + instruction.invoke_signed_with_remaining_accounts( + signers_seeds, + &self.instruction.__remaining_accounts, + ) + } +} + +#[derive(Clone, Debug)] +struct CreateTokenGovernanceCpiBuilderInstruction<'a, 'b> { + __program: &'b solana_account_info::AccountInfo<'a>, + realm_account: Option<&'b solana_account_info::AccountInfo<'a>>, + token_governance_account: Option<&'b solana_account_info::AccountInfo<'a>>, + token_account: Option<&'b solana_account_info::AccountInfo<'a>>, + token_account_authority: Option<&'b solana_account_info::AccountInfo<'a>>, + governing_token_owner_record: Option<&'b solana_account_info::AccountInfo<'a>>, + payer: Option<&'b solana_account_info::AccountInfo<'a>>, + token_program: Option<&'b solana_account_info::AccountInfo<'a>>, + system_program: Option<&'b solana_account_info::AccountInfo<'a>>, + governance_authority: Option<&'b solana_account_info::AccountInfo<'a>>, + realm_config: Option<&'b solana_account_info::AccountInfo<'a>>, + voter_weight_record: Option<&'b solana_account_info::AccountInfo<'a>>, + config: Option, + transfer_account_authorities: Option, + /// Additional instruction accounts `(AccountInfo, is_writable, is_signer)`. + __remaining_accounts: Vec<(&'b solana_account_info::AccountInfo<'a>, bool, bool)>, +} diff --git a/e2e/governance/src/generated/instructions/create_token_owner_record.rs b/e2e/governance/src/generated/instructions/create_token_owner_record.rs new file mode 100644 index 0000000..25b7c74 --- /dev/null +++ b/e2e/governance/src/generated/instructions/create_token_owner_record.rs @@ -0,0 +1,488 @@ +//! This code was AUTOGENERATED using the codama library. +//! Please DO NOT EDIT THIS FILE, instead use visitors +//! to add features, then rerun codama to update it. +//! +//! +//! + +use borsh::BorshDeserialize; +use borsh::BorshSerialize; + +pub const CREATE_TOKEN_OWNER_RECORD_DISCRIMINATOR: u8 = 23; + +/// Accounts. +#[derive(Debug)] +pub struct CreateTokenOwnerRecord { + pub realm_account: solana_pubkey::Pubkey, + + pub governing_token_owner_account: solana_pubkey::Pubkey, + /// seeds=['governance', realm, governing_token_mint, governing_token_owner] + pub token_owner_record: solana_pubkey::Pubkey, + + pub governing_token_mint: solana_pubkey::Pubkey, + + pub payer: solana_pubkey::Pubkey, + + pub system_program: solana_pubkey::Pubkey, +} + +impl CreateTokenOwnerRecord { + pub fn instruction(&self) -> solana_instruction::Instruction { + self.instruction_with_remaining_accounts(&[]) + } + #[allow(clippy::arithmetic_side_effects)] + #[allow(clippy::vec_init_then_push)] + pub fn instruction_with_remaining_accounts( + &self, + remaining_accounts: &[solana_instruction::AccountMeta], + ) -> solana_instruction::Instruction { + let mut accounts = Vec::with_capacity(6 + remaining_accounts.len()); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.realm_account, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.governing_token_owner_account, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + self.token_owner_record, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.governing_token_mint, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.payer, true, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.system_program, + false, + )); + accounts.extend_from_slice(remaining_accounts); + let data = CreateTokenOwnerRecordInstructionData::new() + .try_to_vec() + .unwrap(); + + solana_instruction::Instruction { + program_id: crate::SPL_GOVERNANCE_ID, + accounts, + data, + } + } +} + +#[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct CreateTokenOwnerRecordInstructionData { + discriminator: u8, +} + +impl CreateTokenOwnerRecordInstructionData { + pub fn new() -> Self { + Self { discriminator: 23 } + } + + pub(crate) fn try_to_vec(&self) -> Result, std::io::Error> { + borsh::to_vec(self) + } +} + +impl Default for CreateTokenOwnerRecordInstructionData { + fn default() -> Self { + Self::new() + } +} + +/// Instruction builder for `CreateTokenOwnerRecord`. +/// +/// ### Accounts: +/// +/// 0. `[]` realm_account +/// 1. `[]` governing_token_owner_account +/// 2. `[writable]` token_owner_record +/// 3. `[]` governing_token_mint +/// 4. `[signer]` payer +/// 5. `[optional]` system_program (default to `11111111111111111111111111111111`) +#[derive(Clone, Debug, Default)] +pub struct CreateTokenOwnerRecordBuilder { + realm_account: Option, + governing_token_owner_account: Option, + token_owner_record: Option, + governing_token_mint: Option, + payer: Option, + system_program: Option, + __remaining_accounts: Vec, +} + +impl CreateTokenOwnerRecordBuilder { + pub fn new() -> Self { + Self::default() + } + #[inline(always)] + pub fn realm_account(&mut self, realm_account: solana_pubkey::Pubkey) -> &mut Self { + self.realm_account = Some(realm_account); + self + } + #[inline(always)] + pub fn governing_token_owner_account( + &mut self, + governing_token_owner_account: solana_pubkey::Pubkey, + ) -> &mut Self { + self.governing_token_owner_account = Some(governing_token_owner_account); + self + } + /// seeds=['governance', realm, governing_token_mint, governing_token_owner] + #[inline(always)] + pub fn token_owner_record(&mut self, token_owner_record: solana_pubkey::Pubkey) -> &mut Self { + self.token_owner_record = Some(token_owner_record); + self + } + #[inline(always)] + pub fn governing_token_mint( + &mut self, + governing_token_mint: solana_pubkey::Pubkey, + ) -> &mut Self { + self.governing_token_mint = Some(governing_token_mint); + self + } + #[inline(always)] + pub fn payer(&mut self, payer: solana_pubkey::Pubkey) -> &mut Self { + self.payer = Some(payer); + self + } + /// `[optional account, default to '11111111111111111111111111111111']` + #[inline(always)] + pub fn system_program(&mut self, system_program: solana_pubkey::Pubkey) -> &mut Self { + self.system_program = Some(system_program); + self + } + /// Add an additional account to the instruction. + #[inline(always)] + pub fn add_remaining_account(&mut self, account: solana_instruction::AccountMeta) -> &mut Self { + self.__remaining_accounts.push(account); + self + } + /// Add additional accounts to the instruction. + #[inline(always)] + pub fn add_remaining_accounts( + &mut self, + accounts: &[solana_instruction::AccountMeta], + ) -> &mut Self { + self.__remaining_accounts.extend_from_slice(accounts); + self + } + #[allow(clippy::clone_on_copy)] + pub fn instruction(&self) -> solana_instruction::Instruction { + let accounts = CreateTokenOwnerRecord { + realm_account: self.realm_account.expect("realm_account is not set"), + governing_token_owner_account: self + .governing_token_owner_account + .expect("governing_token_owner_account is not set"), + token_owner_record: self + .token_owner_record + .expect("token_owner_record is not set"), + governing_token_mint: self + .governing_token_mint + .expect("governing_token_mint is not set"), + payer: self.payer.expect("payer is not set"), + system_program: self + .system_program + .unwrap_or(solana_pubkey::pubkey!("11111111111111111111111111111111")), + }; + + accounts.instruction_with_remaining_accounts(&self.__remaining_accounts) + } +} + +/// `create_token_owner_record` CPI accounts. +pub struct CreateTokenOwnerRecordCpiAccounts<'a, 'b> { + pub realm_account: &'b solana_account_info::AccountInfo<'a>, + + pub governing_token_owner_account: &'b solana_account_info::AccountInfo<'a>, + /// seeds=['governance', realm, governing_token_mint, governing_token_owner] + pub token_owner_record: &'b solana_account_info::AccountInfo<'a>, + + pub governing_token_mint: &'b solana_account_info::AccountInfo<'a>, + + pub payer: &'b solana_account_info::AccountInfo<'a>, + + pub system_program: &'b solana_account_info::AccountInfo<'a>, +} + +/// `create_token_owner_record` CPI instruction. +pub struct CreateTokenOwnerRecordCpi<'a, 'b> { + /// The program to invoke. + pub __program: &'b solana_account_info::AccountInfo<'a>, + + pub realm_account: &'b solana_account_info::AccountInfo<'a>, + + pub governing_token_owner_account: &'b solana_account_info::AccountInfo<'a>, + /// seeds=['governance', realm, governing_token_mint, governing_token_owner] + pub token_owner_record: &'b solana_account_info::AccountInfo<'a>, + + pub governing_token_mint: &'b solana_account_info::AccountInfo<'a>, + + pub payer: &'b solana_account_info::AccountInfo<'a>, + + pub system_program: &'b solana_account_info::AccountInfo<'a>, +} + +impl<'a, 'b> CreateTokenOwnerRecordCpi<'a, 'b> { + pub fn new( + program: &'b solana_account_info::AccountInfo<'a>, + accounts: CreateTokenOwnerRecordCpiAccounts<'a, 'b>, + ) -> Self { + Self { + __program: program, + realm_account: accounts.realm_account, + governing_token_owner_account: accounts.governing_token_owner_account, + token_owner_record: accounts.token_owner_record, + governing_token_mint: accounts.governing_token_mint, + payer: accounts.payer, + system_program: accounts.system_program, + } + } + #[inline(always)] + pub fn invoke(&self) -> solana_program_error::ProgramResult { + self.invoke_signed_with_remaining_accounts(&[], &[]) + } + #[inline(always)] + pub fn invoke_with_remaining_accounts( + &self, + remaining_accounts: &[(&'b solana_account_info::AccountInfo<'a>, bool, bool)], + ) -> solana_program_error::ProgramResult { + self.invoke_signed_with_remaining_accounts(&[], remaining_accounts) + } + #[inline(always)] + pub fn invoke_signed(&self, signers_seeds: &[&[&[u8]]]) -> solana_program_error::ProgramResult { + self.invoke_signed_with_remaining_accounts(signers_seeds, &[]) + } + #[allow(clippy::arithmetic_side_effects)] + #[allow(clippy::clone_on_copy)] + #[allow(clippy::vec_init_then_push)] + pub fn invoke_signed_with_remaining_accounts( + &self, + signers_seeds: &[&[&[u8]]], + remaining_accounts: &[(&'b solana_account_info::AccountInfo<'a>, bool, bool)], + ) -> solana_program_error::ProgramResult { + let mut accounts = Vec::with_capacity(6 + remaining_accounts.len()); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.realm_account.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.governing_token_owner_account.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + *self.token_owner_record.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.governing_token_mint.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.payer.key, + true, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.system_program.key, + false, + )); + remaining_accounts.iter().for_each(|remaining_account| { + accounts.push(solana_instruction::AccountMeta { + pubkey: *remaining_account.0.key, + is_signer: remaining_account.1, + is_writable: remaining_account.2, + }) + }); + let data = CreateTokenOwnerRecordInstructionData::new() + .try_to_vec() + .unwrap(); + + let instruction = solana_instruction::Instruction { + program_id: crate::SPL_GOVERNANCE_ID, + accounts, + data, + }; + let mut account_infos = Vec::with_capacity(7 + remaining_accounts.len()); + account_infos.push(self.__program.clone()); + account_infos.push(self.realm_account.clone()); + account_infos.push(self.governing_token_owner_account.clone()); + account_infos.push(self.token_owner_record.clone()); + account_infos.push(self.governing_token_mint.clone()); + account_infos.push(self.payer.clone()); + account_infos.push(self.system_program.clone()); + remaining_accounts + .iter() + .for_each(|remaining_account| account_infos.push(remaining_account.0.clone())); + + if signers_seeds.is_empty() { + solana_cpi::invoke(&instruction, &account_infos) + } else { + solana_cpi::invoke_signed(&instruction, &account_infos, signers_seeds) + } + } +} + +/// Instruction builder for `CreateTokenOwnerRecord` via CPI. +/// +/// ### Accounts: +/// +/// 0. `[]` realm_account +/// 1. `[]` governing_token_owner_account +/// 2. `[writable]` token_owner_record +/// 3. `[]` governing_token_mint +/// 4. `[signer]` payer +/// 5. `[]` system_program +#[derive(Clone, Debug)] +pub struct CreateTokenOwnerRecordCpiBuilder<'a, 'b> { + instruction: Box>, +} + +impl<'a, 'b> CreateTokenOwnerRecordCpiBuilder<'a, 'b> { + pub fn new(program: &'b solana_account_info::AccountInfo<'a>) -> Self { + let instruction = Box::new(CreateTokenOwnerRecordCpiBuilderInstruction { + __program: program, + realm_account: None, + governing_token_owner_account: None, + token_owner_record: None, + governing_token_mint: None, + payer: None, + system_program: None, + __remaining_accounts: Vec::new(), + }); + Self { instruction } + } + #[inline(always)] + pub fn realm_account( + &mut self, + realm_account: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.realm_account = Some(realm_account); + self + } + #[inline(always)] + pub fn governing_token_owner_account( + &mut self, + governing_token_owner_account: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.governing_token_owner_account = Some(governing_token_owner_account); + self + } + /// seeds=['governance', realm, governing_token_mint, governing_token_owner] + #[inline(always)] + pub fn token_owner_record( + &mut self, + token_owner_record: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.token_owner_record = Some(token_owner_record); + self + } + #[inline(always)] + pub fn governing_token_mint( + &mut self, + governing_token_mint: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.governing_token_mint = Some(governing_token_mint); + self + } + #[inline(always)] + pub fn payer(&mut self, payer: &'b solana_account_info::AccountInfo<'a>) -> &mut Self { + self.instruction.payer = Some(payer); + self + } + #[inline(always)] + pub fn system_program( + &mut self, + system_program: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.system_program = Some(system_program); + self + } + /// Add an additional account to the instruction. + #[inline(always)] + pub fn add_remaining_account( + &mut self, + account: &'b solana_account_info::AccountInfo<'a>, + is_writable: bool, + is_signer: bool, + ) -> &mut Self { + self.instruction + .__remaining_accounts + .push((account, is_writable, is_signer)); + self + } + /// Add additional accounts to the instruction. + /// + /// Each account is represented by a tuple of the `AccountInfo`, a `bool` indicating whether the account is writable or not, + /// and a `bool` indicating whether the account is a signer or not. + #[inline(always)] + pub fn add_remaining_accounts( + &mut self, + accounts: &[(&'b solana_account_info::AccountInfo<'a>, bool, bool)], + ) -> &mut Self { + self.instruction + .__remaining_accounts + .extend_from_slice(accounts); + self + } + #[inline(always)] + pub fn invoke(&self) -> solana_program_error::ProgramResult { + self.invoke_signed(&[]) + } + #[allow(clippy::clone_on_copy)] + #[allow(clippy::vec_init_then_push)] + pub fn invoke_signed(&self, signers_seeds: &[&[&[u8]]]) -> solana_program_error::ProgramResult { + let instruction = CreateTokenOwnerRecordCpi { + __program: self.instruction.__program, + + realm_account: self + .instruction + .realm_account + .expect("realm_account is not set"), + + governing_token_owner_account: self + .instruction + .governing_token_owner_account + .expect("governing_token_owner_account is not set"), + + token_owner_record: self + .instruction + .token_owner_record + .expect("token_owner_record is not set"), + + governing_token_mint: self + .instruction + .governing_token_mint + .expect("governing_token_mint is not set"), + + payer: self.instruction.payer.expect("payer is not set"), + + system_program: self + .instruction + .system_program + .expect("system_program is not set"), + }; + instruction.invoke_signed_with_remaining_accounts( + signers_seeds, + &self.instruction.__remaining_accounts, + ) + } +} + +#[derive(Clone, Debug)] +struct CreateTokenOwnerRecordCpiBuilderInstruction<'a, 'b> { + __program: &'b solana_account_info::AccountInfo<'a>, + realm_account: Option<&'b solana_account_info::AccountInfo<'a>>, + governing_token_owner_account: Option<&'b solana_account_info::AccountInfo<'a>>, + token_owner_record: Option<&'b solana_account_info::AccountInfo<'a>>, + governing_token_mint: Option<&'b solana_account_info::AccountInfo<'a>>, + payer: Option<&'b solana_account_info::AccountInfo<'a>>, + system_program: Option<&'b solana_account_info::AccountInfo<'a>>, + /// Additional instruction accounts `(AccountInfo, is_writable, is_signer)`. + __remaining_accounts: Vec<(&'b solana_account_info::AccountInfo<'a>, bool, bool)>, +} diff --git a/e2e/governance/src/generated/instructions/deposit_governing_tokens.rs b/e2e/governance/src/generated/instructions/deposit_governing_tokens.rs new file mode 100644 index 0000000..a4390ae --- /dev/null +++ b/e2e/governance/src/generated/instructions/deposit_governing_tokens.rs @@ -0,0 +1,716 @@ +//! This code was AUTOGENERATED using the codama library. +//! Please DO NOT EDIT THIS FILE, instead use visitors +//! to add features, then rerun codama to update it. +//! +//! +//! + +use borsh::BorshDeserialize; +use borsh::BorshSerialize; + +pub const DEPOSIT_GOVERNING_TOKENS_DISCRIMINATOR: u8 = 1; + +/// Accounts. +#[derive(Debug)] +pub struct DepositGoverningTokens { + pub realm_account: solana_pubkey::Pubkey, + /// seeds=['governance', realm, governing_token_mint] + pub governing_token_holding_account: solana_pubkey::Pubkey, + /// It can either be spl-token TokenAccount or MintAccount. Tokens will be transferred or minted to the holding account + pub governing_token_source_account: solana_pubkey::Pubkey, + + pub governing_token_owner_account: solana_pubkey::Pubkey, + /// It should be owner for TokenAccount and mint_authority for MintAccount + pub governing_token_source_account_authority: solana_pubkey::Pubkey, + /// seeds=['governance', realm, governing_token_mint, governing_token_owner] + pub token_owner_record: solana_pubkey::Pubkey, + + pub payer: solana_pubkey::Pubkey, + + pub system_program: solana_pubkey::Pubkey, + + pub token_program: solana_pubkey::Pubkey, + /// seeds=['realm-config', realm] + pub realm_config_account: solana_pubkey::Pubkey, +} + +impl DepositGoverningTokens { + pub fn instruction( + &self, + args: DepositGoverningTokensInstructionArgs, + ) -> solana_instruction::Instruction { + self.instruction_with_remaining_accounts(args, &[]) + } + #[allow(clippy::arithmetic_side_effects)] + #[allow(clippy::vec_init_then_push)] + pub fn instruction_with_remaining_accounts( + &self, + args: DepositGoverningTokensInstructionArgs, + remaining_accounts: &[solana_instruction::AccountMeta], + ) -> solana_instruction::Instruction { + let mut accounts = Vec::with_capacity(10 + remaining_accounts.len()); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.realm_account, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + self.governing_token_holding_account, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + self.governing_token_source_account, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.governing_token_owner_account, + true, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.governing_token_source_account_authority, + true, + )); + accounts.push(solana_instruction::AccountMeta::new( + self.token_owner_record, + false, + )); + accounts.push(solana_instruction::AccountMeta::new(self.payer, true)); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.system_program, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.token_program, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.realm_config_account, + false, + )); + accounts.extend_from_slice(remaining_accounts); + let mut data = DepositGoverningTokensInstructionData::new() + .try_to_vec() + .unwrap(); + let mut args = args.try_to_vec().unwrap(); + data.append(&mut args); + + solana_instruction::Instruction { + program_id: crate::SPL_GOVERNANCE_ID, + accounts, + data, + } + } +} + +#[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct DepositGoverningTokensInstructionData { + discriminator: u8, +} + +impl DepositGoverningTokensInstructionData { + pub fn new() -> Self { + Self { discriminator: 1 } + } + + pub(crate) fn try_to_vec(&self) -> Result, std::io::Error> { + borsh::to_vec(self) + } +} + +impl Default for DepositGoverningTokensInstructionData { + fn default() -> Self { + Self::new() + } +} + +#[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct DepositGoverningTokensInstructionArgs { + pub amount: u64, +} + +impl DepositGoverningTokensInstructionArgs { + pub(crate) fn try_to_vec(&self) -> Result, std::io::Error> { + borsh::to_vec(self) + } +} + +/// Instruction builder for `DepositGoverningTokens`. +/// +/// ### Accounts: +/// +/// 0. `[]` realm_account +/// 1. `[writable]` governing_token_holding_account +/// 2. `[writable]` governing_token_source_account +/// 3. `[signer]` governing_token_owner_account +/// 4. `[signer]` governing_token_source_account_authority +/// 5. `[writable]` token_owner_record +/// 6. `[writable, signer]` payer +/// 7. `[optional]` system_program (default to `11111111111111111111111111111111`) +/// 8. `[optional]` token_program (default to `TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA`) +/// 9. `[]` realm_config_account +#[derive(Clone, Debug, Default)] +pub struct DepositGoverningTokensBuilder { + realm_account: Option, + governing_token_holding_account: Option, + governing_token_source_account: Option, + governing_token_owner_account: Option, + governing_token_source_account_authority: Option, + token_owner_record: Option, + payer: Option, + system_program: Option, + token_program: Option, + realm_config_account: Option, + amount: Option, + __remaining_accounts: Vec, +} + +impl DepositGoverningTokensBuilder { + pub fn new() -> Self { + Self::default() + } + #[inline(always)] + pub fn realm_account(&mut self, realm_account: solana_pubkey::Pubkey) -> &mut Self { + self.realm_account = Some(realm_account); + self + } + /// seeds=['governance', realm, governing_token_mint] + #[inline(always)] + pub fn governing_token_holding_account( + &mut self, + governing_token_holding_account: solana_pubkey::Pubkey, + ) -> &mut Self { + self.governing_token_holding_account = Some(governing_token_holding_account); + self + } + /// It can either be spl-token TokenAccount or MintAccount. Tokens will be transferred or minted to the holding account + #[inline(always)] + pub fn governing_token_source_account( + &mut self, + governing_token_source_account: solana_pubkey::Pubkey, + ) -> &mut Self { + self.governing_token_source_account = Some(governing_token_source_account); + self + } + #[inline(always)] + pub fn governing_token_owner_account( + &mut self, + governing_token_owner_account: solana_pubkey::Pubkey, + ) -> &mut Self { + self.governing_token_owner_account = Some(governing_token_owner_account); + self + } + /// It should be owner for TokenAccount and mint_authority for MintAccount + #[inline(always)] + pub fn governing_token_source_account_authority( + &mut self, + governing_token_source_account_authority: solana_pubkey::Pubkey, + ) -> &mut Self { + self.governing_token_source_account_authority = + Some(governing_token_source_account_authority); + self + } + /// seeds=['governance', realm, governing_token_mint, governing_token_owner] + #[inline(always)] + pub fn token_owner_record(&mut self, token_owner_record: solana_pubkey::Pubkey) -> &mut Self { + self.token_owner_record = Some(token_owner_record); + self + } + #[inline(always)] + pub fn payer(&mut self, payer: solana_pubkey::Pubkey) -> &mut Self { + self.payer = Some(payer); + self + } + /// `[optional account, default to '11111111111111111111111111111111']` + #[inline(always)] + pub fn system_program(&mut self, system_program: solana_pubkey::Pubkey) -> &mut Self { + self.system_program = Some(system_program); + self + } + /// `[optional account, default to 'TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA']` + #[inline(always)] + pub fn token_program(&mut self, token_program: solana_pubkey::Pubkey) -> &mut Self { + self.token_program = Some(token_program); + self + } + /// seeds=['realm-config', realm] + #[inline(always)] + pub fn realm_config_account( + &mut self, + realm_config_account: solana_pubkey::Pubkey, + ) -> &mut Self { + self.realm_config_account = Some(realm_config_account); + self + } + #[inline(always)] + pub fn amount(&mut self, amount: u64) -> &mut Self { + self.amount = Some(amount); + self + } + /// Add an additional account to the instruction. + #[inline(always)] + pub fn add_remaining_account(&mut self, account: solana_instruction::AccountMeta) -> &mut Self { + self.__remaining_accounts.push(account); + self + } + /// Add additional accounts to the instruction. + #[inline(always)] + pub fn add_remaining_accounts( + &mut self, + accounts: &[solana_instruction::AccountMeta], + ) -> &mut Self { + self.__remaining_accounts.extend_from_slice(accounts); + self + } + #[allow(clippy::clone_on_copy)] + pub fn instruction(&self) -> solana_instruction::Instruction { + let accounts = DepositGoverningTokens { + realm_account: self.realm_account.expect("realm_account is not set"), + governing_token_holding_account: self + .governing_token_holding_account + .expect("governing_token_holding_account is not set"), + governing_token_source_account: self + .governing_token_source_account + .expect("governing_token_source_account is not set"), + governing_token_owner_account: self + .governing_token_owner_account + .expect("governing_token_owner_account is not set"), + governing_token_source_account_authority: self + .governing_token_source_account_authority + .expect("governing_token_source_account_authority is not set"), + token_owner_record: self + .token_owner_record + .expect("token_owner_record is not set"), + payer: self.payer.expect("payer is not set"), + system_program: self + .system_program + .unwrap_or(solana_pubkey::pubkey!("11111111111111111111111111111111")), + token_program: self.token_program.unwrap_or(solana_pubkey::pubkey!( + "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA" + )), + realm_config_account: self + .realm_config_account + .expect("realm_config_account is not set"), + }; + let args = DepositGoverningTokensInstructionArgs { + amount: self.amount.clone().expect("amount is not set"), + }; + + accounts.instruction_with_remaining_accounts(args, &self.__remaining_accounts) + } +} + +/// `deposit_governing_tokens` CPI accounts. +pub struct DepositGoverningTokensCpiAccounts<'a, 'b> { + pub realm_account: &'b solana_account_info::AccountInfo<'a>, + /// seeds=['governance', realm, governing_token_mint] + pub governing_token_holding_account: &'b solana_account_info::AccountInfo<'a>, + /// It can either be spl-token TokenAccount or MintAccount. Tokens will be transferred or minted to the holding account + pub governing_token_source_account: &'b solana_account_info::AccountInfo<'a>, + + pub governing_token_owner_account: &'b solana_account_info::AccountInfo<'a>, + /// It should be owner for TokenAccount and mint_authority for MintAccount + pub governing_token_source_account_authority: &'b solana_account_info::AccountInfo<'a>, + /// seeds=['governance', realm, governing_token_mint, governing_token_owner] + pub token_owner_record: &'b solana_account_info::AccountInfo<'a>, + + pub payer: &'b solana_account_info::AccountInfo<'a>, + + pub system_program: &'b solana_account_info::AccountInfo<'a>, + + pub token_program: &'b solana_account_info::AccountInfo<'a>, + /// seeds=['realm-config', realm] + pub realm_config_account: &'b solana_account_info::AccountInfo<'a>, +} + +/// `deposit_governing_tokens` CPI instruction. +pub struct DepositGoverningTokensCpi<'a, 'b> { + /// The program to invoke. + pub __program: &'b solana_account_info::AccountInfo<'a>, + + pub realm_account: &'b solana_account_info::AccountInfo<'a>, + /// seeds=['governance', realm, governing_token_mint] + pub governing_token_holding_account: &'b solana_account_info::AccountInfo<'a>, + /// It can either be spl-token TokenAccount or MintAccount. Tokens will be transferred or minted to the holding account + pub governing_token_source_account: &'b solana_account_info::AccountInfo<'a>, + + pub governing_token_owner_account: &'b solana_account_info::AccountInfo<'a>, + /// It should be owner for TokenAccount and mint_authority for MintAccount + pub governing_token_source_account_authority: &'b solana_account_info::AccountInfo<'a>, + /// seeds=['governance', realm, governing_token_mint, governing_token_owner] + pub token_owner_record: &'b solana_account_info::AccountInfo<'a>, + + pub payer: &'b solana_account_info::AccountInfo<'a>, + + pub system_program: &'b solana_account_info::AccountInfo<'a>, + + pub token_program: &'b solana_account_info::AccountInfo<'a>, + /// seeds=['realm-config', realm] + pub realm_config_account: &'b solana_account_info::AccountInfo<'a>, + /// The arguments for the instruction. + pub __args: DepositGoverningTokensInstructionArgs, +} + +impl<'a, 'b> DepositGoverningTokensCpi<'a, 'b> { + pub fn new( + program: &'b solana_account_info::AccountInfo<'a>, + accounts: DepositGoverningTokensCpiAccounts<'a, 'b>, + args: DepositGoverningTokensInstructionArgs, + ) -> Self { + Self { + __program: program, + realm_account: accounts.realm_account, + governing_token_holding_account: accounts.governing_token_holding_account, + governing_token_source_account: accounts.governing_token_source_account, + governing_token_owner_account: accounts.governing_token_owner_account, + governing_token_source_account_authority: accounts + .governing_token_source_account_authority, + token_owner_record: accounts.token_owner_record, + payer: accounts.payer, + system_program: accounts.system_program, + token_program: accounts.token_program, + realm_config_account: accounts.realm_config_account, + __args: args, + } + } + #[inline(always)] + pub fn invoke(&self) -> solana_program_error::ProgramResult { + self.invoke_signed_with_remaining_accounts(&[], &[]) + } + #[inline(always)] + pub fn invoke_with_remaining_accounts( + &self, + remaining_accounts: &[(&'b solana_account_info::AccountInfo<'a>, bool, bool)], + ) -> solana_program_error::ProgramResult { + self.invoke_signed_with_remaining_accounts(&[], remaining_accounts) + } + #[inline(always)] + pub fn invoke_signed(&self, signers_seeds: &[&[&[u8]]]) -> solana_program_error::ProgramResult { + self.invoke_signed_with_remaining_accounts(signers_seeds, &[]) + } + #[allow(clippy::arithmetic_side_effects)] + #[allow(clippy::clone_on_copy)] + #[allow(clippy::vec_init_then_push)] + pub fn invoke_signed_with_remaining_accounts( + &self, + signers_seeds: &[&[&[u8]]], + remaining_accounts: &[(&'b solana_account_info::AccountInfo<'a>, bool, bool)], + ) -> solana_program_error::ProgramResult { + let mut accounts = Vec::with_capacity(10 + remaining_accounts.len()); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.realm_account.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + *self.governing_token_holding_account.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + *self.governing_token_source_account.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.governing_token_owner_account.key, + true, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.governing_token_source_account_authority.key, + true, + )); + accounts.push(solana_instruction::AccountMeta::new( + *self.token_owner_record.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new(*self.payer.key, true)); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.system_program.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.token_program.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.realm_config_account.key, + false, + )); + remaining_accounts.iter().for_each(|remaining_account| { + accounts.push(solana_instruction::AccountMeta { + pubkey: *remaining_account.0.key, + is_signer: remaining_account.1, + is_writable: remaining_account.2, + }) + }); + let mut data = DepositGoverningTokensInstructionData::new() + .try_to_vec() + .unwrap(); + let mut args = self.__args.try_to_vec().unwrap(); + data.append(&mut args); + + let instruction = solana_instruction::Instruction { + program_id: crate::SPL_GOVERNANCE_ID, + accounts, + data, + }; + let mut account_infos = Vec::with_capacity(11 + remaining_accounts.len()); + account_infos.push(self.__program.clone()); + account_infos.push(self.realm_account.clone()); + account_infos.push(self.governing_token_holding_account.clone()); + account_infos.push(self.governing_token_source_account.clone()); + account_infos.push(self.governing_token_owner_account.clone()); + account_infos.push(self.governing_token_source_account_authority.clone()); + account_infos.push(self.token_owner_record.clone()); + account_infos.push(self.payer.clone()); + account_infos.push(self.system_program.clone()); + account_infos.push(self.token_program.clone()); + account_infos.push(self.realm_config_account.clone()); + remaining_accounts + .iter() + .for_each(|remaining_account| account_infos.push(remaining_account.0.clone())); + + if signers_seeds.is_empty() { + solana_cpi::invoke(&instruction, &account_infos) + } else { + solana_cpi::invoke_signed(&instruction, &account_infos, signers_seeds) + } + } +} + +/// Instruction builder for `DepositGoverningTokens` via CPI. +/// +/// ### Accounts: +/// +/// 0. `[]` realm_account +/// 1. `[writable]` governing_token_holding_account +/// 2. `[writable]` governing_token_source_account +/// 3. `[signer]` governing_token_owner_account +/// 4. `[signer]` governing_token_source_account_authority +/// 5. `[writable]` token_owner_record +/// 6. `[writable, signer]` payer +/// 7. `[]` system_program +/// 8. `[]` token_program +/// 9. `[]` realm_config_account +#[derive(Clone, Debug)] +pub struct DepositGoverningTokensCpiBuilder<'a, 'b> { + instruction: Box>, +} + +impl<'a, 'b> DepositGoverningTokensCpiBuilder<'a, 'b> { + pub fn new(program: &'b solana_account_info::AccountInfo<'a>) -> Self { + let instruction = Box::new(DepositGoverningTokensCpiBuilderInstruction { + __program: program, + realm_account: None, + governing_token_holding_account: None, + governing_token_source_account: None, + governing_token_owner_account: None, + governing_token_source_account_authority: None, + token_owner_record: None, + payer: None, + system_program: None, + token_program: None, + realm_config_account: None, + amount: None, + __remaining_accounts: Vec::new(), + }); + Self { instruction } + } + #[inline(always)] + pub fn realm_account( + &mut self, + realm_account: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.realm_account = Some(realm_account); + self + } + /// seeds=['governance', realm, governing_token_mint] + #[inline(always)] + pub fn governing_token_holding_account( + &mut self, + governing_token_holding_account: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.governing_token_holding_account = Some(governing_token_holding_account); + self + } + /// It can either be spl-token TokenAccount or MintAccount. Tokens will be transferred or minted to the holding account + #[inline(always)] + pub fn governing_token_source_account( + &mut self, + governing_token_source_account: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.governing_token_source_account = Some(governing_token_source_account); + self + } + #[inline(always)] + pub fn governing_token_owner_account( + &mut self, + governing_token_owner_account: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.governing_token_owner_account = Some(governing_token_owner_account); + self + } + /// It should be owner for TokenAccount and mint_authority for MintAccount + #[inline(always)] + pub fn governing_token_source_account_authority( + &mut self, + governing_token_source_account_authority: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.governing_token_source_account_authority = + Some(governing_token_source_account_authority); + self + } + /// seeds=['governance', realm, governing_token_mint, governing_token_owner] + #[inline(always)] + pub fn token_owner_record( + &mut self, + token_owner_record: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.token_owner_record = Some(token_owner_record); + self + } + #[inline(always)] + pub fn payer(&mut self, payer: &'b solana_account_info::AccountInfo<'a>) -> &mut Self { + self.instruction.payer = Some(payer); + self + } + #[inline(always)] + pub fn system_program( + &mut self, + system_program: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.system_program = Some(system_program); + self + } + #[inline(always)] + pub fn token_program( + &mut self, + token_program: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.token_program = Some(token_program); + self + } + /// seeds=['realm-config', realm] + #[inline(always)] + pub fn realm_config_account( + &mut self, + realm_config_account: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.realm_config_account = Some(realm_config_account); + self + } + #[inline(always)] + pub fn amount(&mut self, amount: u64) -> &mut Self { + self.instruction.amount = Some(amount); + self + } + /// Add an additional account to the instruction. + #[inline(always)] + pub fn add_remaining_account( + &mut self, + account: &'b solana_account_info::AccountInfo<'a>, + is_writable: bool, + is_signer: bool, + ) -> &mut Self { + self.instruction + .__remaining_accounts + .push((account, is_writable, is_signer)); + self + } + /// Add additional accounts to the instruction. + /// + /// Each account is represented by a tuple of the `AccountInfo`, a `bool` indicating whether the account is writable or not, + /// and a `bool` indicating whether the account is a signer or not. + #[inline(always)] + pub fn add_remaining_accounts( + &mut self, + accounts: &[(&'b solana_account_info::AccountInfo<'a>, bool, bool)], + ) -> &mut Self { + self.instruction + .__remaining_accounts + .extend_from_slice(accounts); + self + } + #[inline(always)] + pub fn invoke(&self) -> solana_program_error::ProgramResult { + self.invoke_signed(&[]) + } + #[allow(clippy::clone_on_copy)] + #[allow(clippy::vec_init_then_push)] + pub fn invoke_signed(&self, signers_seeds: &[&[&[u8]]]) -> solana_program_error::ProgramResult { + let args = DepositGoverningTokensInstructionArgs { + amount: self.instruction.amount.clone().expect("amount is not set"), + }; + let instruction = DepositGoverningTokensCpi { + __program: self.instruction.__program, + + realm_account: self + .instruction + .realm_account + .expect("realm_account is not set"), + + governing_token_holding_account: self + .instruction + .governing_token_holding_account + .expect("governing_token_holding_account is not set"), + + governing_token_source_account: self + .instruction + .governing_token_source_account + .expect("governing_token_source_account is not set"), + + governing_token_owner_account: self + .instruction + .governing_token_owner_account + .expect("governing_token_owner_account is not set"), + + governing_token_source_account_authority: self + .instruction + .governing_token_source_account_authority + .expect("governing_token_source_account_authority is not set"), + + token_owner_record: self + .instruction + .token_owner_record + .expect("token_owner_record is not set"), + + payer: self.instruction.payer.expect("payer is not set"), + + system_program: self + .instruction + .system_program + .expect("system_program is not set"), + + token_program: self + .instruction + .token_program + .expect("token_program is not set"), + + realm_config_account: self + .instruction + .realm_config_account + .expect("realm_config_account is not set"), + __args: args, + }; + instruction.invoke_signed_with_remaining_accounts( + signers_seeds, + &self.instruction.__remaining_accounts, + ) + } +} + +#[derive(Clone, Debug)] +struct DepositGoverningTokensCpiBuilderInstruction<'a, 'b> { + __program: &'b solana_account_info::AccountInfo<'a>, + realm_account: Option<&'b solana_account_info::AccountInfo<'a>>, + governing_token_holding_account: Option<&'b solana_account_info::AccountInfo<'a>>, + governing_token_source_account: Option<&'b solana_account_info::AccountInfo<'a>>, + governing_token_owner_account: Option<&'b solana_account_info::AccountInfo<'a>>, + governing_token_source_account_authority: Option<&'b solana_account_info::AccountInfo<'a>>, + token_owner_record: Option<&'b solana_account_info::AccountInfo<'a>>, + payer: Option<&'b solana_account_info::AccountInfo<'a>>, + system_program: Option<&'b solana_account_info::AccountInfo<'a>>, + token_program: Option<&'b solana_account_info::AccountInfo<'a>>, + realm_config_account: Option<&'b solana_account_info::AccountInfo<'a>>, + amount: Option, + /// Additional instruction accounts `(AccountInfo, is_writable, is_signer)`. + __remaining_accounts: Vec<(&'b solana_account_info::AccountInfo<'a>, bool, bool)>, +} diff --git a/e2e/governance/src/generated/instructions/execute_transaction.rs b/e2e/governance/src/generated/instructions/execute_transaction.rs new file mode 100644 index 0000000..a26c75c --- /dev/null +++ b/e2e/governance/src/generated/instructions/execute_transaction.rs @@ -0,0 +1,365 @@ +//! This code was AUTOGENERATED using the codama library. +//! Please DO NOT EDIT THIS FILE, instead use visitors +//! to add features, then rerun codama to update it. +//! +//! +//! + +use borsh::BorshDeserialize; +use borsh::BorshSerialize; + +pub const EXECUTE_TRANSACTION_DISCRIMINATOR: u8 = 16; + +/// Accounts. +#[derive(Debug)] +pub struct ExecuteTransaction { + pub governance_account: solana_pubkey::Pubkey, + + pub proposal_account: solana_pubkey::Pubkey, + + pub proposal_transaction_account: solana_pubkey::Pubkey, +} + +impl ExecuteTransaction { + pub fn instruction(&self) -> solana_instruction::Instruction { + self.instruction_with_remaining_accounts(&[]) + } + #[allow(clippy::arithmetic_side_effects)] + #[allow(clippy::vec_init_then_push)] + pub fn instruction_with_remaining_accounts( + &self, + remaining_accounts: &[solana_instruction::AccountMeta], + ) -> solana_instruction::Instruction { + let mut accounts = Vec::with_capacity(3 + remaining_accounts.len()); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.governance_account, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + self.proposal_account, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + self.proposal_transaction_account, + false, + )); + accounts.extend_from_slice(remaining_accounts); + let data = ExecuteTransactionInstructionData::new() + .try_to_vec() + .unwrap(); + + solana_instruction::Instruction { + program_id: crate::SPL_GOVERNANCE_ID, + accounts, + data, + } + } +} + +#[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct ExecuteTransactionInstructionData { + discriminator: u8, +} + +impl ExecuteTransactionInstructionData { + pub fn new() -> Self { + Self { discriminator: 16 } + } + + pub(crate) fn try_to_vec(&self) -> Result, std::io::Error> { + borsh::to_vec(self) + } +} + +impl Default for ExecuteTransactionInstructionData { + fn default() -> Self { + Self::new() + } +} + +/// Instruction builder for `ExecuteTransaction`. +/// +/// ### Accounts: +/// +/// 0. `[]` governance_account +/// 1. `[writable]` proposal_account +/// 2. `[writable]` proposal_transaction_account +#[derive(Clone, Debug, Default)] +pub struct ExecuteTransactionBuilder { + governance_account: Option, + proposal_account: Option, + proposal_transaction_account: Option, + __remaining_accounts: Vec, +} + +impl ExecuteTransactionBuilder { + pub fn new() -> Self { + Self::default() + } + #[inline(always)] + pub fn governance_account(&mut self, governance_account: solana_pubkey::Pubkey) -> &mut Self { + self.governance_account = Some(governance_account); + self + } + #[inline(always)] + pub fn proposal_account(&mut self, proposal_account: solana_pubkey::Pubkey) -> &mut Self { + self.proposal_account = Some(proposal_account); + self + } + #[inline(always)] + pub fn proposal_transaction_account( + &mut self, + proposal_transaction_account: solana_pubkey::Pubkey, + ) -> &mut Self { + self.proposal_transaction_account = Some(proposal_transaction_account); + self + } + /// Add an additional account to the instruction. + #[inline(always)] + pub fn add_remaining_account(&mut self, account: solana_instruction::AccountMeta) -> &mut Self { + self.__remaining_accounts.push(account); + self + } + /// Add additional accounts to the instruction. + #[inline(always)] + pub fn add_remaining_accounts( + &mut self, + accounts: &[solana_instruction::AccountMeta], + ) -> &mut Self { + self.__remaining_accounts.extend_from_slice(accounts); + self + } + #[allow(clippy::clone_on_copy)] + pub fn instruction(&self) -> solana_instruction::Instruction { + let accounts = ExecuteTransaction { + governance_account: self + .governance_account + .expect("governance_account is not set"), + proposal_account: self.proposal_account.expect("proposal_account is not set"), + proposal_transaction_account: self + .proposal_transaction_account + .expect("proposal_transaction_account is not set"), + }; + + accounts.instruction_with_remaining_accounts(&self.__remaining_accounts) + } +} + +/// `execute_transaction` CPI accounts. +pub struct ExecuteTransactionCpiAccounts<'a, 'b> { + pub governance_account: &'b solana_account_info::AccountInfo<'a>, + + pub proposal_account: &'b solana_account_info::AccountInfo<'a>, + + pub proposal_transaction_account: &'b solana_account_info::AccountInfo<'a>, +} + +/// `execute_transaction` CPI instruction. +pub struct ExecuteTransactionCpi<'a, 'b> { + /// The program to invoke. + pub __program: &'b solana_account_info::AccountInfo<'a>, + + pub governance_account: &'b solana_account_info::AccountInfo<'a>, + + pub proposal_account: &'b solana_account_info::AccountInfo<'a>, + + pub proposal_transaction_account: &'b solana_account_info::AccountInfo<'a>, +} + +impl<'a, 'b> ExecuteTransactionCpi<'a, 'b> { + pub fn new( + program: &'b solana_account_info::AccountInfo<'a>, + accounts: ExecuteTransactionCpiAccounts<'a, 'b>, + ) -> Self { + Self { + __program: program, + governance_account: accounts.governance_account, + proposal_account: accounts.proposal_account, + proposal_transaction_account: accounts.proposal_transaction_account, + } + } + #[inline(always)] + pub fn invoke(&self) -> solana_program_error::ProgramResult { + self.invoke_signed_with_remaining_accounts(&[], &[]) + } + #[inline(always)] + pub fn invoke_with_remaining_accounts( + &self, + remaining_accounts: &[(&'b solana_account_info::AccountInfo<'a>, bool, bool)], + ) -> solana_program_error::ProgramResult { + self.invoke_signed_with_remaining_accounts(&[], remaining_accounts) + } + #[inline(always)] + pub fn invoke_signed(&self, signers_seeds: &[&[&[u8]]]) -> solana_program_error::ProgramResult { + self.invoke_signed_with_remaining_accounts(signers_seeds, &[]) + } + #[allow(clippy::arithmetic_side_effects)] + #[allow(clippy::clone_on_copy)] + #[allow(clippy::vec_init_then_push)] + pub fn invoke_signed_with_remaining_accounts( + &self, + signers_seeds: &[&[&[u8]]], + remaining_accounts: &[(&'b solana_account_info::AccountInfo<'a>, bool, bool)], + ) -> solana_program_error::ProgramResult { + let mut accounts = Vec::with_capacity(3 + remaining_accounts.len()); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.governance_account.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + *self.proposal_account.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + *self.proposal_transaction_account.key, + false, + )); + remaining_accounts.iter().for_each(|remaining_account| { + accounts.push(solana_instruction::AccountMeta { + pubkey: *remaining_account.0.key, + is_signer: remaining_account.1, + is_writable: remaining_account.2, + }) + }); + let data = ExecuteTransactionInstructionData::new() + .try_to_vec() + .unwrap(); + + let instruction = solana_instruction::Instruction { + program_id: crate::SPL_GOVERNANCE_ID, + accounts, + data, + }; + let mut account_infos = Vec::with_capacity(4 + remaining_accounts.len()); + account_infos.push(self.__program.clone()); + account_infos.push(self.governance_account.clone()); + account_infos.push(self.proposal_account.clone()); + account_infos.push(self.proposal_transaction_account.clone()); + remaining_accounts + .iter() + .for_each(|remaining_account| account_infos.push(remaining_account.0.clone())); + + if signers_seeds.is_empty() { + solana_cpi::invoke(&instruction, &account_infos) + } else { + solana_cpi::invoke_signed(&instruction, &account_infos, signers_seeds) + } + } +} + +/// Instruction builder for `ExecuteTransaction` via CPI. +/// +/// ### Accounts: +/// +/// 0. `[]` governance_account +/// 1. `[writable]` proposal_account +/// 2. `[writable]` proposal_transaction_account +#[derive(Clone, Debug)] +pub struct ExecuteTransactionCpiBuilder<'a, 'b> { + instruction: Box>, +} + +impl<'a, 'b> ExecuteTransactionCpiBuilder<'a, 'b> { + pub fn new(program: &'b solana_account_info::AccountInfo<'a>) -> Self { + let instruction = Box::new(ExecuteTransactionCpiBuilderInstruction { + __program: program, + governance_account: None, + proposal_account: None, + proposal_transaction_account: None, + __remaining_accounts: Vec::new(), + }); + Self { instruction } + } + #[inline(always)] + pub fn governance_account( + &mut self, + governance_account: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.governance_account = Some(governance_account); + self + } + #[inline(always)] + pub fn proposal_account( + &mut self, + proposal_account: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.proposal_account = Some(proposal_account); + self + } + #[inline(always)] + pub fn proposal_transaction_account( + &mut self, + proposal_transaction_account: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.proposal_transaction_account = Some(proposal_transaction_account); + self + } + /// Add an additional account to the instruction. + #[inline(always)] + pub fn add_remaining_account( + &mut self, + account: &'b solana_account_info::AccountInfo<'a>, + is_writable: bool, + is_signer: bool, + ) -> &mut Self { + self.instruction + .__remaining_accounts + .push((account, is_writable, is_signer)); + self + } + /// Add additional accounts to the instruction. + /// + /// Each account is represented by a tuple of the `AccountInfo`, a `bool` indicating whether the account is writable or not, + /// and a `bool` indicating whether the account is a signer or not. + #[inline(always)] + pub fn add_remaining_accounts( + &mut self, + accounts: &[(&'b solana_account_info::AccountInfo<'a>, bool, bool)], + ) -> &mut Self { + self.instruction + .__remaining_accounts + .extend_from_slice(accounts); + self + } + #[inline(always)] + pub fn invoke(&self) -> solana_program_error::ProgramResult { + self.invoke_signed(&[]) + } + #[allow(clippy::clone_on_copy)] + #[allow(clippy::vec_init_then_push)] + pub fn invoke_signed(&self, signers_seeds: &[&[&[u8]]]) -> solana_program_error::ProgramResult { + let instruction = ExecuteTransactionCpi { + __program: self.instruction.__program, + + governance_account: self + .instruction + .governance_account + .expect("governance_account is not set"), + + proposal_account: self + .instruction + .proposal_account + .expect("proposal_account is not set"), + + proposal_transaction_account: self + .instruction + .proposal_transaction_account + .expect("proposal_transaction_account is not set"), + }; + instruction.invoke_signed_with_remaining_accounts( + signers_seeds, + &self.instruction.__remaining_accounts, + ) + } +} + +#[derive(Clone, Debug)] +struct ExecuteTransactionCpiBuilderInstruction<'a, 'b> { + __program: &'b solana_account_info::AccountInfo<'a>, + governance_account: Option<&'b solana_account_info::AccountInfo<'a>>, + proposal_account: Option<&'b solana_account_info::AccountInfo<'a>>, + proposal_transaction_account: Option<&'b solana_account_info::AccountInfo<'a>>, + /// Additional instruction accounts `(AccountInfo, is_writable, is_signer)`. + __remaining_accounts: Vec<(&'b solana_account_info::AccountInfo<'a>, bool, bool)>, +} diff --git a/e2e/governance/src/generated/instructions/finalize_vote.rs b/e2e/governance/src/generated/instructions/finalize_vote.rs new file mode 100644 index 0000000..cb800b2 --- /dev/null +++ b/e2e/governance/src/generated/instructions/finalize_vote.rs @@ -0,0 +1,547 @@ +//! This code was AUTOGENERATED using the codama library. +//! Please DO NOT EDIT THIS FILE, instead use visitors +//! to add features, then rerun codama to update it. +//! +//! +//! + +use borsh::BorshDeserialize; +use borsh::BorshSerialize; + +pub const FINALIZE_VOTE_DISCRIMINATOR: u8 = 14; + +/// Accounts. +#[derive(Debug)] +pub struct FinalizeVote { + pub realm_account: solana_pubkey::Pubkey, + + pub governance_account: solana_pubkey::Pubkey, + + pub proposal_account: solana_pubkey::Pubkey, + /// TokenOwnerRecord of the Proposal owner + pub token_owner_record: solana_pubkey::Pubkey, + + pub governing_token_mint: solana_pubkey::Pubkey, + /// RealmConfig account. PDA seeds: ['realm-config', realm] + pub realm_config: solana_pubkey::Pubkey, + /// Optional Max Voter Weight Record + pub max_voter_weight_record: Option, +} + +impl FinalizeVote { + pub fn instruction(&self) -> solana_instruction::Instruction { + self.instruction_with_remaining_accounts(&[]) + } + #[allow(clippy::arithmetic_side_effects)] + #[allow(clippy::vec_init_then_push)] + pub fn instruction_with_remaining_accounts( + &self, + remaining_accounts: &[solana_instruction::AccountMeta], + ) -> solana_instruction::Instruction { + let mut accounts = Vec::with_capacity(7 + remaining_accounts.len()); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.realm_account, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + self.governance_account, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + self.proposal_account, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + self.token_owner_record, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.governing_token_mint, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.realm_config, + false, + )); + if let Some(max_voter_weight_record) = self.max_voter_weight_record { + accounts.push(solana_instruction::AccountMeta::new_readonly( + max_voter_weight_record, + false, + )); + } else { + accounts.push(solana_instruction::AccountMeta::new_readonly( + crate::SPL_GOVERNANCE_ID, + false, + )); + } + accounts.extend_from_slice(remaining_accounts); + let data = FinalizeVoteInstructionData::new().try_to_vec().unwrap(); + + solana_instruction::Instruction { + program_id: crate::SPL_GOVERNANCE_ID, + accounts, + data, + } + } +} + +#[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct FinalizeVoteInstructionData { + discriminator: u8, +} + +impl FinalizeVoteInstructionData { + pub fn new() -> Self { + Self { discriminator: 14 } + } + + pub(crate) fn try_to_vec(&self) -> Result, std::io::Error> { + borsh::to_vec(self) + } +} + +impl Default for FinalizeVoteInstructionData { + fn default() -> Self { + Self::new() + } +} + +/// Instruction builder for `FinalizeVote`. +/// +/// ### Accounts: +/// +/// 0. `[]` realm_account +/// 1. `[writable]` governance_account +/// 2. `[writable]` proposal_account +/// 3. `[writable]` token_owner_record +/// 4. `[]` governing_token_mint +/// 5. `[]` realm_config +/// 6. `[optional]` max_voter_weight_record +#[derive(Clone, Debug, Default)] +pub struct FinalizeVoteBuilder { + realm_account: Option, + governance_account: Option, + proposal_account: Option, + token_owner_record: Option, + governing_token_mint: Option, + realm_config: Option, + max_voter_weight_record: Option, + __remaining_accounts: Vec, +} + +impl FinalizeVoteBuilder { + pub fn new() -> Self { + Self::default() + } + #[inline(always)] + pub fn realm_account(&mut self, realm_account: solana_pubkey::Pubkey) -> &mut Self { + self.realm_account = Some(realm_account); + self + } + #[inline(always)] + pub fn governance_account(&mut self, governance_account: solana_pubkey::Pubkey) -> &mut Self { + self.governance_account = Some(governance_account); + self + } + #[inline(always)] + pub fn proposal_account(&mut self, proposal_account: solana_pubkey::Pubkey) -> &mut Self { + self.proposal_account = Some(proposal_account); + self + } + /// TokenOwnerRecord of the Proposal owner + #[inline(always)] + pub fn token_owner_record(&mut self, token_owner_record: solana_pubkey::Pubkey) -> &mut Self { + self.token_owner_record = Some(token_owner_record); + self + } + #[inline(always)] + pub fn governing_token_mint( + &mut self, + governing_token_mint: solana_pubkey::Pubkey, + ) -> &mut Self { + self.governing_token_mint = Some(governing_token_mint); + self + } + /// RealmConfig account. PDA seeds: ['realm-config', realm] + #[inline(always)] + pub fn realm_config(&mut self, realm_config: solana_pubkey::Pubkey) -> &mut Self { + self.realm_config = Some(realm_config); + self + } + /// `[optional account]` + /// Optional Max Voter Weight Record + #[inline(always)] + pub fn max_voter_weight_record( + &mut self, + max_voter_weight_record: Option, + ) -> &mut Self { + self.max_voter_weight_record = max_voter_weight_record; + self + } + /// Add an additional account to the instruction. + #[inline(always)] + pub fn add_remaining_account(&mut self, account: solana_instruction::AccountMeta) -> &mut Self { + self.__remaining_accounts.push(account); + self + } + /// Add additional accounts to the instruction. + #[inline(always)] + pub fn add_remaining_accounts( + &mut self, + accounts: &[solana_instruction::AccountMeta], + ) -> &mut Self { + self.__remaining_accounts.extend_from_slice(accounts); + self + } + #[allow(clippy::clone_on_copy)] + pub fn instruction(&self) -> solana_instruction::Instruction { + let accounts = FinalizeVote { + realm_account: self.realm_account.expect("realm_account is not set"), + governance_account: self + .governance_account + .expect("governance_account is not set"), + proposal_account: self.proposal_account.expect("proposal_account is not set"), + token_owner_record: self + .token_owner_record + .expect("token_owner_record is not set"), + governing_token_mint: self + .governing_token_mint + .expect("governing_token_mint is not set"), + realm_config: self.realm_config.expect("realm_config is not set"), + max_voter_weight_record: self.max_voter_weight_record, + }; + + accounts.instruction_with_remaining_accounts(&self.__remaining_accounts) + } +} + +/// `finalize_vote` CPI accounts. +pub struct FinalizeVoteCpiAccounts<'a, 'b> { + pub realm_account: &'b solana_account_info::AccountInfo<'a>, + + pub governance_account: &'b solana_account_info::AccountInfo<'a>, + + pub proposal_account: &'b solana_account_info::AccountInfo<'a>, + /// TokenOwnerRecord of the Proposal owner + pub token_owner_record: &'b solana_account_info::AccountInfo<'a>, + + pub governing_token_mint: &'b solana_account_info::AccountInfo<'a>, + /// RealmConfig account. PDA seeds: ['realm-config', realm] + pub realm_config: &'b solana_account_info::AccountInfo<'a>, + /// Optional Max Voter Weight Record + pub max_voter_weight_record: Option<&'b solana_account_info::AccountInfo<'a>>, +} + +/// `finalize_vote` CPI instruction. +pub struct FinalizeVoteCpi<'a, 'b> { + /// The program to invoke. + pub __program: &'b solana_account_info::AccountInfo<'a>, + + pub realm_account: &'b solana_account_info::AccountInfo<'a>, + + pub governance_account: &'b solana_account_info::AccountInfo<'a>, + + pub proposal_account: &'b solana_account_info::AccountInfo<'a>, + /// TokenOwnerRecord of the Proposal owner + pub token_owner_record: &'b solana_account_info::AccountInfo<'a>, + + pub governing_token_mint: &'b solana_account_info::AccountInfo<'a>, + /// RealmConfig account. PDA seeds: ['realm-config', realm] + pub realm_config: &'b solana_account_info::AccountInfo<'a>, + /// Optional Max Voter Weight Record + pub max_voter_weight_record: Option<&'b solana_account_info::AccountInfo<'a>>, +} + +impl<'a, 'b> FinalizeVoteCpi<'a, 'b> { + pub fn new( + program: &'b solana_account_info::AccountInfo<'a>, + accounts: FinalizeVoteCpiAccounts<'a, 'b>, + ) -> Self { + Self { + __program: program, + realm_account: accounts.realm_account, + governance_account: accounts.governance_account, + proposal_account: accounts.proposal_account, + token_owner_record: accounts.token_owner_record, + governing_token_mint: accounts.governing_token_mint, + realm_config: accounts.realm_config, + max_voter_weight_record: accounts.max_voter_weight_record, + } + } + #[inline(always)] + pub fn invoke(&self) -> solana_program_error::ProgramResult { + self.invoke_signed_with_remaining_accounts(&[], &[]) + } + #[inline(always)] + pub fn invoke_with_remaining_accounts( + &self, + remaining_accounts: &[(&'b solana_account_info::AccountInfo<'a>, bool, bool)], + ) -> solana_program_error::ProgramResult { + self.invoke_signed_with_remaining_accounts(&[], remaining_accounts) + } + #[inline(always)] + pub fn invoke_signed(&self, signers_seeds: &[&[&[u8]]]) -> solana_program_error::ProgramResult { + self.invoke_signed_with_remaining_accounts(signers_seeds, &[]) + } + #[allow(clippy::arithmetic_side_effects)] + #[allow(clippy::clone_on_copy)] + #[allow(clippy::vec_init_then_push)] + pub fn invoke_signed_with_remaining_accounts( + &self, + signers_seeds: &[&[&[u8]]], + remaining_accounts: &[(&'b solana_account_info::AccountInfo<'a>, bool, bool)], + ) -> solana_program_error::ProgramResult { + let mut accounts = Vec::with_capacity(7 + remaining_accounts.len()); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.realm_account.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + *self.governance_account.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + *self.proposal_account.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + *self.token_owner_record.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.governing_token_mint.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.realm_config.key, + false, + )); + if let Some(max_voter_weight_record) = self.max_voter_weight_record { + accounts.push(solana_instruction::AccountMeta::new_readonly( + *max_voter_weight_record.key, + false, + )); + } else { + accounts.push(solana_instruction::AccountMeta::new_readonly( + crate::SPL_GOVERNANCE_ID, + false, + )); + } + remaining_accounts.iter().for_each(|remaining_account| { + accounts.push(solana_instruction::AccountMeta { + pubkey: *remaining_account.0.key, + is_signer: remaining_account.1, + is_writable: remaining_account.2, + }) + }); + let data = FinalizeVoteInstructionData::new().try_to_vec().unwrap(); + + let instruction = solana_instruction::Instruction { + program_id: crate::SPL_GOVERNANCE_ID, + accounts, + data, + }; + let mut account_infos = Vec::with_capacity(8 + remaining_accounts.len()); + account_infos.push(self.__program.clone()); + account_infos.push(self.realm_account.clone()); + account_infos.push(self.governance_account.clone()); + account_infos.push(self.proposal_account.clone()); + account_infos.push(self.token_owner_record.clone()); + account_infos.push(self.governing_token_mint.clone()); + account_infos.push(self.realm_config.clone()); + if let Some(max_voter_weight_record) = self.max_voter_weight_record { + account_infos.push(max_voter_weight_record.clone()); + } + remaining_accounts + .iter() + .for_each(|remaining_account| account_infos.push(remaining_account.0.clone())); + + if signers_seeds.is_empty() { + solana_cpi::invoke(&instruction, &account_infos) + } else { + solana_cpi::invoke_signed(&instruction, &account_infos, signers_seeds) + } + } +} + +/// Instruction builder for `FinalizeVote` via CPI. +/// +/// ### Accounts: +/// +/// 0. `[]` realm_account +/// 1. `[writable]` governance_account +/// 2. `[writable]` proposal_account +/// 3. `[writable]` token_owner_record +/// 4. `[]` governing_token_mint +/// 5. `[]` realm_config +/// 6. `[optional]` max_voter_weight_record +#[derive(Clone, Debug)] +pub struct FinalizeVoteCpiBuilder<'a, 'b> { + instruction: Box>, +} + +impl<'a, 'b> FinalizeVoteCpiBuilder<'a, 'b> { + pub fn new(program: &'b solana_account_info::AccountInfo<'a>) -> Self { + let instruction = Box::new(FinalizeVoteCpiBuilderInstruction { + __program: program, + realm_account: None, + governance_account: None, + proposal_account: None, + token_owner_record: None, + governing_token_mint: None, + realm_config: None, + max_voter_weight_record: None, + __remaining_accounts: Vec::new(), + }); + Self { instruction } + } + #[inline(always)] + pub fn realm_account( + &mut self, + realm_account: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.realm_account = Some(realm_account); + self + } + #[inline(always)] + pub fn governance_account( + &mut self, + governance_account: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.governance_account = Some(governance_account); + self + } + #[inline(always)] + pub fn proposal_account( + &mut self, + proposal_account: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.proposal_account = Some(proposal_account); + self + } + /// TokenOwnerRecord of the Proposal owner + #[inline(always)] + pub fn token_owner_record( + &mut self, + token_owner_record: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.token_owner_record = Some(token_owner_record); + self + } + #[inline(always)] + pub fn governing_token_mint( + &mut self, + governing_token_mint: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.governing_token_mint = Some(governing_token_mint); + self + } + /// RealmConfig account. PDA seeds: ['realm-config', realm] + #[inline(always)] + pub fn realm_config( + &mut self, + realm_config: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.realm_config = Some(realm_config); + self + } + /// `[optional account]` + /// Optional Max Voter Weight Record + #[inline(always)] + pub fn max_voter_weight_record( + &mut self, + max_voter_weight_record: Option<&'b solana_account_info::AccountInfo<'a>>, + ) -> &mut Self { + self.instruction.max_voter_weight_record = max_voter_weight_record; + self + } + /// Add an additional account to the instruction. + #[inline(always)] + pub fn add_remaining_account( + &mut self, + account: &'b solana_account_info::AccountInfo<'a>, + is_writable: bool, + is_signer: bool, + ) -> &mut Self { + self.instruction + .__remaining_accounts + .push((account, is_writable, is_signer)); + self + } + /// Add additional accounts to the instruction. + /// + /// Each account is represented by a tuple of the `AccountInfo`, a `bool` indicating whether the account is writable or not, + /// and a `bool` indicating whether the account is a signer or not. + #[inline(always)] + pub fn add_remaining_accounts( + &mut self, + accounts: &[(&'b solana_account_info::AccountInfo<'a>, bool, bool)], + ) -> &mut Self { + self.instruction + .__remaining_accounts + .extend_from_slice(accounts); + self + } + #[inline(always)] + pub fn invoke(&self) -> solana_program_error::ProgramResult { + self.invoke_signed(&[]) + } + #[allow(clippy::clone_on_copy)] + #[allow(clippy::vec_init_then_push)] + pub fn invoke_signed(&self, signers_seeds: &[&[&[u8]]]) -> solana_program_error::ProgramResult { + let instruction = FinalizeVoteCpi { + __program: self.instruction.__program, + + realm_account: self + .instruction + .realm_account + .expect("realm_account is not set"), + + governance_account: self + .instruction + .governance_account + .expect("governance_account is not set"), + + proposal_account: self + .instruction + .proposal_account + .expect("proposal_account is not set"), + + token_owner_record: self + .instruction + .token_owner_record + .expect("token_owner_record is not set"), + + governing_token_mint: self + .instruction + .governing_token_mint + .expect("governing_token_mint is not set"), + + realm_config: self + .instruction + .realm_config + .expect("realm_config is not set"), + + max_voter_weight_record: self.instruction.max_voter_weight_record, + }; + instruction.invoke_signed_with_remaining_accounts( + signers_seeds, + &self.instruction.__remaining_accounts, + ) + } +} + +#[derive(Clone, Debug)] +struct FinalizeVoteCpiBuilderInstruction<'a, 'b> { + __program: &'b solana_account_info::AccountInfo<'a>, + realm_account: Option<&'b solana_account_info::AccountInfo<'a>>, + governance_account: Option<&'b solana_account_info::AccountInfo<'a>>, + proposal_account: Option<&'b solana_account_info::AccountInfo<'a>>, + token_owner_record: Option<&'b solana_account_info::AccountInfo<'a>>, + governing_token_mint: Option<&'b solana_account_info::AccountInfo<'a>>, + realm_config: Option<&'b solana_account_info::AccountInfo<'a>>, + max_voter_weight_record: Option<&'b solana_account_info::AccountInfo<'a>>, + /// Additional instruction accounts `(AccountInfo, is_writable, is_signer)`. + __remaining_accounts: Vec<(&'b solana_account_info::AccountInfo<'a>, bool, bool)>, +} diff --git a/e2e/governance/src/generated/instructions/flag_transaction_error.rs b/e2e/governance/src/generated/instructions/flag_transaction_error.rs new file mode 100644 index 0000000..3549368 --- /dev/null +++ b/e2e/governance/src/generated/instructions/flag_transaction_error.rs @@ -0,0 +1,416 @@ +//! This code was AUTOGENERATED using the codama library. +//! Please DO NOT EDIT THIS FILE, instead use visitors +//! to add features, then rerun codama to update it. +//! +//! +//! + +use borsh::BorshDeserialize; +use borsh::BorshSerialize; + +pub const FLAG_TRANSACTION_ERROR_DISCRIMINATOR: u8 = 20; + +/// Accounts. +#[derive(Debug)] +pub struct FlagTransactionError { + pub proposal_account: solana_pubkey::Pubkey, + /// TokenOwnerRecord account of the Proposal owner + pub token_owner_record: solana_pubkey::Pubkey, + /// Governance Authority (Token Owner or Governance Delegate) + pub governance_authority: solana_pubkey::Pubkey, + /// ProposalTransaction account to flag + pub proposal_transaction_account: solana_pubkey::Pubkey, +} + +impl FlagTransactionError { + pub fn instruction(&self) -> solana_instruction::Instruction { + self.instruction_with_remaining_accounts(&[]) + } + #[allow(clippy::arithmetic_side_effects)] + #[allow(clippy::vec_init_then_push)] + pub fn instruction_with_remaining_accounts( + &self, + remaining_accounts: &[solana_instruction::AccountMeta], + ) -> solana_instruction::Instruction { + let mut accounts = Vec::with_capacity(4 + remaining_accounts.len()); + accounts.push(solana_instruction::AccountMeta::new( + self.proposal_account, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.token_owner_record, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.governance_authority, + true, + )); + accounts.push(solana_instruction::AccountMeta::new( + self.proposal_transaction_account, + false, + )); + accounts.extend_from_slice(remaining_accounts); + let data = FlagTransactionErrorInstructionData::new() + .try_to_vec() + .unwrap(); + + solana_instruction::Instruction { + program_id: crate::SPL_GOVERNANCE_ID, + accounts, + data, + } + } +} + +#[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct FlagTransactionErrorInstructionData { + discriminator: u8, +} + +impl FlagTransactionErrorInstructionData { + pub fn new() -> Self { + Self { discriminator: 20 } + } + + pub(crate) fn try_to_vec(&self) -> Result, std::io::Error> { + borsh::to_vec(self) + } +} + +impl Default for FlagTransactionErrorInstructionData { + fn default() -> Self { + Self::new() + } +} + +/// Instruction builder for `FlagTransactionError`. +/// +/// ### Accounts: +/// +/// 0. `[writable]` proposal_account +/// 1. `[]` token_owner_record +/// 2. `[signer]` governance_authority +/// 3. `[writable]` proposal_transaction_account +#[derive(Clone, Debug, Default)] +pub struct FlagTransactionErrorBuilder { + proposal_account: Option, + token_owner_record: Option, + governance_authority: Option, + proposal_transaction_account: Option, + __remaining_accounts: Vec, +} + +impl FlagTransactionErrorBuilder { + pub fn new() -> Self { + Self::default() + } + #[inline(always)] + pub fn proposal_account(&mut self, proposal_account: solana_pubkey::Pubkey) -> &mut Self { + self.proposal_account = Some(proposal_account); + self + } + /// TokenOwnerRecord account of the Proposal owner + #[inline(always)] + pub fn token_owner_record(&mut self, token_owner_record: solana_pubkey::Pubkey) -> &mut Self { + self.token_owner_record = Some(token_owner_record); + self + } + /// Governance Authority (Token Owner or Governance Delegate) + #[inline(always)] + pub fn governance_authority( + &mut self, + governance_authority: solana_pubkey::Pubkey, + ) -> &mut Self { + self.governance_authority = Some(governance_authority); + self + } + /// ProposalTransaction account to flag + #[inline(always)] + pub fn proposal_transaction_account( + &mut self, + proposal_transaction_account: solana_pubkey::Pubkey, + ) -> &mut Self { + self.proposal_transaction_account = Some(proposal_transaction_account); + self + } + /// Add an additional account to the instruction. + #[inline(always)] + pub fn add_remaining_account(&mut self, account: solana_instruction::AccountMeta) -> &mut Self { + self.__remaining_accounts.push(account); + self + } + /// Add additional accounts to the instruction. + #[inline(always)] + pub fn add_remaining_accounts( + &mut self, + accounts: &[solana_instruction::AccountMeta], + ) -> &mut Self { + self.__remaining_accounts.extend_from_slice(accounts); + self + } + #[allow(clippy::clone_on_copy)] + pub fn instruction(&self) -> solana_instruction::Instruction { + let accounts = FlagTransactionError { + proposal_account: self.proposal_account.expect("proposal_account is not set"), + token_owner_record: self + .token_owner_record + .expect("token_owner_record is not set"), + governance_authority: self + .governance_authority + .expect("governance_authority is not set"), + proposal_transaction_account: self + .proposal_transaction_account + .expect("proposal_transaction_account is not set"), + }; + + accounts.instruction_with_remaining_accounts(&self.__remaining_accounts) + } +} + +/// `flag_transaction_error` CPI accounts. +pub struct FlagTransactionErrorCpiAccounts<'a, 'b> { + pub proposal_account: &'b solana_account_info::AccountInfo<'a>, + /// TokenOwnerRecord account of the Proposal owner + pub token_owner_record: &'b solana_account_info::AccountInfo<'a>, + /// Governance Authority (Token Owner or Governance Delegate) + pub governance_authority: &'b solana_account_info::AccountInfo<'a>, + /// ProposalTransaction account to flag + pub proposal_transaction_account: &'b solana_account_info::AccountInfo<'a>, +} + +/// `flag_transaction_error` CPI instruction. +pub struct FlagTransactionErrorCpi<'a, 'b> { + /// The program to invoke. + pub __program: &'b solana_account_info::AccountInfo<'a>, + + pub proposal_account: &'b solana_account_info::AccountInfo<'a>, + /// TokenOwnerRecord account of the Proposal owner + pub token_owner_record: &'b solana_account_info::AccountInfo<'a>, + /// Governance Authority (Token Owner or Governance Delegate) + pub governance_authority: &'b solana_account_info::AccountInfo<'a>, + /// ProposalTransaction account to flag + pub proposal_transaction_account: &'b solana_account_info::AccountInfo<'a>, +} + +impl<'a, 'b> FlagTransactionErrorCpi<'a, 'b> { + pub fn new( + program: &'b solana_account_info::AccountInfo<'a>, + accounts: FlagTransactionErrorCpiAccounts<'a, 'b>, + ) -> Self { + Self { + __program: program, + proposal_account: accounts.proposal_account, + token_owner_record: accounts.token_owner_record, + governance_authority: accounts.governance_authority, + proposal_transaction_account: accounts.proposal_transaction_account, + } + } + #[inline(always)] + pub fn invoke(&self) -> solana_program_error::ProgramResult { + self.invoke_signed_with_remaining_accounts(&[], &[]) + } + #[inline(always)] + pub fn invoke_with_remaining_accounts( + &self, + remaining_accounts: &[(&'b solana_account_info::AccountInfo<'a>, bool, bool)], + ) -> solana_program_error::ProgramResult { + self.invoke_signed_with_remaining_accounts(&[], remaining_accounts) + } + #[inline(always)] + pub fn invoke_signed(&self, signers_seeds: &[&[&[u8]]]) -> solana_program_error::ProgramResult { + self.invoke_signed_with_remaining_accounts(signers_seeds, &[]) + } + #[allow(clippy::arithmetic_side_effects)] + #[allow(clippy::clone_on_copy)] + #[allow(clippy::vec_init_then_push)] + pub fn invoke_signed_with_remaining_accounts( + &self, + signers_seeds: &[&[&[u8]]], + remaining_accounts: &[(&'b solana_account_info::AccountInfo<'a>, bool, bool)], + ) -> solana_program_error::ProgramResult { + let mut accounts = Vec::with_capacity(4 + remaining_accounts.len()); + accounts.push(solana_instruction::AccountMeta::new( + *self.proposal_account.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.token_owner_record.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.governance_authority.key, + true, + )); + accounts.push(solana_instruction::AccountMeta::new( + *self.proposal_transaction_account.key, + false, + )); + remaining_accounts.iter().for_each(|remaining_account| { + accounts.push(solana_instruction::AccountMeta { + pubkey: *remaining_account.0.key, + is_signer: remaining_account.1, + is_writable: remaining_account.2, + }) + }); + let data = FlagTransactionErrorInstructionData::new() + .try_to_vec() + .unwrap(); + + let instruction = solana_instruction::Instruction { + program_id: crate::SPL_GOVERNANCE_ID, + accounts, + data, + }; + let mut account_infos = Vec::with_capacity(5 + remaining_accounts.len()); + account_infos.push(self.__program.clone()); + account_infos.push(self.proposal_account.clone()); + account_infos.push(self.token_owner_record.clone()); + account_infos.push(self.governance_authority.clone()); + account_infos.push(self.proposal_transaction_account.clone()); + remaining_accounts + .iter() + .for_each(|remaining_account| account_infos.push(remaining_account.0.clone())); + + if signers_seeds.is_empty() { + solana_cpi::invoke(&instruction, &account_infos) + } else { + solana_cpi::invoke_signed(&instruction, &account_infos, signers_seeds) + } + } +} + +/// Instruction builder for `FlagTransactionError` via CPI. +/// +/// ### Accounts: +/// +/// 0. `[writable]` proposal_account +/// 1. `[]` token_owner_record +/// 2. `[signer]` governance_authority +/// 3. `[writable]` proposal_transaction_account +#[derive(Clone, Debug)] +pub struct FlagTransactionErrorCpiBuilder<'a, 'b> { + instruction: Box>, +} + +impl<'a, 'b> FlagTransactionErrorCpiBuilder<'a, 'b> { + pub fn new(program: &'b solana_account_info::AccountInfo<'a>) -> Self { + let instruction = Box::new(FlagTransactionErrorCpiBuilderInstruction { + __program: program, + proposal_account: None, + token_owner_record: None, + governance_authority: None, + proposal_transaction_account: None, + __remaining_accounts: Vec::new(), + }); + Self { instruction } + } + #[inline(always)] + pub fn proposal_account( + &mut self, + proposal_account: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.proposal_account = Some(proposal_account); + self + } + /// TokenOwnerRecord account of the Proposal owner + #[inline(always)] + pub fn token_owner_record( + &mut self, + token_owner_record: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.token_owner_record = Some(token_owner_record); + self + } + /// Governance Authority (Token Owner or Governance Delegate) + #[inline(always)] + pub fn governance_authority( + &mut self, + governance_authority: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.governance_authority = Some(governance_authority); + self + } + /// ProposalTransaction account to flag + #[inline(always)] + pub fn proposal_transaction_account( + &mut self, + proposal_transaction_account: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.proposal_transaction_account = Some(proposal_transaction_account); + self + } + /// Add an additional account to the instruction. + #[inline(always)] + pub fn add_remaining_account( + &mut self, + account: &'b solana_account_info::AccountInfo<'a>, + is_writable: bool, + is_signer: bool, + ) -> &mut Self { + self.instruction + .__remaining_accounts + .push((account, is_writable, is_signer)); + self + } + /// Add additional accounts to the instruction. + /// + /// Each account is represented by a tuple of the `AccountInfo`, a `bool` indicating whether the account is writable or not, + /// and a `bool` indicating whether the account is a signer or not. + #[inline(always)] + pub fn add_remaining_accounts( + &mut self, + accounts: &[(&'b solana_account_info::AccountInfo<'a>, bool, bool)], + ) -> &mut Self { + self.instruction + .__remaining_accounts + .extend_from_slice(accounts); + self + } + #[inline(always)] + pub fn invoke(&self) -> solana_program_error::ProgramResult { + self.invoke_signed(&[]) + } + #[allow(clippy::clone_on_copy)] + #[allow(clippy::vec_init_then_push)] + pub fn invoke_signed(&self, signers_seeds: &[&[&[u8]]]) -> solana_program_error::ProgramResult { + let instruction = FlagTransactionErrorCpi { + __program: self.instruction.__program, + + proposal_account: self + .instruction + .proposal_account + .expect("proposal_account is not set"), + + token_owner_record: self + .instruction + .token_owner_record + .expect("token_owner_record is not set"), + + governance_authority: self + .instruction + .governance_authority + .expect("governance_authority is not set"), + + proposal_transaction_account: self + .instruction + .proposal_transaction_account + .expect("proposal_transaction_account is not set"), + }; + instruction.invoke_signed_with_remaining_accounts( + signers_seeds, + &self.instruction.__remaining_accounts, + ) + } +} + +#[derive(Clone, Debug)] +struct FlagTransactionErrorCpiBuilderInstruction<'a, 'b> { + __program: &'b solana_account_info::AccountInfo<'a>, + proposal_account: Option<&'b solana_account_info::AccountInfo<'a>>, + token_owner_record: Option<&'b solana_account_info::AccountInfo<'a>>, + governance_authority: Option<&'b solana_account_info::AccountInfo<'a>>, + proposal_transaction_account: Option<&'b solana_account_info::AccountInfo<'a>>, + /// Additional instruction accounts `(AccountInfo, is_writable, is_signer)`. + __remaining_accounts: Vec<(&'b solana_account_info::AccountInfo<'a>, bool, bool)>, +} diff --git a/e2e/governance/src/generated/instructions/insert_transaction.rs b/e2e/governance/src/generated/instructions/insert_transaction.rs new file mode 100644 index 0000000..e670906 --- /dev/null +++ b/e2e/governance/src/generated/instructions/insert_transaction.rs @@ -0,0 +1,675 @@ +//! This code was AUTOGENERATED using the codama library. +//! Please DO NOT EDIT THIS FILE, instead use visitors +//! to add features, then rerun codama to update it. +//! +//! +//! + +use crate::generated::types::InstructionData; +use borsh::BorshDeserialize; +use borsh::BorshSerialize; + +pub const INSERT_TRANSACTION_DISCRIMINATOR: u8 = 9; + +/// Accounts. +#[derive(Debug)] +pub struct InsertTransaction { + pub governance_account: solana_pubkey::Pubkey, + + pub proposal_account: solana_pubkey::Pubkey, + /// TokenOwnerRecord account of the Proposal owner + pub token_owner_record: solana_pubkey::Pubkey, + /// Governance Authority (Token Owner or Governance Delegate) + pub governance_authority: solana_pubkey::Pubkey, + /// ProposalTransaction, account. PDA seeds: ['governance', proposal, option_index, index] + pub proposal_transaction_account: solana_pubkey::Pubkey, + + pub payer: solana_pubkey::Pubkey, + + pub system_program: solana_pubkey::Pubkey, + + pub rent: solana_pubkey::Pubkey, +} + +impl InsertTransaction { + pub fn instruction( + &self, + args: InsertTransactionInstructionArgs, + ) -> solana_instruction::Instruction { + self.instruction_with_remaining_accounts(args, &[]) + } + #[allow(clippy::arithmetic_side_effects)] + #[allow(clippy::vec_init_then_push)] + pub fn instruction_with_remaining_accounts( + &self, + args: InsertTransactionInstructionArgs, + remaining_accounts: &[solana_instruction::AccountMeta], + ) -> solana_instruction::Instruction { + let mut accounts = Vec::with_capacity(8 + remaining_accounts.len()); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.governance_account, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + self.proposal_account, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.token_owner_record, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.governance_authority, + true, + )); + accounts.push(solana_instruction::AccountMeta::new( + self.proposal_transaction_account, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.payer, true, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.system_program, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.rent, false, + )); + accounts.extend_from_slice(remaining_accounts); + let mut data = InsertTransactionInstructionData::new() + .try_to_vec() + .unwrap(); + let mut args = args.try_to_vec().unwrap(); + data.append(&mut args); + + solana_instruction::Instruction { + program_id: crate::SPL_GOVERNANCE_ID, + accounts, + data, + } + } +} + +#[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct InsertTransactionInstructionData { + discriminator: u8, +} + +impl InsertTransactionInstructionData { + pub fn new() -> Self { + Self { discriminator: 9 } + } + + pub(crate) fn try_to_vec(&self) -> Result, std::io::Error> { + borsh::to_vec(self) + } +} + +impl Default for InsertTransactionInstructionData { + fn default() -> Self { + Self::new() + } +} + +#[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct InsertTransactionInstructionArgs { + pub option_index: u8, + pub index: u16, + pub hold_up_time: u32, + pub instructions: Vec, +} + +impl InsertTransactionInstructionArgs { + pub(crate) fn try_to_vec(&self) -> Result, std::io::Error> { + borsh::to_vec(self) + } +} + +/// Instruction builder for `InsertTransaction`. +/// +/// ### Accounts: +/// +/// 0. `[]` governance_account +/// 1. `[writable]` proposal_account +/// 2. `[]` token_owner_record +/// 3. `[signer]` governance_authority +/// 4. `[writable]` proposal_transaction_account +/// 5. `[signer]` payer +/// 6. `[optional]` system_program (default to `11111111111111111111111111111111`) +/// 7. `[optional]` rent (default to `SysvarRent111111111111111111111111111111111`) +#[derive(Clone, Debug, Default)] +pub struct InsertTransactionBuilder { + governance_account: Option, + proposal_account: Option, + token_owner_record: Option, + governance_authority: Option, + proposal_transaction_account: Option, + payer: Option, + system_program: Option, + rent: Option, + option_index: Option, + index: Option, + hold_up_time: Option, + instructions: Option>, + __remaining_accounts: Vec, +} + +impl InsertTransactionBuilder { + pub fn new() -> Self { + Self::default() + } + #[inline(always)] + pub fn governance_account(&mut self, governance_account: solana_pubkey::Pubkey) -> &mut Self { + self.governance_account = Some(governance_account); + self + } + #[inline(always)] + pub fn proposal_account(&mut self, proposal_account: solana_pubkey::Pubkey) -> &mut Self { + self.proposal_account = Some(proposal_account); + self + } + /// TokenOwnerRecord account of the Proposal owner + #[inline(always)] + pub fn token_owner_record(&mut self, token_owner_record: solana_pubkey::Pubkey) -> &mut Self { + self.token_owner_record = Some(token_owner_record); + self + } + /// Governance Authority (Token Owner or Governance Delegate) + #[inline(always)] + pub fn governance_authority( + &mut self, + governance_authority: solana_pubkey::Pubkey, + ) -> &mut Self { + self.governance_authority = Some(governance_authority); + self + } + /// ProposalTransaction, account. PDA seeds: ['governance', proposal, option_index, index] + #[inline(always)] + pub fn proposal_transaction_account( + &mut self, + proposal_transaction_account: solana_pubkey::Pubkey, + ) -> &mut Self { + self.proposal_transaction_account = Some(proposal_transaction_account); + self + } + #[inline(always)] + pub fn payer(&mut self, payer: solana_pubkey::Pubkey) -> &mut Self { + self.payer = Some(payer); + self + } + /// `[optional account, default to '11111111111111111111111111111111']` + #[inline(always)] + pub fn system_program(&mut self, system_program: solana_pubkey::Pubkey) -> &mut Self { + self.system_program = Some(system_program); + self + } + /// `[optional account, default to 'SysvarRent111111111111111111111111111111111']` + #[inline(always)] + pub fn rent(&mut self, rent: solana_pubkey::Pubkey) -> &mut Self { + self.rent = Some(rent); + self + } + #[inline(always)] + pub fn option_index(&mut self, option_index: u8) -> &mut Self { + self.option_index = Some(option_index); + self + } + #[inline(always)] + pub fn index(&mut self, index: u16) -> &mut Self { + self.index = Some(index); + self + } + #[inline(always)] + pub fn hold_up_time(&mut self, hold_up_time: u32) -> &mut Self { + self.hold_up_time = Some(hold_up_time); + self + } + #[inline(always)] + pub fn instructions(&mut self, instructions: Vec) -> &mut Self { + self.instructions = Some(instructions); + self + } + /// Add an additional account to the instruction. + #[inline(always)] + pub fn add_remaining_account(&mut self, account: solana_instruction::AccountMeta) -> &mut Self { + self.__remaining_accounts.push(account); + self + } + /// Add additional accounts to the instruction. + #[inline(always)] + pub fn add_remaining_accounts( + &mut self, + accounts: &[solana_instruction::AccountMeta], + ) -> &mut Self { + self.__remaining_accounts.extend_from_slice(accounts); + self + } + #[allow(clippy::clone_on_copy)] + pub fn instruction(&self) -> solana_instruction::Instruction { + let accounts = InsertTransaction { + governance_account: self + .governance_account + .expect("governance_account is not set"), + proposal_account: self.proposal_account.expect("proposal_account is not set"), + token_owner_record: self + .token_owner_record + .expect("token_owner_record is not set"), + governance_authority: self + .governance_authority + .expect("governance_authority is not set"), + proposal_transaction_account: self + .proposal_transaction_account + .expect("proposal_transaction_account is not set"), + payer: self.payer.expect("payer is not set"), + system_program: self + .system_program + .unwrap_or(solana_pubkey::pubkey!("11111111111111111111111111111111")), + rent: self.rent.unwrap_or(solana_pubkey::pubkey!( + "SysvarRent111111111111111111111111111111111" + )), + }; + let args = InsertTransactionInstructionArgs { + option_index: self.option_index.clone().expect("option_index is not set"), + index: self.index.clone().expect("index is not set"), + hold_up_time: self.hold_up_time.clone().expect("hold_up_time is not set"), + instructions: self.instructions.clone().expect("instructions is not set"), + }; + + accounts.instruction_with_remaining_accounts(args, &self.__remaining_accounts) + } +} + +/// `insert_transaction` CPI accounts. +pub struct InsertTransactionCpiAccounts<'a, 'b> { + pub governance_account: &'b solana_account_info::AccountInfo<'a>, + + pub proposal_account: &'b solana_account_info::AccountInfo<'a>, + /// TokenOwnerRecord account of the Proposal owner + pub token_owner_record: &'b solana_account_info::AccountInfo<'a>, + /// Governance Authority (Token Owner or Governance Delegate) + pub governance_authority: &'b solana_account_info::AccountInfo<'a>, + /// ProposalTransaction, account. PDA seeds: ['governance', proposal, option_index, index] + pub proposal_transaction_account: &'b solana_account_info::AccountInfo<'a>, + + pub payer: &'b solana_account_info::AccountInfo<'a>, + + pub system_program: &'b solana_account_info::AccountInfo<'a>, + + pub rent: &'b solana_account_info::AccountInfo<'a>, +} + +/// `insert_transaction` CPI instruction. +pub struct InsertTransactionCpi<'a, 'b> { + /// The program to invoke. + pub __program: &'b solana_account_info::AccountInfo<'a>, + + pub governance_account: &'b solana_account_info::AccountInfo<'a>, + + pub proposal_account: &'b solana_account_info::AccountInfo<'a>, + /// TokenOwnerRecord account of the Proposal owner + pub token_owner_record: &'b solana_account_info::AccountInfo<'a>, + /// Governance Authority (Token Owner or Governance Delegate) + pub governance_authority: &'b solana_account_info::AccountInfo<'a>, + /// ProposalTransaction, account. PDA seeds: ['governance', proposal, option_index, index] + pub proposal_transaction_account: &'b solana_account_info::AccountInfo<'a>, + + pub payer: &'b solana_account_info::AccountInfo<'a>, + + pub system_program: &'b solana_account_info::AccountInfo<'a>, + + pub rent: &'b solana_account_info::AccountInfo<'a>, + /// The arguments for the instruction. + pub __args: InsertTransactionInstructionArgs, +} + +impl<'a, 'b> InsertTransactionCpi<'a, 'b> { + pub fn new( + program: &'b solana_account_info::AccountInfo<'a>, + accounts: InsertTransactionCpiAccounts<'a, 'b>, + args: InsertTransactionInstructionArgs, + ) -> Self { + Self { + __program: program, + governance_account: accounts.governance_account, + proposal_account: accounts.proposal_account, + token_owner_record: accounts.token_owner_record, + governance_authority: accounts.governance_authority, + proposal_transaction_account: accounts.proposal_transaction_account, + payer: accounts.payer, + system_program: accounts.system_program, + rent: accounts.rent, + __args: args, + } + } + #[inline(always)] + pub fn invoke(&self) -> solana_program_error::ProgramResult { + self.invoke_signed_with_remaining_accounts(&[], &[]) + } + #[inline(always)] + pub fn invoke_with_remaining_accounts( + &self, + remaining_accounts: &[(&'b solana_account_info::AccountInfo<'a>, bool, bool)], + ) -> solana_program_error::ProgramResult { + self.invoke_signed_with_remaining_accounts(&[], remaining_accounts) + } + #[inline(always)] + pub fn invoke_signed(&self, signers_seeds: &[&[&[u8]]]) -> solana_program_error::ProgramResult { + self.invoke_signed_with_remaining_accounts(signers_seeds, &[]) + } + #[allow(clippy::arithmetic_side_effects)] + #[allow(clippy::clone_on_copy)] + #[allow(clippy::vec_init_then_push)] + pub fn invoke_signed_with_remaining_accounts( + &self, + signers_seeds: &[&[&[u8]]], + remaining_accounts: &[(&'b solana_account_info::AccountInfo<'a>, bool, bool)], + ) -> solana_program_error::ProgramResult { + let mut accounts = Vec::with_capacity(8 + remaining_accounts.len()); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.governance_account.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + *self.proposal_account.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.token_owner_record.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.governance_authority.key, + true, + )); + accounts.push(solana_instruction::AccountMeta::new( + *self.proposal_transaction_account.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.payer.key, + true, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.system_program.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.rent.key, + false, + )); + remaining_accounts.iter().for_each(|remaining_account| { + accounts.push(solana_instruction::AccountMeta { + pubkey: *remaining_account.0.key, + is_signer: remaining_account.1, + is_writable: remaining_account.2, + }) + }); + let mut data = InsertTransactionInstructionData::new() + .try_to_vec() + .unwrap(); + let mut args = self.__args.try_to_vec().unwrap(); + data.append(&mut args); + + let instruction = solana_instruction::Instruction { + program_id: crate::SPL_GOVERNANCE_ID, + accounts, + data, + }; + let mut account_infos = Vec::with_capacity(9 + remaining_accounts.len()); + account_infos.push(self.__program.clone()); + account_infos.push(self.governance_account.clone()); + account_infos.push(self.proposal_account.clone()); + account_infos.push(self.token_owner_record.clone()); + account_infos.push(self.governance_authority.clone()); + account_infos.push(self.proposal_transaction_account.clone()); + account_infos.push(self.payer.clone()); + account_infos.push(self.system_program.clone()); + account_infos.push(self.rent.clone()); + remaining_accounts + .iter() + .for_each(|remaining_account| account_infos.push(remaining_account.0.clone())); + + if signers_seeds.is_empty() { + solana_cpi::invoke(&instruction, &account_infos) + } else { + solana_cpi::invoke_signed(&instruction, &account_infos, signers_seeds) + } + } +} + +/// Instruction builder for `InsertTransaction` via CPI. +/// +/// ### Accounts: +/// +/// 0. `[]` governance_account +/// 1. `[writable]` proposal_account +/// 2. `[]` token_owner_record +/// 3. `[signer]` governance_authority +/// 4. `[writable]` proposal_transaction_account +/// 5. `[signer]` payer +/// 6. `[]` system_program +/// 7. `[]` rent +#[derive(Clone, Debug)] +pub struct InsertTransactionCpiBuilder<'a, 'b> { + instruction: Box>, +} + +impl<'a, 'b> InsertTransactionCpiBuilder<'a, 'b> { + pub fn new(program: &'b solana_account_info::AccountInfo<'a>) -> Self { + let instruction = Box::new(InsertTransactionCpiBuilderInstruction { + __program: program, + governance_account: None, + proposal_account: None, + token_owner_record: None, + governance_authority: None, + proposal_transaction_account: None, + payer: None, + system_program: None, + rent: None, + option_index: None, + index: None, + hold_up_time: None, + instructions: None, + __remaining_accounts: Vec::new(), + }); + Self { instruction } + } + #[inline(always)] + pub fn governance_account( + &mut self, + governance_account: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.governance_account = Some(governance_account); + self + } + #[inline(always)] + pub fn proposal_account( + &mut self, + proposal_account: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.proposal_account = Some(proposal_account); + self + } + /// TokenOwnerRecord account of the Proposal owner + #[inline(always)] + pub fn token_owner_record( + &mut self, + token_owner_record: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.token_owner_record = Some(token_owner_record); + self + } + /// Governance Authority (Token Owner or Governance Delegate) + #[inline(always)] + pub fn governance_authority( + &mut self, + governance_authority: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.governance_authority = Some(governance_authority); + self + } + /// ProposalTransaction, account. PDA seeds: ['governance', proposal, option_index, index] + #[inline(always)] + pub fn proposal_transaction_account( + &mut self, + proposal_transaction_account: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.proposal_transaction_account = Some(proposal_transaction_account); + self + } + #[inline(always)] + pub fn payer(&mut self, payer: &'b solana_account_info::AccountInfo<'a>) -> &mut Self { + self.instruction.payer = Some(payer); + self + } + #[inline(always)] + pub fn system_program( + &mut self, + system_program: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.system_program = Some(system_program); + self + } + #[inline(always)] + pub fn rent(&mut self, rent: &'b solana_account_info::AccountInfo<'a>) -> &mut Self { + self.instruction.rent = Some(rent); + self + } + #[inline(always)] + pub fn option_index(&mut self, option_index: u8) -> &mut Self { + self.instruction.option_index = Some(option_index); + self + } + #[inline(always)] + pub fn index(&mut self, index: u16) -> &mut Self { + self.instruction.index = Some(index); + self + } + #[inline(always)] + pub fn hold_up_time(&mut self, hold_up_time: u32) -> &mut Self { + self.instruction.hold_up_time = Some(hold_up_time); + self + } + #[inline(always)] + pub fn instructions(&mut self, instructions: Vec) -> &mut Self { + self.instruction.instructions = Some(instructions); + self + } + /// Add an additional account to the instruction. + #[inline(always)] + pub fn add_remaining_account( + &mut self, + account: &'b solana_account_info::AccountInfo<'a>, + is_writable: bool, + is_signer: bool, + ) -> &mut Self { + self.instruction + .__remaining_accounts + .push((account, is_writable, is_signer)); + self + } + /// Add additional accounts to the instruction. + /// + /// Each account is represented by a tuple of the `AccountInfo`, a `bool` indicating whether the account is writable or not, + /// and a `bool` indicating whether the account is a signer or not. + #[inline(always)] + pub fn add_remaining_accounts( + &mut self, + accounts: &[(&'b solana_account_info::AccountInfo<'a>, bool, bool)], + ) -> &mut Self { + self.instruction + .__remaining_accounts + .extend_from_slice(accounts); + self + } + #[inline(always)] + pub fn invoke(&self) -> solana_program_error::ProgramResult { + self.invoke_signed(&[]) + } + #[allow(clippy::clone_on_copy)] + #[allow(clippy::vec_init_then_push)] + pub fn invoke_signed(&self, signers_seeds: &[&[&[u8]]]) -> solana_program_error::ProgramResult { + let args = InsertTransactionInstructionArgs { + option_index: self + .instruction + .option_index + .clone() + .expect("option_index is not set"), + index: self.instruction.index.clone().expect("index is not set"), + hold_up_time: self + .instruction + .hold_up_time + .clone() + .expect("hold_up_time is not set"), + instructions: self + .instruction + .instructions + .clone() + .expect("instructions is not set"), + }; + let instruction = InsertTransactionCpi { + __program: self.instruction.__program, + + governance_account: self + .instruction + .governance_account + .expect("governance_account is not set"), + + proposal_account: self + .instruction + .proposal_account + .expect("proposal_account is not set"), + + token_owner_record: self + .instruction + .token_owner_record + .expect("token_owner_record is not set"), + + governance_authority: self + .instruction + .governance_authority + .expect("governance_authority is not set"), + + proposal_transaction_account: self + .instruction + .proposal_transaction_account + .expect("proposal_transaction_account is not set"), + + payer: self.instruction.payer.expect("payer is not set"), + + system_program: self + .instruction + .system_program + .expect("system_program is not set"), + + rent: self.instruction.rent.expect("rent is not set"), + __args: args, + }; + instruction.invoke_signed_with_remaining_accounts( + signers_seeds, + &self.instruction.__remaining_accounts, + ) + } +} + +#[derive(Clone, Debug)] +struct InsertTransactionCpiBuilderInstruction<'a, 'b> { + __program: &'b solana_account_info::AccountInfo<'a>, + governance_account: Option<&'b solana_account_info::AccountInfo<'a>>, + proposal_account: Option<&'b solana_account_info::AccountInfo<'a>>, + token_owner_record: Option<&'b solana_account_info::AccountInfo<'a>>, + governance_authority: Option<&'b solana_account_info::AccountInfo<'a>>, + proposal_transaction_account: Option<&'b solana_account_info::AccountInfo<'a>>, + payer: Option<&'b solana_account_info::AccountInfo<'a>>, + system_program: Option<&'b solana_account_info::AccountInfo<'a>>, + rent: Option<&'b solana_account_info::AccountInfo<'a>>, + option_index: Option, + index: Option, + hold_up_time: Option, + instructions: Option>, + /// Additional instruction accounts `(AccountInfo, is_writable, is_signer)`. + __remaining_accounts: Vec<(&'b solana_account_info::AccountInfo<'a>, bool, bool)>, +} diff --git a/e2e/governance/src/generated/instructions/legacy1.rs b/e2e/governance/src/generated/instructions/legacy1.rs new file mode 100644 index 0000000..9e155f0 --- /dev/null +++ b/e2e/governance/src/generated/instructions/legacy1.rs @@ -0,0 +1,225 @@ +//! This code was AUTOGENERATED using the codama library. +//! Please DO NOT EDIT THIS FILE, instead use visitors +//! to add features, then rerun codama to update it. +//! +//! +//! + +use borsh::BorshDeserialize; +use borsh::BorshSerialize; + +pub const LEGACY1_DISCRIMINATOR: u8 = 8; + +/// Accounts. +#[derive(Debug)] +pub struct Legacy1 {} + +impl Legacy1 { + pub fn instruction(&self) -> solana_instruction::Instruction { + self.instruction_with_remaining_accounts(&[]) + } + #[allow(clippy::arithmetic_side_effects)] + #[allow(clippy::vec_init_then_push)] + pub fn instruction_with_remaining_accounts( + &self, + remaining_accounts: &[solana_instruction::AccountMeta], + ) -> solana_instruction::Instruction { + let mut accounts = Vec::with_capacity(remaining_accounts.len()); + accounts.extend_from_slice(remaining_accounts); + let data = Legacy1InstructionData::new().try_to_vec().unwrap(); + + solana_instruction::Instruction { + program_id: crate::SPL_GOVERNANCE_ID, + accounts, + data, + } + } +} + +#[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct Legacy1InstructionData { + discriminator: u8, +} + +impl Legacy1InstructionData { + pub fn new() -> Self { + Self { discriminator: 8 } + } + + pub(crate) fn try_to_vec(&self) -> Result, std::io::Error> { + borsh::to_vec(self) + } +} + +impl Default for Legacy1InstructionData { + fn default() -> Self { + Self::new() + } +} + +/// Instruction builder for `Legacy1`. +/// +/// ### Accounts: +/// +#[derive(Clone, Debug, Default)] +pub struct Legacy1Builder { + __remaining_accounts: Vec, +} + +impl Legacy1Builder { + pub fn new() -> Self { + Self::default() + } + /// Add an additional account to the instruction. + #[inline(always)] + pub fn add_remaining_account(&mut self, account: solana_instruction::AccountMeta) -> &mut Self { + self.__remaining_accounts.push(account); + self + } + /// Add additional accounts to the instruction. + #[inline(always)] + pub fn add_remaining_accounts( + &mut self, + accounts: &[solana_instruction::AccountMeta], + ) -> &mut Self { + self.__remaining_accounts.extend_from_slice(accounts); + self + } + #[allow(clippy::clone_on_copy)] + pub fn instruction(&self) -> solana_instruction::Instruction { + let accounts = Legacy1 {}; + + accounts.instruction_with_remaining_accounts(&self.__remaining_accounts) + } +} + +/// `legacy1` CPI instruction. +pub struct Legacy1Cpi<'a, 'b> { + /// The program to invoke. + pub __program: &'b solana_account_info::AccountInfo<'a>, +} + +impl<'a, 'b> Legacy1Cpi<'a, 'b> { + pub fn new(program: &'b solana_account_info::AccountInfo<'a>) -> Self { + Self { __program: program } + } + #[inline(always)] + pub fn invoke(&self) -> solana_program_error::ProgramResult { + self.invoke_signed_with_remaining_accounts(&[], &[]) + } + #[inline(always)] + pub fn invoke_with_remaining_accounts( + &self, + remaining_accounts: &[(&'b solana_account_info::AccountInfo<'a>, bool, bool)], + ) -> solana_program_error::ProgramResult { + self.invoke_signed_with_remaining_accounts(&[], remaining_accounts) + } + #[inline(always)] + pub fn invoke_signed(&self, signers_seeds: &[&[&[u8]]]) -> solana_program_error::ProgramResult { + self.invoke_signed_with_remaining_accounts(signers_seeds, &[]) + } + #[allow(clippy::arithmetic_side_effects)] + #[allow(clippy::clone_on_copy)] + #[allow(clippy::vec_init_then_push)] + pub fn invoke_signed_with_remaining_accounts( + &self, + signers_seeds: &[&[&[u8]]], + remaining_accounts: &[(&'b solana_account_info::AccountInfo<'a>, bool, bool)], + ) -> solana_program_error::ProgramResult { + let mut accounts = Vec::with_capacity(remaining_accounts.len()); + remaining_accounts.iter().for_each(|remaining_account| { + accounts.push(solana_instruction::AccountMeta { + pubkey: *remaining_account.0.key, + is_signer: remaining_account.1, + is_writable: remaining_account.2, + }) + }); + let data = Legacy1InstructionData::new().try_to_vec().unwrap(); + + let instruction = solana_instruction::Instruction { + program_id: crate::SPL_GOVERNANCE_ID, + accounts, + data, + }; + let mut account_infos = Vec::with_capacity(1 + remaining_accounts.len()); + account_infos.push(self.__program.clone()); + remaining_accounts + .iter() + .for_each(|remaining_account| account_infos.push(remaining_account.0.clone())); + + if signers_seeds.is_empty() { + solana_cpi::invoke(&instruction, &account_infos) + } else { + solana_cpi::invoke_signed(&instruction, &account_infos, signers_seeds) + } + } +} + +/// Instruction builder for `Legacy1` via CPI. +/// +/// ### Accounts: +/// +#[derive(Clone, Debug)] +pub struct Legacy1CpiBuilder<'a, 'b> { + instruction: Box>, +} + +impl<'a, 'b> Legacy1CpiBuilder<'a, 'b> { + pub fn new(program: &'b solana_account_info::AccountInfo<'a>) -> Self { + let instruction = Box::new(Legacy1CpiBuilderInstruction { + __program: program, + __remaining_accounts: Vec::new(), + }); + Self { instruction } + } + /// Add an additional account to the instruction. + #[inline(always)] + pub fn add_remaining_account( + &mut self, + account: &'b solana_account_info::AccountInfo<'a>, + is_writable: bool, + is_signer: bool, + ) -> &mut Self { + self.instruction + .__remaining_accounts + .push((account, is_writable, is_signer)); + self + } + /// Add additional accounts to the instruction. + /// + /// Each account is represented by a tuple of the `AccountInfo`, a `bool` indicating whether the account is writable or not, + /// and a `bool` indicating whether the account is a signer or not. + #[inline(always)] + pub fn add_remaining_accounts( + &mut self, + accounts: &[(&'b solana_account_info::AccountInfo<'a>, bool, bool)], + ) -> &mut Self { + self.instruction + .__remaining_accounts + .extend_from_slice(accounts); + self + } + #[inline(always)] + pub fn invoke(&self) -> solana_program_error::ProgramResult { + self.invoke_signed(&[]) + } + #[allow(clippy::clone_on_copy)] + #[allow(clippy::vec_init_then_push)] + pub fn invoke_signed(&self, signers_seeds: &[&[&[u8]]]) -> solana_program_error::ProgramResult { + let instruction = Legacy1Cpi { + __program: self.instruction.__program, + }; + instruction.invoke_signed_with_remaining_accounts( + signers_seeds, + &self.instruction.__remaining_accounts, + ) + } +} + +#[derive(Clone, Debug)] +struct Legacy1CpiBuilderInstruction<'a, 'b> { + __program: &'b solana_account_info::AccountInfo<'a>, + /// Additional instruction accounts `(AccountInfo, is_writable, is_signer)`. + __remaining_accounts: Vec<(&'b solana_account_info::AccountInfo<'a>, bool, bool)>, +} diff --git a/e2e/governance/src/generated/instructions/mod.rs b/e2e/governance/src/generated/instructions/mod.rs new file mode 100644 index 0000000..6531b79 --- /dev/null +++ b/e2e/governance/src/generated/instructions/mod.rs @@ -0,0 +1,70 @@ +//! This code was AUTOGENERATED using the codama library. +//! Please DO NOT EDIT THIS FILE, instead use visitors +//! to add features, then rerun codama to update it. +//! +//! +//! + +pub(crate) mod r#add_required_signatory; +pub(crate) mod r#add_signatory; +pub(crate) mod r#cancel_proposal; +pub(crate) mod r#cast_vote; +pub(crate) mod r#complete_proposal; +pub(crate) mod r#create_governance; +pub(crate) mod r#create_mint_governance; +pub(crate) mod r#create_native_treasury; +pub(crate) mod r#create_program_governance; +pub(crate) mod r#create_proposal; +pub(crate) mod r#create_realm; +pub(crate) mod r#create_token_governance; +pub(crate) mod r#create_token_owner_record; +pub(crate) mod r#deposit_governing_tokens; +pub(crate) mod r#execute_transaction; +pub(crate) mod r#finalize_vote; +pub(crate) mod r#flag_transaction_error; +pub(crate) mod r#insert_transaction; +pub(crate) mod r#legacy1; +pub(crate) mod r#refund_proposal_deposit; +pub(crate) mod r#relinquish_vote; +pub(crate) mod r#remove_required_signatory; +pub(crate) mod r#remove_transaction; +pub(crate) mod r#revoke_governing_tokens; +pub(crate) mod r#set_governance_config; +pub(crate) mod r#set_governance_delegate; +pub(crate) mod r#set_realm_authority; +pub(crate) mod r#set_realm_config; +pub(crate) mod r#sign_off_proposal; +pub(crate) mod r#update_program_metadata; +pub(crate) mod r#withdraw_governing_tokens; + +pub use self::r#add_required_signatory::*; +pub use self::r#add_signatory::*; +pub use self::r#cancel_proposal::*; +pub use self::r#cast_vote::*; +pub use self::r#complete_proposal::*; +pub use self::r#create_governance::*; +pub use self::r#create_mint_governance::*; +pub use self::r#create_native_treasury::*; +pub use self::r#create_program_governance::*; +pub use self::r#create_proposal::*; +pub use self::r#create_realm::*; +pub use self::r#create_token_governance::*; +pub use self::r#create_token_owner_record::*; +pub use self::r#deposit_governing_tokens::*; +pub use self::r#execute_transaction::*; +pub use self::r#finalize_vote::*; +pub use self::r#flag_transaction_error::*; +pub use self::r#insert_transaction::*; +pub use self::r#legacy1::*; +pub use self::r#refund_proposal_deposit::*; +pub use self::r#relinquish_vote::*; +pub use self::r#remove_required_signatory::*; +pub use self::r#remove_transaction::*; +pub use self::r#revoke_governing_tokens::*; +pub use self::r#set_governance_config::*; +pub use self::r#set_governance_delegate::*; +pub use self::r#set_realm_authority::*; +pub use self::r#set_realm_config::*; +pub use self::r#sign_off_proposal::*; +pub use self::r#update_program_metadata::*; +pub use self::r#withdraw_governing_tokens::*; diff --git a/e2e/governance/src/generated/instructions/refund_proposal_deposit.rs b/e2e/governance/src/generated/instructions/refund_proposal_deposit.rs new file mode 100644 index 0000000..9c672c1 --- /dev/null +++ b/e2e/governance/src/generated/instructions/refund_proposal_deposit.rs @@ -0,0 +1,372 @@ +//! This code was AUTOGENERATED using the codama library. +//! Please DO NOT EDIT THIS FILE, instead use visitors +//! to add features, then rerun codama to update it. +//! +//! +//! + +use borsh::BorshDeserialize; +use borsh::BorshSerialize; + +pub const REFUND_PROPOSAL_DEPOSIT_DISCRIMINATOR: u8 = 27; + +/// Accounts. +#[derive(Debug)] +pub struct RefundProposalDeposit { + pub proposal_account: solana_pubkey::Pubkey, + /// PDA Seeds: ['proposal-deposit', proposal, deposit payer] + pub proposal_deposit_account: solana_pubkey::Pubkey, + /// Proposal Deposit Payer (beneficiary) account + pub proposal_deposit_payer: solana_pubkey::Pubkey, +} + +impl RefundProposalDeposit { + pub fn instruction(&self) -> solana_instruction::Instruction { + self.instruction_with_remaining_accounts(&[]) + } + #[allow(clippy::arithmetic_side_effects)] + #[allow(clippy::vec_init_then_push)] + pub fn instruction_with_remaining_accounts( + &self, + remaining_accounts: &[solana_instruction::AccountMeta], + ) -> solana_instruction::Instruction { + let mut accounts = Vec::with_capacity(3 + remaining_accounts.len()); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.proposal_account, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + self.proposal_deposit_account, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + self.proposal_deposit_payer, + false, + )); + accounts.extend_from_slice(remaining_accounts); + let data = RefundProposalDepositInstructionData::new() + .try_to_vec() + .unwrap(); + + solana_instruction::Instruction { + program_id: crate::SPL_GOVERNANCE_ID, + accounts, + data, + } + } +} + +#[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct RefundProposalDepositInstructionData { + discriminator: u8, +} + +impl RefundProposalDepositInstructionData { + pub fn new() -> Self { + Self { discriminator: 27 } + } + + pub(crate) fn try_to_vec(&self) -> Result, std::io::Error> { + borsh::to_vec(self) + } +} + +impl Default for RefundProposalDepositInstructionData { + fn default() -> Self { + Self::new() + } +} + +/// Instruction builder for `RefundProposalDeposit`. +/// +/// ### Accounts: +/// +/// 0. `[]` proposal_account +/// 1. `[writable]` proposal_deposit_account +/// 2. `[writable]` proposal_deposit_payer +#[derive(Clone, Debug, Default)] +pub struct RefundProposalDepositBuilder { + proposal_account: Option, + proposal_deposit_account: Option, + proposal_deposit_payer: Option, + __remaining_accounts: Vec, +} + +impl RefundProposalDepositBuilder { + pub fn new() -> Self { + Self::default() + } + #[inline(always)] + pub fn proposal_account(&mut self, proposal_account: solana_pubkey::Pubkey) -> &mut Self { + self.proposal_account = Some(proposal_account); + self + } + /// PDA Seeds: ['proposal-deposit', proposal, deposit payer] + #[inline(always)] + pub fn proposal_deposit_account( + &mut self, + proposal_deposit_account: solana_pubkey::Pubkey, + ) -> &mut Self { + self.proposal_deposit_account = Some(proposal_deposit_account); + self + } + /// Proposal Deposit Payer (beneficiary) account + #[inline(always)] + pub fn proposal_deposit_payer( + &mut self, + proposal_deposit_payer: solana_pubkey::Pubkey, + ) -> &mut Self { + self.proposal_deposit_payer = Some(proposal_deposit_payer); + self + } + /// Add an additional account to the instruction. + #[inline(always)] + pub fn add_remaining_account(&mut self, account: solana_instruction::AccountMeta) -> &mut Self { + self.__remaining_accounts.push(account); + self + } + /// Add additional accounts to the instruction. + #[inline(always)] + pub fn add_remaining_accounts( + &mut self, + accounts: &[solana_instruction::AccountMeta], + ) -> &mut Self { + self.__remaining_accounts.extend_from_slice(accounts); + self + } + #[allow(clippy::clone_on_copy)] + pub fn instruction(&self) -> solana_instruction::Instruction { + let accounts = RefundProposalDeposit { + proposal_account: self.proposal_account.expect("proposal_account is not set"), + proposal_deposit_account: self + .proposal_deposit_account + .expect("proposal_deposit_account is not set"), + proposal_deposit_payer: self + .proposal_deposit_payer + .expect("proposal_deposit_payer is not set"), + }; + + accounts.instruction_with_remaining_accounts(&self.__remaining_accounts) + } +} + +/// `refund_proposal_deposit` CPI accounts. +pub struct RefundProposalDepositCpiAccounts<'a, 'b> { + pub proposal_account: &'b solana_account_info::AccountInfo<'a>, + /// PDA Seeds: ['proposal-deposit', proposal, deposit payer] + pub proposal_deposit_account: &'b solana_account_info::AccountInfo<'a>, + /// Proposal Deposit Payer (beneficiary) account + pub proposal_deposit_payer: &'b solana_account_info::AccountInfo<'a>, +} + +/// `refund_proposal_deposit` CPI instruction. +pub struct RefundProposalDepositCpi<'a, 'b> { + /// The program to invoke. + pub __program: &'b solana_account_info::AccountInfo<'a>, + + pub proposal_account: &'b solana_account_info::AccountInfo<'a>, + /// PDA Seeds: ['proposal-deposit', proposal, deposit payer] + pub proposal_deposit_account: &'b solana_account_info::AccountInfo<'a>, + /// Proposal Deposit Payer (beneficiary) account + pub proposal_deposit_payer: &'b solana_account_info::AccountInfo<'a>, +} + +impl<'a, 'b> RefundProposalDepositCpi<'a, 'b> { + pub fn new( + program: &'b solana_account_info::AccountInfo<'a>, + accounts: RefundProposalDepositCpiAccounts<'a, 'b>, + ) -> Self { + Self { + __program: program, + proposal_account: accounts.proposal_account, + proposal_deposit_account: accounts.proposal_deposit_account, + proposal_deposit_payer: accounts.proposal_deposit_payer, + } + } + #[inline(always)] + pub fn invoke(&self) -> solana_program_error::ProgramResult { + self.invoke_signed_with_remaining_accounts(&[], &[]) + } + #[inline(always)] + pub fn invoke_with_remaining_accounts( + &self, + remaining_accounts: &[(&'b solana_account_info::AccountInfo<'a>, bool, bool)], + ) -> solana_program_error::ProgramResult { + self.invoke_signed_with_remaining_accounts(&[], remaining_accounts) + } + #[inline(always)] + pub fn invoke_signed(&self, signers_seeds: &[&[&[u8]]]) -> solana_program_error::ProgramResult { + self.invoke_signed_with_remaining_accounts(signers_seeds, &[]) + } + #[allow(clippy::arithmetic_side_effects)] + #[allow(clippy::clone_on_copy)] + #[allow(clippy::vec_init_then_push)] + pub fn invoke_signed_with_remaining_accounts( + &self, + signers_seeds: &[&[&[u8]]], + remaining_accounts: &[(&'b solana_account_info::AccountInfo<'a>, bool, bool)], + ) -> solana_program_error::ProgramResult { + let mut accounts = Vec::with_capacity(3 + remaining_accounts.len()); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.proposal_account.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + *self.proposal_deposit_account.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + *self.proposal_deposit_payer.key, + false, + )); + remaining_accounts.iter().for_each(|remaining_account| { + accounts.push(solana_instruction::AccountMeta { + pubkey: *remaining_account.0.key, + is_signer: remaining_account.1, + is_writable: remaining_account.2, + }) + }); + let data = RefundProposalDepositInstructionData::new() + .try_to_vec() + .unwrap(); + + let instruction = solana_instruction::Instruction { + program_id: crate::SPL_GOVERNANCE_ID, + accounts, + data, + }; + let mut account_infos = Vec::with_capacity(4 + remaining_accounts.len()); + account_infos.push(self.__program.clone()); + account_infos.push(self.proposal_account.clone()); + account_infos.push(self.proposal_deposit_account.clone()); + account_infos.push(self.proposal_deposit_payer.clone()); + remaining_accounts + .iter() + .for_each(|remaining_account| account_infos.push(remaining_account.0.clone())); + + if signers_seeds.is_empty() { + solana_cpi::invoke(&instruction, &account_infos) + } else { + solana_cpi::invoke_signed(&instruction, &account_infos, signers_seeds) + } + } +} + +/// Instruction builder for `RefundProposalDeposit` via CPI. +/// +/// ### Accounts: +/// +/// 0. `[]` proposal_account +/// 1. `[writable]` proposal_deposit_account +/// 2. `[writable]` proposal_deposit_payer +#[derive(Clone, Debug)] +pub struct RefundProposalDepositCpiBuilder<'a, 'b> { + instruction: Box>, +} + +impl<'a, 'b> RefundProposalDepositCpiBuilder<'a, 'b> { + pub fn new(program: &'b solana_account_info::AccountInfo<'a>) -> Self { + let instruction = Box::new(RefundProposalDepositCpiBuilderInstruction { + __program: program, + proposal_account: None, + proposal_deposit_account: None, + proposal_deposit_payer: None, + __remaining_accounts: Vec::new(), + }); + Self { instruction } + } + #[inline(always)] + pub fn proposal_account( + &mut self, + proposal_account: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.proposal_account = Some(proposal_account); + self + } + /// PDA Seeds: ['proposal-deposit', proposal, deposit payer] + #[inline(always)] + pub fn proposal_deposit_account( + &mut self, + proposal_deposit_account: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.proposal_deposit_account = Some(proposal_deposit_account); + self + } + /// Proposal Deposit Payer (beneficiary) account + #[inline(always)] + pub fn proposal_deposit_payer( + &mut self, + proposal_deposit_payer: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.proposal_deposit_payer = Some(proposal_deposit_payer); + self + } + /// Add an additional account to the instruction. + #[inline(always)] + pub fn add_remaining_account( + &mut self, + account: &'b solana_account_info::AccountInfo<'a>, + is_writable: bool, + is_signer: bool, + ) -> &mut Self { + self.instruction + .__remaining_accounts + .push((account, is_writable, is_signer)); + self + } + /// Add additional accounts to the instruction. + /// + /// Each account is represented by a tuple of the `AccountInfo`, a `bool` indicating whether the account is writable or not, + /// and a `bool` indicating whether the account is a signer or not. + #[inline(always)] + pub fn add_remaining_accounts( + &mut self, + accounts: &[(&'b solana_account_info::AccountInfo<'a>, bool, bool)], + ) -> &mut Self { + self.instruction + .__remaining_accounts + .extend_from_slice(accounts); + self + } + #[inline(always)] + pub fn invoke(&self) -> solana_program_error::ProgramResult { + self.invoke_signed(&[]) + } + #[allow(clippy::clone_on_copy)] + #[allow(clippy::vec_init_then_push)] + pub fn invoke_signed(&self, signers_seeds: &[&[&[u8]]]) -> solana_program_error::ProgramResult { + let instruction = RefundProposalDepositCpi { + __program: self.instruction.__program, + + proposal_account: self + .instruction + .proposal_account + .expect("proposal_account is not set"), + + proposal_deposit_account: self + .instruction + .proposal_deposit_account + .expect("proposal_deposit_account is not set"), + + proposal_deposit_payer: self + .instruction + .proposal_deposit_payer + .expect("proposal_deposit_payer is not set"), + }; + instruction.invoke_signed_with_remaining_accounts( + signers_seeds, + &self.instruction.__remaining_accounts, + ) + } +} + +#[derive(Clone, Debug)] +struct RefundProposalDepositCpiBuilderInstruction<'a, 'b> { + __program: &'b solana_account_info::AccountInfo<'a>, + proposal_account: Option<&'b solana_account_info::AccountInfo<'a>>, + proposal_deposit_account: Option<&'b solana_account_info::AccountInfo<'a>>, + proposal_deposit_payer: Option<&'b solana_account_info::AccountInfo<'a>>, + /// Additional instruction accounts `(AccountInfo, is_writable, is_signer)`. + __remaining_accounts: Vec<(&'b solana_account_info::AccountInfo<'a>, bool, bool)>, +} diff --git a/e2e/governance/src/generated/instructions/relinquish_vote.rs b/e2e/governance/src/generated/instructions/relinquish_vote.rs new file mode 100644 index 0000000..8721fc5 --- /dev/null +++ b/e2e/governance/src/generated/instructions/relinquish_vote.rs @@ -0,0 +1,617 @@ +//! This code was AUTOGENERATED using the codama library. +//! Please DO NOT EDIT THIS FILE, instead use visitors +//! to add features, then rerun codama to update it. +//! +//! +//! + +use borsh::BorshDeserialize; +use borsh::BorshSerialize; + +pub const RELINQUISH_VOTE_DISCRIMINATOR: u8 = 15; + +/// Accounts. +#[derive(Debug)] +pub struct RelinquishVote { + pub realm_account: solana_pubkey::Pubkey, + + pub governance_account: solana_pubkey::Pubkey, + + pub proposal_account: solana_pubkey::Pubkey, + /// TokenOwnerRecord account. PDA seeds: ['governance',realm, vote_governing_token_mint, governing_token_owner] + pub token_owner_record: solana_pubkey::Pubkey, + /// Proposal VoteRecord account. PDA seeds: ['governance',proposal, token_owner_record] + pub proposal_vote_record: solana_pubkey::Pubkey, + /// The Governing Token Mint which was used to cast the vote (vote_governing_token_mint) + pub governing_token_mint: solana_pubkey::Pubkey, + + pub governance_authority: Option, + /// Optional Beneficiary account which would receive lamports when VoteRecord Account is disposed. + /// It's required only when Proposal is still being voted on + pub beneficiary_account: Option, +} + +impl RelinquishVote { + pub fn instruction(&self) -> solana_instruction::Instruction { + self.instruction_with_remaining_accounts(&[]) + } + #[allow(clippy::arithmetic_side_effects)] + #[allow(clippy::vec_init_then_push)] + pub fn instruction_with_remaining_accounts( + &self, + remaining_accounts: &[solana_instruction::AccountMeta], + ) -> solana_instruction::Instruction { + let mut accounts = Vec::with_capacity(8 + remaining_accounts.len()); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.realm_account, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.governance_account, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + self.proposal_account, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + self.token_owner_record, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + self.proposal_vote_record, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.governing_token_mint, + false, + )); + if let Some(governance_authority) = self.governance_authority { + accounts.push(solana_instruction::AccountMeta::new_readonly( + governance_authority, + true, + )); + } else { + accounts.push(solana_instruction::AccountMeta::new_readonly( + crate::SPL_GOVERNANCE_ID, + false, + )); + } + if let Some(beneficiary_account) = self.beneficiary_account { + accounts.push(solana_instruction::AccountMeta::new( + beneficiary_account, + false, + )); + } else { + accounts.push(solana_instruction::AccountMeta::new_readonly( + crate::SPL_GOVERNANCE_ID, + false, + )); + } + accounts.extend_from_slice(remaining_accounts); + let data = RelinquishVoteInstructionData::new().try_to_vec().unwrap(); + + solana_instruction::Instruction { + program_id: crate::SPL_GOVERNANCE_ID, + accounts, + data, + } + } +} + +#[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct RelinquishVoteInstructionData { + discriminator: u8, +} + +impl RelinquishVoteInstructionData { + pub fn new() -> Self { + Self { discriminator: 15 } + } + + pub(crate) fn try_to_vec(&self) -> Result, std::io::Error> { + borsh::to_vec(self) + } +} + +impl Default for RelinquishVoteInstructionData { + fn default() -> Self { + Self::new() + } +} + +/// Instruction builder for `RelinquishVote`. +/// +/// ### Accounts: +/// +/// 0. `[]` realm_account +/// 1. `[]` governance_account +/// 2. `[writable]` proposal_account +/// 3. `[writable]` token_owner_record +/// 4. `[writable]` proposal_vote_record +/// 5. `[]` governing_token_mint +/// 6. `[signer, optional]` governance_authority +/// 7. `[writable, optional]` beneficiary_account +#[derive(Clone, Debug, Default)] +pub struct RelinquishVoteBuilder { + realm_account: Option, + governance_account: Option, + proposal_account: Option, + token_owner_record: Option, + proposal_vote_record: Option, + governing_token_mint: Option, + governance_authority: Option, + beneficiary_account: Option, + __remaining_accounts: Vec, +} + +impl RelinquishVoteBuilder { + pub fn new() -> Self { + Self::default() + } + #[inline(always)] + pub fn realm_account(&mut self, realm_account: solana_pubkey::Pubkey) -> &mut Self { + self.realm_account = Some(realm_account); + self + } + #[inline(always)] + pub fn governance_account(&mut self, governance_account: solana_pubkey::Pubkey) -> &mut Self { + self.governance_account = Some(governance_account); + self + } + #[inline(always)] + pub fn proposal_account(&mut self, proposal_account: solana_pubkey::Pubkey) -> &mut Self { + self.proposal_account = Some(proposal_account); + self + } + /// TokenOwnerRecord account. PDA seeds: ['governance',realm, vote_governing_token_mint, governing_token_owner] + #[inline(always)] + pub fn token_owner_record(&mut self, token_owner_record: solana_pubkey::Pubkey) -> &mut Self { + self.token_owner_record = Some(token_owner_record); + self + } + /// Proposal VoteRecord account. PDA seeds: ['governance',proposal, token_owner_record] + #[inline(always)] + pub fn proposal_vote_record( + &mut self, + proposal_vote_record: solana_pubkey::Pubkey, + ) -> &mut Self { + self.proposal_vote_record = Some(proposal_vote_record); + self + } + /// The Governing Token Mint which was used to cast the vote (vote_governing_token_mint) + #[inline(always)] + pub fn governing_token_mint( + &mut self, + governing_token_mint: solana_pubkey::Pubkey, + ) -> &mut Self { + self.governing_token_mint = Some(governing_token_mint); + self + } + /// `[optional account]` + #[inline(always)] + pub fn governance_authority( + &mut self, + governance_authority: Option, + ) -> &mut Self { + self.governance_authority = governance_authority; + self + } + /// `[optional account]` + /// Optional Beneficiary account which would receive lamports when VoteRecord Account is disposed. + /// It's required only when Proposal is still being voted on + #[inline(always)] + pub fn beneficiary_account( + &mut self, + beneficiary_account: Option, + ) -> &mut Self { + self.beneficiary_account = beneficiary_account; + self + } + /// Add an additional account to the instruction. + #[inline(always)] + pub fn add_remaining_account(&mut self, account: solana_instruction::AccountMeta) -> &mut Self { + self.__remaining_accounts.push(account); + self + } + /// Add additional accounts to the instruction. + #[inline(always)] + pub fn add_remaining_accounts( + &mut self, + accounts: &[solana_instruction::AccountMeta], + ) -> &mut Self { + self.__remaining_accounts.extend_from_slice(accounts); + self + } + #[allow(clippy::clone_on_copy)] + pub fn instruction(&self) -> solana_instruction::Instruction { + let accounts = RelinquishVote { + realm_account: self.realm_account.expect("realm_account is not set"), + governance_account: self + .governance_account + .expect("governance_account is not set"), + proposal_account: self.proposal_account.expect("proposal_account is not set"), + token_owner_record: self + .token_owner_record + .expect("token_owner_record is not set"), + proposal_vote_record: self + .proposal_vote_record + .expect("proposal_vote_record is not set"), + governing_token_mint: self + .governing_token_mint + .expect("governing_token_mint is not set"), + governance_authority: self.governance_authority, + beneficiary_account: self.beneficiary_account, + }; + + accounts.instruction_with_remaining_accounts(&self.__remaining_accounts) + } +} + +/// `relinquish_vote` CPI accounts. +pub struct RelinquishVoteCpiAccounts<'a, 'b> { + pub realm_account: &'b solana_account_info::AccountInfo<'a>, + + pub governance_account: &'b solana_account_info::AccountInfo<'a>, + + pub proposal_account: &'b solana_account_info::AccountInfo<'a>, + /// TokenOwnerRecord account. PDA seeds: ['governance',realm, vote_governing_token_mint, governing_token_owner] + pub token_owner_record: &'b solana_account_info::AccountInfo<'a>, + /// Proposal VoteRecord account. PDA seeds: ['governance',proposal, token_owner_record] + pub proposal_vote_record: &'b solana_account_info::AccountInfo<'a>, + /// The Governing Token Mint which was used to cast the vote (vote_governing_token_mint) + pub governing_token_mint: &'b solana_account_info::AccountInfo<'a>, + + pub governance_authority: Option<&'b solana_account_info::AccountInfo<'a>>, + /// Optional Beneficiary account which would receive lamports when VoteRecord Account is disposed. + /// It's required only when Proposal is still being voted on + pub beneficiary_account: Option<&'b solana_account_info::AccountInfo<'a>>, +} + +/// `relinquish_vote` CPI instruction. +pub struct RelinquishVoteCpi<'a, 'b> { + /// The program to invoke. + pub __program: &'b solana_account_info::AccountInfo<'a>, + + pub realm_account: &'b solana_account_info::AccountInfo<'a>, + + pub governance_account: &'b solana_account_info::AccountInfo<'a>, + + pub proposal_account: &'b solana_account_info::AccountInfo<'a>, + /// TokenOwnerRecord account. PDA seeds: ['governance',realm, vote_governing_token_mint, governing_token_owner] + pub token_owner_record: &'b solana_account_info::AccountInfo<'a>, + /// Proposal VoteRecord account. PDA seeds: ['governance',proposal, token_owner_record] + pub proposal_vote_record: &'b solana_account_info::AccountInfo<'a>, + /// The Governing Token Mint which was used to cast the vote (vote_governing_token_mint) + pub governing_token_mint: &'b solana_account_info::AccountInfo<'a>, + + pub governance_authority: Option<&'b solana_account_info::AccountInfo<'a>>, + /// Optional Beneficiary account which would receive lamports when VoteRecord Account is disposed. + /// It's required only when Proposal is still being voted on + pub beneficiary_account: Option<&'b solana_account_info::AccountInfo<'a>>, +} + +impl<'a, 'b> RelinquishVoteCpi<'a, 'b> { + pub fn new( + program: &'b solana_account_info::AccountInfo<'a>, + accounts: RelinquishVoteCpiAccounts<'a, 'b>, + ) -> Self { + Self { + __program: program, + realm_account: accounts.realm_account, + governance_account: accounts.governance_account, + proposal_account: accounts.proposal_account, + token_owner_record: accounts.token_owner_record, + proposal_vote_record: accounts.proposal_vote_record, + governing_token_mint: accounts.governing_token_mint, + governance_authority: accounts.governance_authority, + beneficiary_account: accounts.beneficiary_account, + } + } + #[inline(always)] + pub fn invoke(&self) -> solana_program_error::ProgramResult { + self.invoke_signed_with_remaining_accounts(&[], &[]) + } + #[inline(always)] + pub fn invoke_with_remaining_accounts( + &self, + remaining_accounts: &[(&'b solana_account_info::AccountInfo<'a>, bool, bool)], + ) -> solana_program_error::ProgramResult { + self.invoke_signed_with_remaining_accounts(&[], remaining_accounts) + } + #[inline(always)] + pub fn invoke_signed(&self, signers_seeds: &[&[&[u8]]]) -> solana_program_error::ProgramResult { + self.invoke_signed_with_remaining_accounts(signers_seeds, &[]) + } + #[allow(clippy::arithmetic_side_effects)] + #[allow(clippy::clone_on_copy)] + #[allow(clippy::vec_init_then_push)] + pub fn invoke_signed_with_remaining_accounts( + &self, + signers_seeds: &[&[&[u8]]], + remaining_accounts: &[(&'b solana_account_info::AccountInfo<'a>, bool, bool)], + ) -> solana_program_error::ProgramResult { + let mut accounts = Vec::with_capacity(8 + remaining_accounts.len()); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.realm_account.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.governance_account.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + *self.proposal_account.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + *self.token_owner_record.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + *self.proposal_vote_record.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.governing_token_mint.key, + false, + )); + if let Some(governance_authority) = self.governance_authority { + accounts.push(solana_instruction::AccountMeta::new_readonly( + *governance_authority.key, + true, + )); + } else { + accounts.push(solana_instruction::AccountMeta::new_readonly( + crate::SPL_GOVERNANCE_ID, + false, + )); + } + if let Some(beneficiary_account) = self.beneficiary_account { + accounts.push(solana_instruction::AccountMeta::new( + *beneficiary_account.key, + false, + )); + } else { + accounts.push(solana_instruction::AccountMeta::new_readonly( + crate::SPL_GOVERNANCE_ID, + false, + )); + } + remaining_accounts.iter().for_each(|remaining_account| { + accounts.push(solana_instruction::AccountMeta { + pubkey: *remaining_account.0.key, + is_signer: remaining_account.1, + is_writable: remaining_account.2, + }) + }); + let data = RelinquishVoteInstructionData::new().try_to_vec().unwrap(); + + let instruction = solana_instruction::Instruction { + program_id: crate::SPL_GOVERNANCE_ID, + accounts, + data, + }; + let mut account_infos = Vec::with_capacity(9 + remaining_accounts.len()); + account_infos.push(self.__program.clone()); + account_infos.push(self.realm_account.clone()); + account_infos.push(self.governance_account.clone()); + account_infos.push(self.proposal_account.clone()); + account_infos.push(self.token_owner_record.clone()); + account_infos.push(self.proposal_vote_record.clone()); + account_infos.push(self.governing_token_mint.clone()); + if let Some(governance_authority) = self.governance_authority { + account_infos.push(governance_authority.clone()); + } + if let Some(beneficiary_account) = self.beneficiary_account { + account_infos.push(beneficiary_account.clone()); + } + remaining_accounts + .iter() + .for_each(|remaining_account| account_infos.push(remaining_account.0.clone())); + + if signers_seeds.is_empty() { + solana_cpi::invoke(&instruction, &account_infos) + } else { + solana_cpi::invoke_signed(&instruction, &account_infos, signers_seeds) + } + } +} + +/// Instruction builder for `RelinquishVote` via CPI. +/// +/// ### Accounts: +/// +/// 0. `[]` realm_account +/// 1. `[]` governance_account +/// 2. `[writable]` proposal_account +/// 3. `[writable]` token_owner_record +/// 4. `[writable]` proposal_vote_record +/// 5. `[]` governing_token_mint +/// 6. `[signer, optional]` governance_authority +/// 7. `[writable, optional]` beneficiary_account +#[derive(Clone, Debug)] +pub struct RelinquishVoteCpiBuilder<'a, 'b> { + instruction: Box>, +} + +impl<'a, 'b> RelinquishVoteCpiBuilder<'a, 'b> { + pub fn new(program: &'b solana_account_info::AccountInfo<'a>) -> Self { + let instruction = Box::new(RelinquishVoteCpiBuilderInstruction { + __program: program, + realm_account: None, + governance_account: None, + proposal_account: None, + token_owner_record: None, + proposal_vote_record: None, + governing_token_mint: None, + governance_authority: None, + beneficiary_account: None, + __remaining_accounts: Vec::new(), + }); + Self { instruction } + } + #[inline(always)] + pub fn realm_account( + &mut self, + realm_account: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.realm_account = Some(realm_account); + self + } + #[inline(always)] + pub fn governance_account( + &mut self, + governance_account: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.governance_account = Some(governance_account); + self + } + #[inline(always)] + pub fn proposal_account( + &mut self, + proposal_account: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.proposal_account = Some(proposal_account); + self + } + /// TokenOwnerRecord account. PDA seeds: ['governance',realm, vote_governing_token_mint, governing_token_owner] + #[inline(always)] + pub fn token_owner_record( + &mut self, + token_owner_record: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.token_owner_record = Some(token_owner_record); + self + } + /// Proposal VoteRecord account. PDA seeds: ['governance',proposal, token_owner_record] + #[inline(always)] + pub fn proposal_vote_record( + &mut self, + proposal_vote_record: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.proposal_vote_record = Some(proposal_vote_record); + self + } + /// The Governing Token Mint which was used to cast the vote (vote_governing_token_mint) + #[inline(always)] + pub fn governing_token_mint( + &mut self, + governing_token_mint: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.governing_token_mint = Some(governing_token_mint); + self + } + /// `[optional account]` + #[inline(always)] + pub fn governance_authority( + &mut self, + governance_authority: Option<&'b solana_account_info::AccountInfo<'a>>, + ) -> &mut Self { + self.instruction.governance_authority = governance_authority; + self + } + /// `[optional account]` + /// Optional Beneficiary account which would receive lamports when VoteRecord Account is disposed. + /// It's required only when Proposal is still being voted on + #[inline(always)] + pub fn beneficiary_account( + &mut self, + beneficiary_account: Option<&'b solana_account_info::AccountInfo<'a>>, + ) -> &mut Self { + self.instruction.beneficiary_account = beneficiary_account; + self + } + /// Add an additional account to the instruction. + #[inline(always)] + pub fn add_remaining_account( + &mut self, + account: &'b solana_account_info::AccountInfo<'a>, + is_writable: bool, + is_signer: bool, + ) -> &mut Self { + self.instruction + .__remaining_accounts + .push((account, is_writable, is_signer)); + self + } + /// Add additional accounts to the instruction. + /// + /// Each account is represented by a tuple of the `AccountInfo`, a `bool` indicating whether the account is writable or not, + /// and a `bool` indicating whether the account is a signer or not. + #[inline(always)] + pub fn add_remaining_accounts( + &mut self, + accounts: &[(&'b solana_account_info::AccountInfo<'a>, bool, bool)], + ) -> &mut Self { + self.instruction + .__remaining_accounts + .extend_from_slice(accounts); + self + } + #[inline(always)] + pub fn invoke(&self) -> solana_program_error::ProgramResult { + self.invoke_signed(&[]) + } + #[allow(clippy::clone_on_copy)] + #[allow(clippy::vec_init_then_push)] + pub fn invoke_signed(&self, signers_seeds: &[&[&[u8]]]) -> solana_program_error::ProgramResult { + let instruction = RelinquishVoteCpi { + __program: self.instruction.__program, + + realm_account: self + .instruction + .realm_account + .expect("realm_account is not set"), + + governance_account: self + .instruction + .governance_account + .expect("governance_account is not set"), + + proposal_account: self + .instruction + .proposal_account + .expect("proposal_account is not set"), + + token_owner_record: self + .instruction + .token_owner_record + .expect("token_owner_record is not set"), + + proposal_vote_record: self + .instruction + .proposal_vote_record + .expect("proposal_vote_record is not set"), + + governing_token_mint: self + .instruction + .governing_token_mint + .expect("governing_token_mint is not set"), + + governance_authority: self.instruction.governance_authority, + + beneficiary_account: self.instruction.beneficiary_account, + }; + instruction.invoke_signed_with_remaining_accounts( + signers_seeds, + &self.instruction.__remaining_accounts, + ) + } +} + +#[derive(Clone, Debug)] +struct RelinquishVoteCpiBuilderInstruction<'a, 'b> { + __program: &'b solana_account_info::AccountInfo<'a>, + realm_account: Option<&'b solana_account_info::AccountInfo<'a>>, + governance_account: Option<&'b solana_account_info::AccountInfo<'a>>, + proposal_account: Option<&'b solana_account_info::AccountInfo<'a>>, + token_owner_record: Option<&'b solana_account_info::AccountInfo<'a>>, + proposal_vote_record: Option<&'b solana_account_info::AccountInfo<'a>>, + governing_token_mint: Option<&'b solana_account_info::AccountInfo<'a>>, + governance_authority: Option<&'b solana_account_info::AccountInfo<'a>>, + beneficiary_account: Option<&'b solana_account_info::AccountInfo<'a>>, + /// Additional instruction accounts `(AccountInfo, is_writable, is_signer)`. + __remaining_accounts: Vec<(&'b solana_account_info::AccountInfo<'a>, bool, bool)>, +} diff --git a/e2e/governance/src/generated/instructions/remove_required_signatory.rs b/e2e/governance/src/generated/instructions/remove_required_signatory.rs new file mode 100644 index 0000000..8b8367d --- /dev/null +++ b/e2e/governance/src/generated/instructions/remove_required_signatory.rs @@ -0,0 +1,369 @@ +//! This code was AUTOGENERATED using the codama library. +//! Please DO NOT EDIT THIS FILE, instead use visitors +//! to add features, then rerun codama to update it. +//! +//! +//! + +use borsh::BorshDeserialize; +use borsh::BorshSerialize; + +pub const REMOVE_REQUIRED_SIGNATORY_DISCRIMINATOR: u8 = 30; + +/// Accounts. +#[derive(Debug)] +pub struct RemoveRequiredSignatory { + pub governance_account: solana_pubkey::Pubkey, + + pub required_signatory_account: solana_pubkey::Pubkey, + /// Beneficiary Account which would receive lamports from the disposed RequiredSignatory Account + pub beneficiary_account: solana_pubkey::Pubkey, +} + +impl RemoveRequiredSignatory { + pub fn instruction(&self) -> solana_instruction::Instruction { + self.instruction_with_remaining_accounts(&[]) + } + #[allow(clippy::arithmetic_side_effects)] + #[allow(clippy::vec_init_then_push)] + pub fn instruction_with_remaining_accounts( + &self, + remaining_accounts: &[solana_instruction::AccountMeta], + ) -> solana_instruction::Instruction { + let mut accounts = Vec::with_capacity(3 + remaining_accounts.len()); + accounts.push(solana_instruction::AccountMeta::new( + self.governance_account, + true, + )); + accounts.push(solana_instruction::AccountMeta::new( + self.required_signatory_account, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + self.beneficiary_account, + false, + )); + accounts.extend_from_slice(remaining_accounts); + let data = RemoveRequiredSignatoryInstructionData::new() + .try_to_vec() + .unwrap(); + + solana_instruction::Instruction { + program_id: crate::SPL_GOVERNANCE_ID, + accounts, + data, + } + } +} + +#[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct RemoveRequiredSignatoryInstructionData { + discriminator: u8, +} + +impl RemoveRequiredSignatoryInstructionData { + pub fn new() -> Self { + Self { discriminator: 30 } + } + + pub(crate) fn try_to_vec(&self) -> Result, std::io::Error> { + borsh::to_vec(self) + } +} + +impl Default for RemoveRequiredSignatoryInstructionData { + fn default() -> Self { + Self::new() + } +} + +/// Instruction builder for `RemoveRequiredSignatory`. +/// +/// ### Accounts: +/// +/// 0. `[writable, signer]` governance_account +/// 1. `[writable]` required_signatory_account +/// 2. `[writable]` beneficiary_account +#[derive(Clone, Debug, Default)] +pub struct RemoveRequiredSignatoryBuilder { + governance_account: Option, + required_signatory_account: Option, + beneficiary_account: Option, + __remaining_accounts: Vec, +} + +impl RemoveRequiredSignatoryBuilder { + pub fn new() -> Self { + Self::default() + } + #[inline(always)] + pub fn governance_account(&mut self, governance_account: solana_pubkey::Pubkey) -> &mut Self { + self.governance_account = Some(governance_account); + self + } + #[inline(always)] + pub fn required_signatory_account( + &mut self, + required_signatory_account: solana_pubkey::Pubkey, + ) -> &mut Self { + self.required_signatory_account = Some(required_signatory_account); + self + } + /// Beneficiary Account which would receive lamports from the disposed RequiredSignatory Account + #[inline(always)] + pub fn beneficiary_account(&mut self, beneficiary_account: solana_pubkey::Pubkey) -> &mut Self { + self.beneficiary_account = Some(beneficiary_account); + self + } + /// Add an additional account to the instruction. + #[inline(always)] + pub fn add_remaining_account(&mut self, account: solana_instruction::AccountMeta) -> &mut Self { + self.__remaining_accounts.push(account); + self + } + /// Add additional accounts to the instruction. + #[inline(always)] + pub fn add_remaining_accounts( + &mut self, + accounts: &[solana_instruction::AccountMeta], + ) -> &mut Self { + self.__remaining_accounts.extend_from_slice(accounts); + self + } + #[allow(clippy::clone_on_copy)] + pub fn instruction(&self) -> solana_instruction::Instruction { + let accounts = RemoveRequiredSignatory { + governance_account: self + .governance_account + .expect("governance_account is not set"), + required_signatory_account: self + .required_signatory_account + .expect("required_signatory_account is not set"), + beneficiary_account: self + .beneficiary_account + .expect("beneficiary_account is not set"), + }; + + accounts.instruction_with_remaining_accounts(&self.__remaining_accounts) + } +} + +/// `remove_required_signatory` CPI accounts. +pub struct RemoveRequiredSignatoryCpiAccounts<'a, 'b> { + pub governance_account: &'b solana_account_info::AccountInfo<'a>, + + pub required_signatory_account: &'b solana_account_info::AccountInfo<'a>, + /// Beneficiary Account which would receive lamports from the disposed RequiredSignatory Account + pub beneficiary_account: &'b solana_account_info::AccountInfo<'a>, +} + +/// `remove_required_signatory` CPI instruction. +pub struct RemoveRequiredSignatoryCpi<'a, 'b> { + /// The program to invoke. + pub __program: &'b solana_account_info::AccountInfo<'a>, + + pub governance_account: &'b solana_account_info::AccountInfo<'a>, + + pub required_signatory_account: &'b solana_account_info::AccountInfo<'a>, + /// Beneficiary Account which would receive lamports from the disposed RequiredSignatory Account + pub beneficiary_account: &'b solana_account_info::AccountInfo<'a>, +} + +impl<'a, 'b> RemoveRequiredSignatoryCpi<'a, 'b> { + pub fn new( + program: &'b solana_account_info::AccountInfo<'a>, + accounts: RemoveRequiredSignatoryCpiAccounts<'a, 'b>, + ) -> Self { + Self { + __program: program, + governance_account: accounts.governance_account, + required_signatory_account: accounts.required_signatory_account, + beneficiary_account: accounts.beneficiary_account, + } + } + #[inline(always)] + pub fn invoke(&self) -> solana_program_error::ProgramResult { + self.invoke_signed_with_remaining_accounts(&[], &[]) + } + #[inline(always)] + pub fn invoke_with_remaining_accounts( + &self, + remaining_accounts: &[(&'b solana_account_info::AccountInfo<'a>, bool, bool)], + ) -> solana_program_error::ProgramResult { + self.invoke_signed_with_remaining_accounts(&[], remaining_accounts) + } + #[inline(always)] + pub fn invoke_signed(&self, signers_seeds: &[&[&[u8]]]) -> solana_program_error::ProgramResult { + self.invoke_signed_with_remaining_accounts(signers_seeds, &[]) + } + #[allow(clippy::arithmetic_side_effects)] + #[allow(clippy::clone_on_copy)] + #[allow(clippy::vec_init_then_push)] + pub fn invoke_signed_with_remaining_accounts( + &self, + signers_seeds: &[&[&[u8]]], + remaining_accounts: &[(&'b solana_account_info::AccountInfo<'a>, bool, bool)], + ) -> solana_program_error::ProgramResult { + let mut accounts = Vec::with_capacity(3 + remaining_accounts.len()); + accounts.push(solana_instruction::AccountMeta::new( + *self.governance_account.key, + true, + )); + accounts.push(solana_instruction::AccountMeta::new( + *self.required_signatory_account.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + *self.beneficiary_account.key, + false, + )); + remaining_accounts.iter().for_each(|remaining_account| { + accounts.push(solana_instruction::AccountMeta { + pubkey: *remaining_account.0.key, + is_signer: remaining_account.1, + is_writable: remaining_account.2, + }) + }); + let data = RemoveRequiredSignatoryInstructionData::new() + .try_to_vec() + .unwrap(); + + let instruction = solana_instruction::Instruction { + program_id: crate::SPL_GOVERNANCE_ID, + accounts, + data, + }; + let mut account_infos = Vec::with_capacity(4 + remaining_accounts.len()); + account_infos.push(self.__program.clone()); + account_infos.push(self.governance_account.clone()); + account_infos.push(self.required_signatory_account.clone()); + account_infos.push(self.beneficiary_account.clone()); + remaining_accounts + .iter() + .for_each(|remaining_account| account_infos.push(remaining_account.0.clone())); + + if signers_seeds.is_empty() { + solana_cpi::invoke(&instruction, &account_infos) + } else { + solana_cpi::invoke_signed(&instruction, &account_infos, signers_seeds) + } + } +} + +/// Instruction builder for `RemoveRequiredSignatory` via CPI. +/// +/// ### Accounts: +/// +/// 0. `[writable, signer]` governance_account +/// 1. `[writable]` required_signatory_account +/// 2. `[writable]` beneficiary_account +#[derive(Clone, Debug)] +pub struct RemoveRequiredSignatoryCpiBuilder<'a, 'b> { + instruction: Box>, +} + +impl<'a, 'b> RemoveRequiredSignatoryCpiBuilder<'a, 'b> { + pub fn new(program: &'b solana_account_info::AccountInfo<'a>) -> Self { + let instruction = Box::new(RemoveRequiredSignatoryCpiBuilderInstruction { + __program: program, + governance_account: None, + required_signatory_account: None, + beneficiary_account: None, + __remaining_accounts: Vec::new(), + }); + Self { instruction } + } + #[inline(always)] + pub fn governance_account( + &mut self, + governance_account: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.governance_account = Some(governance_account); + self + } + #[inline(always)] + pub fn required_signatory_account( + &mut self, + required_signatory_account: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.required_signatory_account = Some(required_signatory_account); + self + } + /// Beneficiary Account which would receive lamports from the disposed RequiredSignatory Account + #[inline(always)] + pub fn beneficiary_account( + &mut self, + beneficiary_account: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.beneficiary_account = Some(beneficiary_account); + self + } + /// Add an additional account to the instruction. + #[inline(always)] + pub fn add_remaining_account( + &mut self, + account: &'b solana_account_info::AccountInfo<'a>, + is_writable: bool, + is_signer: bool, + ) -> &mut Self { + self.instruction + .__remaining_accounts + .push((account, is_writable, is_signer)); + self + } + /// Add additional accounts to the instruction. + /// + /// Each account is represented by a tuple of the `AccountInfo`, a `bool` indicating whether the account is writable or not, + /// and a `bool` indicating whether the account is a signer or not. + #[inline(always)] + pub fn add_remaining_accounts( + &mut self, + accounts: &[(&'b solana_account_info::AccountInfo<'a>, bool, bool)], + ) -> &mut Self { + self.instruction + .__remaining_accounts + .extend_from_slice(accounts); + self + } + #[inline(always)] + pub fn invoke(&self) -> solana_program_error::ProgramResult { + self.invoke_signed(&[]) + } + #[allow(clippy::clone_on_copy)] + #[allow(clippy::vec_init_then_push)] + pub fn invoke_signed(&self, signers_seeds: &[&[&[u8]]]) -> solana_program_error::ProgramResult { + let instruction = RemoveRequiredSignatoryCpi { + __program: self.instruction.__program, + + governance_account: self + .instruction + .governance_account + .expect("governance_account is not set"), + + required_signatory_account: self + .instruction + .required_signatory_account + .expect("required_signatory_account is not set"), + + beneficiary_account: self + .instruction + .beneficiary_account + .expect("beneficiary_account is not set"), + }; + instruction.invoke_signed_with_remaining_accounts( + signers_seeds, + &self.instruction.__remaining_accounts, + ) + } +} + +#[derive(Clone, Debug)] +struct RemoveRequiredSignatoryCpiBuilderInstruction<'a, 'b> { + __program: &'b solana_account_info::AccountInfo<'a>, + governance_account: Option<&'b solana_account_info::AccountInfo<'a>>, + required_signatory_account: Option<&'b solana_account_info::AccountInfo<'a>>, + beneficiary_account: Option<&'b solana_account_info::AccountInfo<'a>>, + /// Additional instruction accounts `(AccountInfo, is_writable, is_signer)`. + __remaining_accounts: Vec<(&'b solana_account_info::AccountInfo<'a>, bool, bool)>, +} diff --git a/e2e/governance/src/generated/instructions/remove_transaction.rs b/e2e/governance/src/generated/instructions/remove_transaction.rs new file mode 100644 index 0000000..7188295 --- /dev/null +++ b/e2e/governance/src/generated/instructions/remove_transaction.rs @@ -0,0 +1,458 @@ +//! This code was AUTOGENERATED using the codama library. +//! Please DO NOT EDIT THIS FILE, instead use visitors +//! to add features, then rerun codama to update it. +//! +//! +//! + +use borsh::BorshDeserialize; +use borsh::BorshSerialize; + +pub const REMOVE_TRANSACTION_DISCRIMINATOR: u8 = 10; + +/// Accounts. +#[derive(Debug)] +pub struct RemoveTransaction { + pub proposal_account: solana_pubkey::Pubkey, + /// TokenOwnerRecord account of the Proposal owner + pub token_owner_record: solana_pubkey::Pubkey, + /// Governance Authority (Token Owner or Governance Delegate) + pub governance_authority: solana_pubkey::Pubkey, + + pub proposal_transaction_account: solana_pubkey::Pubkey, + /// Beneficiary Account which would receive lamports from the disposed ProposalTransaction account + pub beneficiary_account: solana_pubkey::Pubkey, +} + +impl RemoveTransaction { + pub fn instruction(&self) -> solana_instruction::Instruction { + self.instruction_with_remaining_accounts(&[]) + } + #[allow(clippy::arithmetic_side_effects)] + #[allow(clippy::vec_init_then_push)] + pub fn instruction_with_remaining_accounts( + &self, + remaining_accounts: &[solana_instruction::AccountMeta], + ) -> solana_instruction::Instruction { + let mut accounts = Vec::with_capacity(5 + remaining_accounts.len()); + accounts.push(solana_instruction::AccountMeta::new( + self.proposal_account, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.token_owner_record, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.governance_authority, + true, + )); + accounts.push(solana_instruction::AccountMeta::new( + self.proposal_transaction_account, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + self.beneficiary_account, + false, + )); + accounts.extend_from_slice(remaining_accounts); + let data = RemoveTransactionInstructionData::new() + .try_to_vec() + .unwrap(); + + solana_instruction::Instruction { + program_id: crate::SPL_GOVERNANCE_ID, + accounts, + data, + } + } +} + +#[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct RemoveTransactionInstructionData { + discriminator: u8, +} + +impl RemoveTransactionInstructionData { + pub fn new() -> Self { + Self { discriminator: 10 } + } + + pub(crate) fn try_to_vec(&self) -> Result, std::io::Error> { + borsh::to_vec(self) + } +} + +impl Default for RemoveTransactionInstructionData { + fn default() -> Self { + Self::new() + } +} + +/// Instruction builder for `RemoveTransaction`. +/// +/// ### Accounts: +/// +/// 0. `[writable]` proposal_account +/// 1. `[]` token_owner_record +/// 2. `[signer]` governance_authority +/// 3. `[writable]` proposal_transaction_account +/// 4. `[writable]` beneficiary_account +#[derive(Clone, Debug, Default)] +pub struct RemoveTransactionBuilder { + proposal_account: Option, + token_owner_record: Option, + governance_authority: Option, + proposal_transaction_account: Option, + beneficiary_account: Option, + __remaining_accounts: Vec, +} + +impl RemoveTransactionBuilder { + pub fn new() -> Self { + Self::default() + } + #[inline(always)] + pub fn proposal_account(&mut self, proposal_account: solana_pubkey::Pubkey) -> &mut Self { + self.proposal_account = Some(proposal_account); + self + } + /// TokenOwnerRecord account of the Proposal owner + #[inline(always)] + pub fn token_owner_record(&mut self, token_owner_record: solana_pubkey::Pubkey) -> &mut Self { + self.token_owner_record = Some(token_owner_record); + self + } + /// Governance Authority (Token Owner or Governance Delegate) + #[inline(always)] + pub fn governance_authority( + &mut self, + governance_authority: solana_pubkey::Pubkey, + ) -> &mut Self { + self.governance_authority = Some(governance_authority); + self + } + #[inline(always)] + pub fn proposal_transaction_account( + &mut self, + proposal_transaction_account: solana_pubkey::Pubkey, + ) -> &mut Self { + self.proposal_transaction_account = Some(proposal_transaction_account); + self + } + /// Beneficiary Account which would receive lamports from the disposed ProposalTransaction account + #[inline(always)] + pub fn beneficiary_account(&mut self, beneficiary_account: solana_pubkey::Pubkey) -> &mut Self { + self.beneficiary_account = Some(beneficiary_account); + self + } + /// Add an additional account to the instruction. + #[inline(always)] + pub fn add_remaining_account(&mut self, account: solana_instruction::AccountMeta) -> &mut Self { + self.__remaining_accounts.push(account); + self + } + /// Add additional accounts to the instruction. + #[inline(always)] + pub fn add_remaining_accounts( + &mut self, + accounts: &[solana_instruction::AccountMeta], + ) -> &mut Self { + self.__remaining_accounts.extend_from_slice(accounts); + self + } + #[allow(clippy::clone_on_copy)] + pub fn instruction(&self) -> solana_instruction::Instruction { + let accounts = RemoveTransaction { + proposal_account: self.proposal_account.expect("proposal_account is not set"), + token_owner_record: self + .token_owner_record + .expect("token_owner_record is not set"), + governance_authority: self + .governance_authority + .expect("governance_authority is not set"), + proposal_transaction_account: self + .proposal_transaction_account + .expect("proposal_transaction_account is not set"), + beneficiary_account: self + .beneficiary_account + .expect("beneficiary_account is not set"), + }; + + accounts.instruction_with_remaining_accounts(&self.__remaining_accounts) + } +} + +/// `remove_transaction` CPI accounts. +pub struct RemoveTransactionCpiAccounts<'a, 'b> { + pub proposal_account: &'b solana_account_info::AccountInfo<'a>, + /// TokenOwnerRecord account of the Proposal owner + pub token_owner_record: &'b solana_account_info::AccountInfo<'a>, + /// Governance Authority (Token Owner or Governance Delegate) + pub governance_authority: &'b solana_account_info::AccountInfo<'a>, + + pub proposal_transaction_account: &'b solana_account_info::AccountInfo<'a>, + /// Beneficiary Account which would receive lamports from the disposed ProposalTransaction account + pub beneficiary_account: &'b solana_account_info::AccountInfo<'a>, +} + +/// `remove_transaction` CPI instruction. +pub struct RemoveTransactionCpi<'a, 'b> { + /// The program to invoke. + pub __program: &'b solana_account_info::AccountInfo<'a>, + + pub proposal_account: &'b solana_account_info::AccountInfo<'a>, + /// TokenOwnerRecord account of the Proposal owner + pub token_owner_record: &'b solana_account_info::AccountInfo<'a>, + /// Governance Authority (Token Owner or Governance Delegate) + pub governance_authority: &'b solana_account_info::AccountInfo<'a>, + + pub proposal_transaction_account: &'b solana_account_info::AccountInfo<'a>, + /// Beneficiary Account which would receive lamports from the disposed ProposalTransaction account + pub beneficiary_account: &'b solana_account_info::AccountInfo<'a>, +} + +impl<'a, 'b> RemoveTransactionCpi<'a, 'b> { + pub fn new( + program: &'b solana_account_info::AccountInfo<'a>, + accounts: RemoveTransactionCpiAccounts<'a, 'b>, + ) -> Self { + Self { + __program: program, + proposal_account: accounts.proposal_account, + token_owner_record: accounts.token_owner_record, + governance_authority: accounts.governance_authority, + proposal_transaction_account: accounts.proposal_transaction_account, + beneficiary_account: accounts.beneficiary_account, + } + } + #[inline(always)] + pub fn invoke(&self) -> solana_program_error::ProgramResult { + self.invoke_signed_with_remaining_accounts(&[], &[]) + } + #[inline(always)] + pub fn invoke_with_remaining_accounts( + &self, + remaining_accounts: &[(&'b solana_account_info::AccountInfo<'a>, bool, bool)], + ) -> solana_program_error::ProgramResult { + self.invoke_signed_with_remaining_accounts(&[], remaining_accounts) + } + #[inline(always)] + pub fn invoke_signed(&self, signers_seeds: &[&[&[u8]]]) -> solana_program_error::ProgramResult { + self.invoke_signed_with_remaining_accounts(signers_seeds, &[]) + } + #[allow(clippy::arithmetic_side_effects)] + #[allow(clippy::clone_on_copy)] + #[allow(clippy::vec_init_then_push)] + pub fn invoke_signed_with_remaining_accounts( + &self, + signers_seeds: &[&[&[u8]]], + remaining_accounts: &[(&'b solana_account_info::AccountInfo<'a>, bool, bool)], + ) -> solana_program_error::ProgramResult { + let mut accounts = Vec::with_capacity(5 + remaining_accounts.len()); + accounts.push(solana_instruction::AccountMeta::new( + *self.proposal_account.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.token_owner_record.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.governance_authority.key, + true, + )); + accounts.push(solana_instruction::AccountMeta::new( + *self.proposal_transaction_account.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + *self.beneficiary_account.key, + false, + )); + remaining_accounts.iter().for_each(|remaining_account| { + accounts.push(solana_instruction::AccountMeta { + pubkey: *remaining_account.0.key, + is_signer: remaining_account.1, + is_writable: remaining_account.2, + }) + }); + let data = RemoveTransactionInstructionData::new() + .try_to_vec() + .unwrap(); + + let instruction = solana_instruction::Instruction { + program_id: crate::SPL_GOVERNANCE_ID, + accounts, + data, + }; + let mut account_infos = Vec::with_capacity(6 + remaining_accounts.len()); + account_infos.push(self.__program.clone()); + account_infos.push(self.proposal_account.clone()); + account_infos.push(self.token_owner_record.clone()); + account_infos.push(self.governance_authority.clone()); + account_infos.push(self.proposal_transaction_account.clone()); + account_infos.push(self.beneficiary_account.clone()); + remaining_accounts + .iter() + .for_each(|remaining_account| account_infos.push(remaining_account.0.clone())); + + if signers_seeds.is_empty() { + solana_cpi::invoke(&instruction, &account_infos) + } else { + solana_cpi::invoke_signed(&instruction, &account_infos, signers_seeds) + } + } +} + +/// Instruction builder for `RemoveTransaction` via CPI. +/// +/// ### Accounts: +/// +/// 0. `[writable]` proposal_account +/// 1. `[]` token_owner_record +/// 2. `[signer]` governance_authority +/// 3. `[writable]` proposal_transaction_account +/// 4. `[writable]` beneficiary_account +#[derive(Clone, Debug)] +pub struct RemoveTransactionCpiBuilder<'a, 'b> { + instruction: Box>, +} + +impl<'a, 'b> RemoveTransactionCpiBuilder<'a, 'b> { + pub fn new(program: &'b solana_account_info::AccountInfo<'a>) -> Self { + let instruction = Box::new(RemoveTransactionCpiBuilderInstruction { + __program: program, + proposal_account: None, + token_owner_record: None, + governance_authority: None, + proposal_transaction_account: None, + beneficiary_account: None, + __remaining_accounts: Vec::new(), + }); + Self { instruction } + } + #[inline(always)] + pub fn proposal_account( + &mut self, + proposal_account: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.proposal_account = Some(proposal_account); + self + } + /// TokenOwnerRecord account of the Proposal owner + #[inline(always)] + pub fn token_owner_record( + &mut self, + token_owner_record: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.token_owner_record = Some(token_owner_record); + self + } + /// Governance Authority (Token Owner or Governance Delegate) + #[inline(always)] + pub fn governance_authority( + &mut self, + governance_authority: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.governance_authority = Some(governance_authority); + self + } + #[inline(always)] + pub fn proposal_transaction_account( + &mut self, + proposal_transaction_account: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.proposal_transaction_account = Some(proposal_transaction_account); + self + } + /// Beneficiary Account which would receive lamports from the disposed ProposalTransaction account + #[inline(always)] + pub fn beneficiary_account( + &mut self, + beneficiary_account: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.beneficiary_account = Some(beneficiary_account); + self + } + /// Add an additional account to the instruction. + #[inline(always)] + pub fn add_remaining_account( + &mut self, + account: &'b solana_account_info::AccountInfo<'a>, + is_writable: bool, + is_signer: bool, + ) -> &mut Self { + self.instruction + .__remaining_accounts + .push((account, is_writable, is_signer)); + self + } + /// Add additional accounts to the instruction. + /// + /// Each account is represented by a tuple of the `AccountInfo`, a `bool` indicating whether the account is writable or not, + /// and a `bool` indicating whether the account is a signer or not. + #[inline(always)] + pub fn add_remaining_accounts( + &mut self, + accounts: &[(&'b solana_account_info::AccountInfo<'a>, bool, bool)], + ) -> &mut Self { + self.instruction + .__remaining_accounts + .extend_from_slice(accounts); + self + } + #[inline(always)] + pub fn invoke(&self) -> solana_program_error::ProgramResult { + self.invoke_signed(&[]) + } + #[allow(clippy::clone_on_copy)] + #[allow(clippy::vec_init_then_push)] + pub fn invoke_signed(&self, signers_seeds: &[&[&[u8]]]) -> solana_program_error::ProgramResult { + let instruction = RemoveTransactionCpi { + __program: self.instruction.__program, + + proposal_account: self + .instruction + .proposal_account + .expect("proposal_account is not set"), + + token_owner_record: self + .instruction + .token_owner_record + .expect("token_owner_record is not set"), + + governance_authority: self + .instruction + .governance_authority + .expect("governance_authority is not set"), + + proposal_transaction_account: self + .instruction + .proposal_transaction_account + .expect("proposal_transaction_account is not set"), + + beneficiary_account: self + .instruction + .beneficiary_account + .expect("beneficiary_account is not set"), + }; + instruction.invoke_signed_with_remaining_accounts( + signers_seeds, + &self.instruction.__remaining_accounts, + ) + } +} + +#[derive(Clone, Debug)] +struct RemoveTransactionCpiBuilderInstruction<'a, 'b> { + __program: &'b solana_account_info::AccountInfo<'a>, + proposal_account: Option<&'b solana_account_info::AccountInfo<'a>>, + token_owner_record: Option<&'b solana_account_info::AccountInfo<'a>>, + governance_authority: Option<&'b solana_account_info::AccountInfo<'a>>, + proposal_transaction_account: Option<&'b solana_account_info::AccountInfo<'a>>, + beneficiary_account: Option<&'b solana_account_info::AccountInfo<'a>>, + /// Additional instruction accounts `(AccountInfo, is_writable, is_signer)`. + __remaining_accounts: Vec<(&'b solana_account_info::AccountInfo<'a>, bool, bool)>, +} diff --git a/e2e/governance/src/generated/instructions/revoke_governing_tokens.rs b/e2e/governance/src/generated/instructions/revoke_governing_tokens.rs new file mode 100644 index 0000000..2f09cb0 --- /dev/null +++ b/e2e/governance/src/generated/instructions/revoke_governing_tokens.rs @@ -0,0 +1,599 @@ +//! This code was AUTOGENERATED using the codama library. +//! Please DO NOT EDIT THIS FILE, instead use visitors +//! to add features, then rerun codama to update it. +//! +//! +//! + +use borsh::BorshDeserialize; +use borsh::BorshSerialize; + +pub const REVOKE_GOVERNING_TOKENS_DISCRIMINATOR: u8 = 26; + +/// Accounts. +#[derive(Debug)] +pub struct RevokeGoverningTokens { + pub realm_account: solana_pubkey::Pubkey, + /// seeds=['governance', realm, governing_token_mint] + pub governing_token_holding_account: solana_pubkey::Pubkey, + /// seeds=['governance', realm, governing_token_mint, governing_token_owner] + pub token_owner_record: solana_pubkey::Pubkey, + + pub governing_token_mint: solana_pubkey::Pubkey, + /// GoverningTokenMint mint_authority + pub governing_token_mint_authority_or_token_owner: solana_pubkey::Pubkey, + /// seeds=['realm-config', realm] + pub realm_config_account: solana_pubkey::Pubkey, + + pub token_program: solana_pubkey::Pubkey, +} + +impl RevokeGoverningTokens { + pub fn instruction( + &self, + args: RevokeGoverningTokensInstructionArgs, + ) -> solana_instruction::Instruction { + self.instruction_with_remaining_accounts(args, &[]) + } + #[allow(clippy::arithmetic_side_effects)] + #[allow(clippy::vec_init_then_push)] + pub fn instruction_with_remaining_accounts( + &self, + args: RevokeGoverningTokensInstructionArgs, + remaining_accounts: &[solana_instruction::AccountMeta], + ) -> solana_instruction::Instruction { + let mut accounts = Vec::with_capacity(7 + remaining_accounts.len()); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.realm_account, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + self.governing_token_holding_account, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + self.token_owner_record, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + self.governing_token_mint, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.governing_token_mint_authority_or_token_owner, + true, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.realm_config_account, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.token_program, + false, + )); + accounts.extend_from_slice(remaining_accounts); + let mut data = RevokeGoverningTokensInstructionData::new() + .try_to_vec() + .unwrap(); + let mut args = args.try_to_vec().unwrap(); + data.append(&mut args); + + solana_instruction::Instruction { + program_id: crate::SPL_GOVERNANCE_ID, + accounts, + data, + } + } +} + +#[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct RevokeGoverningTokensInstructionData { + discriminator: u8, +} + +impl RevokeGoverningTokensInstructionData { + pub fn new() -> Self { + Self { discriminator: 26 } + } + + pub(crate) fn try_to_vec(&self) -> Result, std::io::Error> { + borsh::to_vec(self) + } +} + +impl Default for RevokeGoverningTokensInstructionData { + fn default() -> Self { + Self::new() + } +} + +#[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct RevokeGoverningTokensInstructionArgs { + pub amount: u64, +} + +impl RevokeGoverningTokensInstructionArgs { + pub(crate) fn try_to_vec(&self) -> Result, std::io::Error> { + borsh::to_vec(self) + } +} + +/// Instruction builder for `RevokeGoverningTokens`. +/// +/// ### Accounts: +/// +/// 0. `[]` realm_account +/// 1. `[writable]` governing_token_holding_account +/// 2. `[writable]` token_owner_record +/// 3. `[writable]` governing_token_mint +/// 4. `[signer]` governing_token_mint_authority_or_token_owner +/// 5. `[]` realm_config_account +/// 6. `[optional]` token_program (default to `TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA`) +#[derive(Clone, Debug, Default)] +pub struct RevokeGoverningTokensBuilder { + realm_account: Option, + governing_token_holding_account: Option, + token_owner_record: Option, + governing_token_mint: Option, + governing_token_mint_authority_or_token_owner: Option, + realm_config_account: Option, + token_program: Option, + amount: Option, + __remaining_accounts: Vec, +} + +impl RevokeGoverningTokensBuilder { + pub fn new() -> Self { + Self::default() + } + #[inline(always)] + pub fn realm_account(&mut self, realm_account: solana_pubkey::Pubkey) -> &mut Self { + self.realm_account = Some(realm_account); + self + } + /// seeds=['governance', realm, governing_token_mint] + #[inline(always)] + pub fn governing_token_holding_account( + &mut self, + governing_token_holding_account: solana_pubkey::Pubkey, + ) -> &mut Self { + self.governing_token_holding_account = Some(governing_token_holding_account); + self + } + /// seeds=['governance', realm, governing_token_mint, governing_token_owner] + #[inline(always)] + pub fn token_owner_record(&mut self, token_owner_record: solana_pubkey::Pubkey) -> &mut Self { + self.token_owner_record = Some(token_owner_record); + self + } + #[inline(always)] + pub fn governing_token_mint( + &mut self, + governing_token_mint: solana_pubkey::Pubkey, + ) -> &mut Self { + self.governing_token_mint = Some(governing_token_mint); + self + } + /// GoverningTokenMint mint_authority + #[inline(always)] + pub fn governing_token_mint_authority_or_token_owner( + &mut self, + governing_token_mint_authority_or_token_owner: solana_pubkey::Pubkey, + ) -> &mut Self { + self.governing_token_mint_authority_or_token_owner = + Some(governing_token_mint_authority_or_token_owner); + self + } + /// seeds=['realm-config', realm] + #[inline(always)] + pub fn realm_config_account( + &mut self, + realm_config_account: solana_pubkey::Pubkey, + ) -> &mut Self { + self.realm_config_account = Some(realm_config_account); + self + } + /// `[optional account, default to 'TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA']` + #[inline(always)] + pub fn token_program(&mut self, token_program: solana_pubkey::Pubkey) -> &mut Self { + self.token_program = Some(token_program); + self + } + #[inline(always)] + pub fn amount(&mut self, amount: u64) -> &mut Self { + self.amount = Some(amount); + self + } + /// Add an additional account to the instruction. + #[inline(always)] + pub fn add_remaining_account(&mut self, account: solana_instruction::AccountMeta) -> &mut Self { + self.__remaining_accounts.push(account); + self + } + /// Add additional accounts to the instruction. + #[inline(always)] + pub fn add_remaining_accounts( + &mut self, + accounts: &[solana_instruction::AccountMeta], + ) -> &mut Self { + self.__remaining_accounts.extend_from_slice(accounts); + self + } + #[allow(clippy::clone_on_copy)] + pub fn instruction(&self) -> solana_instruction::Instruction { + let accounts = RevokeGoverningTokens { + realm_account: self.realm_account.expect("realm_account is not set"), + governing_token_holding_account: self + .governing_token_holding_account + .expect("governing_token_holding_account is not set"), + token_owner_record: self + .token_owner_record + .expect("token_owner_record is not set"), + governing_token_mint: self + .governing_token_mint + .expect("governing_token_mint is not set"), + governing_token_mint_authority_or_token_owner: self + .governing_token_mint_authority_or_token_owner + .expect("governing_token_mint_authority_or_token_owner is not set"), + realm_config_account: self + .realm_config_account + .expect("realm_config_account is not set"), + token_program: self.token_program.unwrap_or(solana_pubkey::pubkey!( + "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA" + )), + }; + let args = RevokeGoverningTokensInstructionArgs { + amount: self.amount.clone().expect("amount is not set"), + }; + + accounts.instruction_with_remaining_accounts(args, &self.__remaining_accounts) + } +} + +/// `revoke_governing_tokens` CPI accounts. +pub struct RevokeGoverningTokensCpiAccounts<'a, 'b> { + pub realm_account: &'b solana_account_info::AccountInfo<'a>, + /// seeds=['governance', realm, governing_token_mint] + pub governing_token_holding_account: &'b solana_account_info::AccountInfo<'a>, + /// seeds=['governance', realm, governing_token_mint, governing_token_owner] + pub token_owner_record: &'b solana_account_info::AccountInfo<'a>, + + pub governing_token_mint: &'b solana_account_info::AccountInfo<'a>, + /// GoverningTokenMint mint_authority + pub governing_token_mint_authority_or_token_owner: &'b solana_account_info::AccountInfo<'a>, + /// seeds=['realm-config', realm] + pub realm_config_account: &'b solana_account_info::AccountInfo<'a>, + + pub token_program: &'b solana_account_info::AccountInfo<'a>, +} + +/// `revoke_governing_tokens` CPI instruction. +pub struct RevokeGoverningTokensCpi<'a, 'b> { + /// The program to invoke. + pub __program: &'b solana_account_info::AccountInfo<'a>, + + pub realm_account: &'b solana_account_info::AccountInfo<'a>, + /// seeds=['governance', realm, governing_token_mint] + pub governing_token_holding_account: &'b solana_account_info::AccountInfo<'a>, + /// seeds=['governance', realm, governing_token_mint, governing_token_owner] + pub token_owner_record: &'b solana_account_info::AccountInfo<'a>, + + pub governing_token_mint: &'b solana_account_info::AccountInfo<'a>, + /// GoverningTokenMint mint_authority + pub governing_token_mint_authority_or_token_owner: &'b solana_account_info::AccountInfo<'a>, + /// seeds=['realm-config', realm] + pub realm_config_account: &'b solana_account_info::AccountInfo<'a>, + + pub token_program: &'b solana_account_info::AccountInfo<'a>, + /// The arguments for the instruction. + pub __args: RevokeGoverningTokensInstructionArgs, +} + +impl<'a, 'b> RevokeGoverningTokensCpi<'a, 'b> { + pub fn new( + program: &'b solana_account_info::AccountInfo<'a>, + accounts: RevokeGoverningTokensCpiAccounts<'a, 'b>, + args: RevokeGoverningTokensInstructionArgs, + ) -> Self { + Self { + __program: program, + realm_account: accounts.realm_account, + governing_token_holding_account: accounts.governing_token_holding_account, + token_owner_record: accounts.token_owner_record, + governing_token_mint: accounts.governing_token_mint, + governing_token_mint_authority_or_token_owner: accounts + .governing_token_mint_authority_or_token_owner, + realm_config_account: accounts.realm_config_account, + token_program: accounts.token_program, + __args: args, + } + } + #[inline(always)] + pub fn invoke(&self) -> solana_program_error::ProgramResult { + self.invoke_signed_with_remaining_accounts(&[], &[]) + } + #[inline(always)] + pub fn invoke_with_remaining_accounts( + &self, + remaining_accounts: &[(&'b solana_account_info::AccountInfo<'a>, bool, bool)], + ) -> solana_program_error::ProgramResult { + self.invoke_signed_with_remaining_accounts(&[], remaining_accounts) + } + #[inline(always)] + pub fn invoke_signed(&self, signers_seeds: &[&[&[u8]]]) -> solana_program_error::ProgramResult { + self.invoke_signed_with_remaining_accounts(signers_seeds, &[]) + } + #[allow(clippy::arithmetic_side_effects)] + #[allow(clippy::clone_on_copy)] + #[allow(clippy::vec_init_then_push)] + pub fn invoke_signed_with_remaining_accounts( + &self, + signers_seeds: &[&[&[u8]]], + remaining_accounts: &[(&'b solana_account_info::AccountInfo<'a>, bool, bool)], + ) -> solana_program_error::ProgramResult { + let mut accounts = Vec::with_capacity(7 + remaining_accounts.len()); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.realm_account.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + *self.governing_token_holding_account.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + *self.token_owner_record.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + *self.governing_token_mint.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.governing_token_mint_authority_or_token_owner.key, + true, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.realm_config_account.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.token_program.key, + false, + )); + remaining_accounts.iter().for_each(|remaining_account| { + accounts.push(solana_instruction::AccountMeta { + pubkey: *remaining_account.0.key, + is_signer: remaining_account.1, + is_writable: remaining_account.2, + }) + }); + let mut data = RevokeGoverningTokensInstructionData::new() + .try_to_vec() + .unwrap(); + let mut args = self.__args.try_to_vec().unwrap(); + data.append(&mut args); + + let instruction = solana_instruction::Instruction { + program_id: crate::SPL_GOVERNANCE_ID, + accounts, + data, + }; + let mut account_infos = Vec::with_capacity(8 + remaining_accounts.len()); + account_infos.push(self.__program.clone()); + account_infos.push(self.realm_account.clone()); + account_infos.push(self.governing_token_holding_account.clone()); + account_infos.push(self.token_owner_record.clone()); + account_infos.push(self.governing_token_mint.clone()); + account_infos.push(self.governing_token_mint_authority_or_token_owner.clone()); + account_infos.push(self.realm_config_account.clone()); + account_infos.push(self.token_program.clone()); + remaining_accounts + .iter() + .for_each(|remaining_account| account_infos.push(remaining_account.0.clone())); + + if signers_seeds.is_empty() { + solana_cpi::invoke(&instruction, &account_infos) + } else { + solana_cpi::invoke_signed(&instruction, &account_infos, signers_seeds) + } + } +} + +/// Instruction builder for `RevokeGoverningTokens` via CPI. +/// +/// ### Accounts: +/// +/// 0. `[]` realm_account +/// 1. `[writable]` governing_token_holding_account +/// 2. `[writable]` token_owner_record +/// 3. `[writable]` governing_token_mint +/// 4. `[signer]` governing_token_mint_authority_or_token_owner +/// 5. `[]` realm_config_account +/// 6. `[]` token_program +#[derive(Clone, Debug)] +pub struct RevokeGoverningTokensCpiBuilder<'a, 'b> { + instruction: Box>, +} + +impl<'a, 'b> RevokeGoverningTokensCpiBuilder<'a, 'b> { + pub fn new(program: &'b solana_account_info::AccountInfo<'a>) -> Self { + let instruction = Box::new(RevokeGoverningTokensCpiBuilderInstruction { + __program: program, + realm_account: None, + governing_token_holding_account: None, + token_owner_record: None, + governing_token_mint: None, + governing_token_mint_authority_or_token_owner: None, + realm_config_account: None, + token_program: None, + amount: None, + __remaining_accounts: Vec::new(), + }); + Self { instruction } + } + #[inline(always)] + pub fn realm_account( + &mut self, + realm_account: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.realm_account = Some(realm_account); + self + } + /// seeds=['governance', realm, governing_token_mint] + #[inline(always)] + pub fn governing_token_holding_account( + &mut self, + governing_token_holding_account: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.governing_token_holding_account = Some(governing_token_holding_account); + self + } + /// seeds=['governance', realm, governing_token_mint, governing_token_owner] + #[inline(always)] + pub fn token_owner_record( + &mut self, + token_owner_record: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.token_owner_record = Some(token_owner_record); + self + } + #[inline(always)] + pub fn governing_token_mint( + &mut self, + governing_token_mint: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.governing_token_mint = Some(governing_token_mint); + self + } + /// GoverningTokenMint mint_authority + #[inline(always)] + pub fn governing_token_mint_authority_or_token_owner( + &mut self, + governing_token_mint_authority_or_token_owner: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction + .governing_token_mint_authority_or_token_owner = + Some(governing_token_mint_authority_or_token_owner); + self + } + /// seeds=['realm-config', realm] + #[inline(always)] + pub fn realm_config_account( + &mut self, + realm_config_account: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.realm_config_account = Some(realm_config_account); + self + } + #[inline(always)] + pub fn token_program( + &mut self, + token_program: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.token_program = Some(token_program); + self + } + #[inline(always)] + pub fn amount(&mut self, amount: u64) -> &mut Self { + self.instruction.amount = Some(amount); + self + } + /// Add an additional account to the instruction. + #[inline(always)] + pub fn add_remaining_account( + &mut self, + account: &'b solana_account_info::AccountInfo<'a>, + is_writable: bool, + is_signer: bool, + ) -> &mut Self { + self.instruction + .__remaining_accounts + .push((account, is_writable, is_signer)); + self + } + /// Add additional accounts to the instruction. + /// + /// Each account is represented by a tuple of the `AccountInfo`, a `bool` indicating whether the account is writable or not, + /// and a `bool` indicating whether the account is a signer or not. + #[inline(always)] + pub fn add_remaining_accounts( + &mut self, + accounts: &[(&'b solana_account_info::AccountInfo<'a>, bool, bool)], + ) -> &mut Self { + self.instruction + .__remaining_accounts + .extend_from_slice(accounts); + self + } + #[inline(always)] + pub fn invoke(&self) -> solana_program_error::ProgramResult { + self.invoke_signed(&[]) + } + #[allow(clippy::clone_on_copy)] + #[allow(clippy::vec_init_then_push)] + pub fn invoke_signed(&self, signers_seeds: &[&[&[u8]]]) -> solana_program_error::ProgramResult { + let args = RevokeGoverningTokensInstructionArgs { + amount: self.instruction.amount.clone().expect("amount is not set"), + }; + let instruction = RevokeGoverningTokensCpi { + __program: self.instruction.__program, + + realm_account: self + .instruction + .realm_account + .expect("realm_account is not set"), + + governing_token_holding_account: self + .instruction + .governing_token_holding_account + .expect("governing_token_holding_account is not set"), + + token_owner_record: self + .instruction + .token_owner_record + .expect("token_owner_record is not set"), + + governing_token_mint: self + .instruction + .governing_token_mint + .expect("governing_token_mint is not set"), + + governing_token_mint_authority_or_token_owner: self + .instruction + .governing_token_mint_authority_or_token_owner + .expect("governing_token_mint_authority_or_token_owner is not set"), + + realm_config_account: self + .instruction + .realm_config_account + .expect("realm_config_account is not set"), + + token_program: self + .instruction + .token_program + .expect("token_program is not set"), + __args: args, + }; + instruction.invoke_signed_with_remaining_accounts( + signers_seeds, + &self.instruction.__remaining_accounts, + ) + } +} + +#[derive(Clone, Debug)] +struct RevokeGoverningTokensCpiBuilderInstruction<'a, 'b> { + __program: &'b solana_account_info::AccountInfo<'a>, + realm_account: Option<&'b solana_account_info::AccountInfo<'a>>, + governing_token_holding_account: Option<&'b solana_account_info::AccountInfo<'a>>, + token_owner_record: Option<&'b solana_account_info::AccountInfo<'a>>, + governing_token_mint: Option<&'b solana_account_info::AccountInfo<'a>>, + governing_token_mint_authority_or_token_owner: Option<&'b solana_account_info::AccountInfo<'a>>, + realm_config_account: Option<&'b solana_account_info::AccountInfo<'a>>, + token_program: Option<&'b solana_account_info::AccountInfo<'a>>, + amount: Option, + /// Additional instruction accounts `(AccountInfo, is_writable, is_signer)`. + __remaining_accounts: Vec<(&'b solana_account_info::AccountInfo<'a>, bool, bool)>, +} diff --git a/e2e/governance/src/generated/instructions/set_governance_config.rs b/e2e/governance/src/generated/instructions/set_governance_config.rs new file mode 100644 index 0000000..99ec8f7 --- /dev/null +++ b/e2e/governance/src/generated/instructions/set_governance_config.rs @@ -0,0 +1,329 @@ +//! This code was AUTOGENERATED using the codama library. +//! Please DO NOT EDIT THIS FILE, instead use visitors +//! to add features, then rerun codama to update it. +//! +//! +//! + +use crate::generated::types::GovernanceConfig; +use borsh::BorshDeserialize; +use borsh::BorshSerialize; + +pub const SET_GOVERNANCE_CONFIG_DISCRIMINATOR: u8 = 19; + +/// Accounts. +#[derive(Debug)] +pub struct SetGovernanceConfig { + /// The governance account the config is for + pub governance_account: solana_pubkey::Pubkey, +} + +impl SetGovernanceConfig { + pub fn instruction( + &self, + args: SetGovernanceConfigInstructionArgs, + ) -> solana_instruction::Instruction { + self.instruction_with_remaining_accounts(args, &[]) + } + #[allow(clippy::arithmetic_side_effects)] + #[allow(clippy::vec_init_then_push)] + pub fn instruction_with_remaining_accounts( + &self, + args: SetGovernanceConfigInstructionArgs, + remaining_accounts: &[solana_instruction::AccountMeta], + ) -> solana_instruction::Instruction { + let mut accounts = Vec::with_capacity(1 + remaining_accounts.len()); + accounts.push(solana_instruction::AccountMeta::new( + self.governance_account, + true, + )); + accounts.extend_from_slice(remaining_accounts); + let mut data = SetGovernanceConfigInstructionData::new() + .try_to_vec() + .unwrap(); + let mut args = args.try_to_vec().unwrap(); + data.append(&mut args); + + solana_instruction::Instruction { + program_id: crate::SPL_GOVERNANCE_ID, + accounts, + data, + } + } +} + +#[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct SetGovernanceConfigInstructionData { + discriminator: u8, +} + +impl SetGovernanceConfigInstructionData { + pub fn new() -> Self { + Self { discriminator: 19 } + } + + pub(crate) fn try_to_vec(&self) -> Result, std::io::Error> { + borsh::to_vec(self) + } +} + +impl Default for SetGovernanceConfigInstructionData { + fn default() -> Self { + Self::new() + } +} + +#[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct SetGovernanceConfigInstructionArgs { + pub config: GovernanceConfig, +} + +impl SetGovernanceConfigInstructionArgs { + pub(crate) fn try_to_vec(&self) -> Result, std::io::Error> { + borsh::to_vec(self) + } +} + +/// Instruction builder for `SetGovernanceConfig`. +/// +/// ### Accounts: +/// +/// 0. `[writable, signer]` governance_account +#[derive(Clone, Debug, Default)] +pub struct SetGovernanceConfigBuilder { + governance_account: Option, + config: Option, + __remaining_accounts: Vec, +} + +impl SetGovernanceConfigBuilder { + pub fn new() -> Self { + Self::default() + } + /// The governance account the config is for + #[inline(always)] + pub fn governance_account(&mut self, governance_account: solana_pubkey::Pubkey) -> &mut Self { + self.governance_account = Some(governance_account); + self + } + #[inline(always)] + pub fn config(&mut self, config: GovernanceConfig) -> &mut Self { + self.config = Some(config); + self + } + /// Add an additional account to the instruction. + #[inline(always)] + pub fn add_remaining_account(&mut self, account: solana_instruction::AccountMeta) -> &mut Self { + self.__remaining_accounts.push(account); + self + } + /// Add additional accounts to the instruction. + #[inline(always)] + pub fn add_remaining_accounts( + &mut self, + accounts: &[solana_instruction::AccountMeta], + ) -> &mut Self { + self.__remaining_accounts.extend_from_slice(accounts); + self + } + #[allow(clippy::clone_on_copy)] + pub fn instruction(&self) -> solana_instruction::Instruction { + let accounts = SetGovernanceConfig { + governance_account: self + .governance_account + .expect("governance_account is not set"), + }; + let args = SetGovernanceConfigInstructionArgs { + config: self.config.clone().expect("config is not set"), + }; + + accounts.instruction_with_remaining_accounts(args, &self.__remaining_accounts) + } +} + +/// `set_governance_config` CPI accounts. +pub struct SetGovernanceConfigCpiAccounts<'a, 'b> { + /// The governance account the config is for + pub governance_account: &'b solana_account_info::AccountInfo<'a>, +} + +/// `set_governance_config` CPI instruction. +pub struct SetGovernanceConfigCpi<'a, 'b> { + /// The program to invoke. + pub __program: &'b solana_account_info::AccountInfo<'a>, + /// The governance account the config is for + pub governance_account: &'b solana_account_info::AccountInfo<'a>, + /// The arguments for the instruction. + pub __args: SetGovernanceConfigInstructionArgs, +} + +impl<'a, 'b> SetGovernanceConfigCpi<'a, 'b> { + pub fn new( + program: &'b solana_account_info::AccountInfo<'a>, + accounts: SetGovernanceConfigCpiAccounts<'a, 'b>, + args: SetGovernanceConfigInstructionArgs, + ) -> Self { + Self { + __program: program, + governance_account: accounts.governance_account, + __args: args, + } + } + #[inline(always)] + pub fn invoke(&self) -> solana_program_error::ProgramResult { + self.invoke_signed_with_remaining_accounts(&[], &[]) + } + #[inline(always)] + pub fn invoke_with_remaining_accounts( + &self, + remaining_accounts: &[(&'b solana_account_info::AccountInfo<'a>, bool, bool)], + ) -> solana_program_error::ProgramResult { + self.invoke_signed_with_remaining_accounts(&[], remaining_accounts) + } + #[inline(always)] + pub fn invoke_signed(&self, signers_seeds: &[&[&[u8]]]) -> solana_program_error::ProgramResult { + self.invoke_signed_with_remaining_accounts(signers_seeds, &[]) + } + #[allow(clippy::arithmetic_side_effects)] + #[allow(clippy::clone_on_copy)] + #[allow(clippy::vec_init_then_push)] + pub fn invoke_signed_with_remaining_accounts( + &self, + signers_seeds: &[&[&[u8]]], + remaining_accounts: &[(&'b solana_account_info::AccountInfo<'a>, bool, bool)], + ) -> solana_program_error::ProgramResult { + let mut accounts = Vec::with_capacity(1 + remaining_accounts.len()); + accounts.push(solana_instruction::AccountMeta::new( + *self.governance_account.key, + true, + )); + remaining_accounts.iter().for_each(|remaining_account| { + accounts.push(solana_instruction::AccountMeta { + pubkey: *remaining_account.0.key, + is_signer: remaining_account.1, + is_writable: remaining_account.2, + }) + }); + let mut data = SetGovernanceConfigInstructionData::new() + .try_to_vec() + .unwrap(); + let mut args = self.__args.try_to_vec().unwrap(); + data.append(&mut args); + + let instruction = solana_instruction::Instruction { + program_id: crate::SPL_GOVERNANCE_ID, + accounts, + data, + }; + let mut account_infos = Vec::with_capacity(2 + remaining_accounts.len()); + account_infos.push(self.__program.clone()); + account_infos.push(self.governance_account.clone()); + remaining_accounts + .iter() + .for_each(|remaining_account| account_infos.push(remaining_account.0.clone())); + + if signers_seeds.is_empty() { + solana_cpi::invoke(&instruction, &account_infos) + } else { + solana_cpi::invoke_signed(&instruction, &account_infos, signers_seeds) + } + } +} + +/// Instruction builder for `SetGovernanceConfig` via CPI. +/// +/// ### Accounts: +/// +/// 0. `[writable, signer]` governance_account +#[derive(Clone, Debug)] +pub struct SetGovernanceConfigCpiBuilder<'a, 'b> { + instruction: Box>, +} + +impl<'a, 'b> SetGovernanceConfigCpiBuilder<'a, 'b> { + pub fn new(program: &'b solana_account_info::AccountInfo<'a>) -> Self { + let instruction = Box::new(SetGovernanceConfigCpiBuilderInstruction { + __program: program, + governance_account: None, + config: None, + __remaining_accounts: Vec::new(), + }); + Self { instruction } + } + /// The governance account the config is for + #[inline(always)] + pub fn governance_account( + &mut self, + governance_account: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.governance_account = Some(governance_account); + self + } + #[inline(always)] + pub fn config(&mut self, config: GovernanceConfig) -> &mut Self { + self.instruction.config = Some(config); + self + } + /// Add an additional account to the instruction. + #[inline(always)] + pub fn add_remaining_account( + &mut self, + account: &'b solana_account_info::AccountInfo<'a>, + is_writable: bool, + is_signer: bool, + ) -> &mut Self { + self.instruction + .__remaining_accounts + .push((account, is_writable, is_signer)); + self + } + /// Add additional accounts to the instruction. + /// + /// Each account is represented by a tuple of the `AccountInfo`, a `bool` indicating whether the account is writable or not, + /// and a `bool` indicating whether the account is a signer or not. + #[inline(always)] + pub fn add_remaining_accounts( + &mut self, + accounts: &[(&'b solana_account_info::AccountInfo<'a>, bool, bool)], + ) -> &mut Self { + self.instruction + .__remaining_accounts + .extend_from_slice(accounts); + self + } + #[inline(always)] + pub fn invoke(&self) -> solana_program_error::ProgramResult { + self.invoke_signed(&[]) + } + #[allow(clippy::clone_on_copy)] + #[allow(clippy::vec_init_then_push)] + pub fn invoke_signed(&self, signers_seeds: &[&[&[u8]]]) -> solana_program_error::ProgramResult { + let args = SetGovernanceConfigInstructionArgs { + config: self.instruction.config.clone().expect("config is not set"), + }; + let instruction = SetGovernanceConfigCpi { + __program: self.instruction.__program, + + governance_account: self + .instruction + .governance_account + .expect("governance_account is not set"), + __args: args, + }; + instruction.invoke_signed_with_remaining_accounts( + signers_seeds, + &self.instruction.__remaining_accounts, + ) + } +} + +#[derive(Clone, Debug)] +struct SetGovernanceConfigCpiBuilderInstruction<'a, 'b> { + __program: &'b solana_account_info::AccountInfo<'a>, + governance_account: Option<&'b solana_account_info::AccountInfo<'a>>, + config: Option, + /// Additional instruction accounts `(AccountInfo, is_writable, is_signer)`. + __remaining_accounts: Vec<(&'b solana_account_info::AccountInfo<'a>, bool, bool)>, +} diff --git a/e2e/governance/src/generated/instructions/set_governance_delegate.rs b/e2e/governance/src/generated/instructions/set_governance_delegate.rs new file mode 100644 index 0000000..d542369 --- /dev/null +++ b/e2e/governance/src/generated/instructions/set_governance_delegate.rs @@ -0,0 +1,376 @@ +//! This code was AUTOGENERATED using the codama library. +//! Please DO NOT EDIT THIS FILE, instead use visitors +//! to add features, then rerun codama to update it. +//! +//! +//! + +use borsh::BorshDeserialize; +use borsh::BorshSerialize; +use solana_pubkey::Pubkey; + +pub const SET_GOVERNANCE_DELEGATE_DISCRIMINATOR: u8 = 3; + +/// Accounts. +#[derive(Debug)] +pub struct SetGovernanceDelegate { + /// Current governance delegate or governing token owner + pub current_delegate_or_owner: solana_pubkey::Pubkey, + + pub token_owner_record: solana_pubkey::Pubkey, +} + +impl SetGovernanceDelegate { + pub fn instruction( + &self, + args: SetGovernanceDelegateInstructionArgs, + ) -> solana_instruction::Instruction { + self.instruction_with_remaining_accounts(args, &[]) + } + #[allow(clippy::arithmetic_side_effects)] + #[allow(clippy::vec_init_then_push)] + pub fn instruction_with_remaining_accounts( + &self, + args: SetGovernanceDelegateInstructionArgs, + remaining_accounts: &[solana_instruction::AccountMeta], + ) -> solana_instruction::Instruction { + let mut accounts = Vec::with_capacity(2 + remaining_accounts.len()); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.current_delegate_or_owner, + true, + )); + accounts.push(solana_instruction::AccountMeta::new( + self.token_owner_record, + false, + )); + accounts.extend_from_slice(remaining_accounts); + let mut data = SetGovernanceDelegateInstructionData::new() + .try_to_vec() + .unwrap(); + let mut args = args.try_to_vec().unwrap(); + data.append(&mut args); + + solana_instruction::Instruction { + program_id: crate::SPL_GOVERNANCE_ID, + accounts, + data, + } + } +} + +#[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct SetGovernanceDelegateInstructionData { + discriminator: u8, +} + +impl SetGovernanceDelegateInstructionData { + pub fn new() -> Self { + Self { discriminator: 3 } + } + + pub(crate) fn try_to_vec(&self) -> Result, std::io::Error> { + borsh::to_vec(self) + } +} + +impl Default for SetGovernanceDelegateInstructionData { + fn default() -> Self { + Self::new() + } +} + +#[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct SetGovernanceDelegateInstructionArgs { + pub new_governance_delegate: Option, +} + +impl SetGovernanceDelegateInstructionArgs { + pub(crate) fn try_to_vec(&self) -> Result, std::io::Error> { + borsh::to_vec(self) + } +} + +/// Instruction builder for `SetGovernanceDelegate`. +/// +/// ### Accounts: +/// +/// 0. `[signer]` current_delegate_or_owner +/// 1. `[writable]` token_owner_record +#[derive(Clone, Debug, Default)] +pub struct SetGovernanceDelegateBuilder { + current_delegate_or_owner: Option, + token_owner_record: Option, + new_governance_delegate: Option, + __remaining_accounts: Vec, +} + +impl SetGovernanceDelegateBuilder { + pub fn new() -> Self { + Self::default() + } + /// Current governance delegate or governing token owner + #[inline(always)] + pub fn current_delegate_or_owner( + &mut self, + current_delegate_or_owner: solana_pubkey::Pubkey, + ) -> &mut Self { + self.current_delegate_or_owner = Some(current_delegate_or_owner); + self + } + #[inline(always)] + pub fn token_owner_record(&mut self, token_owner_record: solana_pubkey::Pubkey) -> &mut Self { + self.token_owner_record = Some(token_owner_record); + self + } + /// `[optional argument]` + #[inline(always)] + pub fn new_governance_delegate(&mut self, new_governance_delegate: Pubkey) -> &mut Self { + self.new_governance_delegate = Some(new_governance_delegate); + self + } + /// Add an additional account to the instruction. + #[inline(always)] + pub fn add_remaining_account(&mut self, account: solana_instruction::AccountMeta) -> &mut Self { + self.__remaining_accounts.push(account); + self + } + /// Add additional accounts to the instruction. + #[inline(always)] + pub fn add_remaining_accounts( + &mut self, + accounts: &[solana_instruction::AccountMeta], + ) -> &mut Self { + self.__remaining_accounts.extend_from_slice(accounts); + self + } + #[allow(clippy::clone_on_copy)] + pub fn instruction(&self) -> solana_instruction::Instruction { + let accounts = SetGovernanceDelegate { + current_delegate_or_owner: self + .current_delegate_or_owner + .expect("current_delegate_or_owner is not set"), + token_owner_record: self + .token_owner_record + .expect("token_owner_record is not set"), + }; + let args = SetGovernanceDelegateInstructionArgs { + new_governance_delegate: self.new_governance_delegate.clone(), + }; + + accounts.instruction_with_remaining_accounts(args, &self.__remaining_accounts) + } +} + +/// `set_governance_delegate` CPI accounts. +pub struct SetGovernanceDelegateCpiAccounts<'a, 'b> { + /// Current governance delegate or governing token owner + pub current_delegate_or_owner: &'b solana_account_info::AccountInfo<'a>, + + pub token_owner_record: &'b solana_account_info::AccountInfo<'a>, +} + +/// `set_governance_delegate` CPI instruction. +pub struct SetGovernanceDelegateCpi<'a, 'b> { + /// The program to invoke. + pub __program: &'b solana_account_info::AccountInfo<'a>, + /// Current governance delegate or governing token owner + pub current_delegate_or_owner: &'b solana_account_info::AccountInfo<'a>, + + pub token_owner_record: &'b solana_account_info::AccountInfo<'a>, + /// The arguments for the instruction. + pub __args: SetGovernanceDelegateInstructionArgs, +} + +impl<'a, 'b> SetGovernanceDelegateCpi<'a, 'b> { + pub fn new( + program: &'b solana_account_info::AccountInfo<'a>, + accounts: SetGovernanceDelegateCpiAccounts<'a, 'b>, + args: SetGovernanceDelegateInstructionArgs, + ) -> Self { + Self { + __program: program, + current_delegate_or_owner: accounts.current_delegate_or_owner, + token_owner_record: accounts.token_owner_record, + __args: args, + } + } + #[inline(always)] + pub fn invoke(&self) -> solana_program_error::ProgramResult { + self.invoke_signed_with_remaining_accounts(&[], &[]) + } + #[inline(always)] + pub fn invoke_with_remaining_accounts( + &self, + remaining_accounts: &[(&'b solana_account_info::AccountInfo<'a>, bool, bool)], + ) -> solana_program_error::ProgramResult { + self.invoke_signed_with_remaining_accounts(&[], remaining_accounts) + } + #[inline(always)] + pub fn invoke_signed(&self, signers_seeds: &[&[&[u8]]]) -> solana_program_error::ProgramResult { + self.invoke_signed_with_remaining_accounts(signers_seeds, &[]) + } + #[allow(clippy::arithmetic_side_effects)] + #[allow(clippy::clone_on_copy)] + #[allow(clippy::vec_init_then_push)] + pub fn invoke_signed_with_remaining_accounts( + &self, + signers_seeds: &[&[&[u8]]], + remaining_accounts: &[(&'b solana_account_info::AccountInfo<'a>, bool, bool)], + ) -> solana_program_error::ProgramResult { + let mut accounts = Vec::with_capacity(2 + remaining_accounts.len()); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.current_delegate_or_owner.key, + true, + )); + accounts.push(solana_instruction::AccountMeta::new( + *self.token_owner_record.key, + false, + )); + remaining_accounts.iter().for_each(|remaining_account| { + accounts.push(solana_instruction::AccountMeta { + pubkey: *remaining_account.0.key, + is_signer: remaining_account.1, + is_writable: remaining_account.2, + }) + }); + let mut data = SetGovernanceDelegateInstructionData::new() + .try_to_vec() + .unwrap(); + let mut args = self.__args.try_to_vec().unwrap(); + data.append(&mut args); + + let instruction = solana_instruction::Instruction { + program_id: crate::SPL_GOVERNANCE_ID, + accounts, + data, + }; + let mut account_infos = Vec::with_capacity(3 + remaining_accounts.len()); + account_infos.push(self.__program.clone()); + account_infos.push(self.current_delegate_or_owner.clone()); + account_infos.push(self.token_owner_record.clone()); + remaining_accounts + .iter() + .for_each(|remaining_account| account_infos.push(remaining_account.0.clone())); + + if signers_seeds.is_empty() { + solana_cpi::invoke(&instruction, &account_infos) + } else { + solana_cpi::invoke_signed(&instruction, &account_infos, signers_seeds) + } + } +} + +/// Instruction builder for `SetGovernanceDelegate` via CPI. +/// +/// ### Accounts: +/// +/// 0. `[signer]` current_delegate_or_owner +/// 1. `[writable]` token_owner_record +#[derive(Clone, Debug)] +pub struct SetGovernanceDelegateCpiBuilder<'a, 'b> { + instruction: Box>, +} + +impl<'a, 'b> SetGovernanceDelegateCpiBuilder<'a, 'b> { + pub fn new(program: &'b solana_account_info::AccountInfo<'a>) -> Self { + let instruction = Box::new(SetGovernanceDelegateCpiBuilderInstruction { + __program: program, + current_delegate_or_owner: None, + token_owner_record: None, + new_governance_delegate: None, + __remaining_accounts: Vec::new(), + }); + Self { instruction } + } + /// Current governance delegate or governing token owner + #[inline(always)] + pub fn current_delegate_or_owner( + &mut self, + current_delegate_or_owner: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.current_delegate_or_owner = Some(current_delegate_or_owner); + self + } + #[inline(always)] + pub fn token_owner_record( + &mut self, + token_owner_record: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.token_owner_record = Some(token_owner_record); + self + } + /// `[optional argument]` + #[inline(always)] + pub fn new_governance_delegate(&mut self, new_governance_delegate: Pubkey) -> &mut Self { + self.instruction.new_governance_delegate = Some(new_governance_delegate); + self + } + /// Add an additional account to the instruction. + #[inline(always)] + pub fn add_remaining_account( + &mut self, + account: &'b solana_account_info::AccountInfo<'a>, + is_writable: bool, + is_signer: bool, + ) -> &mut Self { + self.instruction + .__remaining_accounts + .push((account, is_writable, is_signer)); + self + } + /// Add additional accounts to the instruction. + /// + /// Each account is represented by a tuple of the `AccountInfo`, a `bool` indicating whether the account is writable or not, + /// and a `bool` indicating whether the account is a signer or not. + #[inline(always)] + pub fn add_remaining_accounts( + &mut self, + accounts: &[(&'b solana_account_info::AccountInfo<'a>, bool, bool)], + ) -> &mut Self { + self.instruction + .__remaining_accounts + .extend_from_slice(accounts); + self + } + #[inline(always)] + pub fn invoke(&self) -> solana_program_error::ProgramResult { + self.invoke_signed(&[]) + } + #[allow(clippy::clone_on_copy)] + #[allow(clippy::vec_init_then_push)] + pub fn invoke_signed(&self, signers_seeds: &[&[&[u8]]]) -> solana_program_error::ProgramResult { + let args = SetGovernanceDelegateInstructionArgs { + new_governance_delegate: self.instruction.new_governance_delegate.clone(), + }; + let instruction = SetGovernanceDelegateCpi { + __program: self.instruction.__program, + + current_delegate_or_owner: self + .instruction + .current_delegate_or_owner + .expect("current_delegate_or_owner is not set"), + + token_owner_record: self + .instruction + .token_owner_record + .expect("token_owner_record is not set"), + __args: args, + }; + instruction.invoke_signed_with_remaining_accounts( + signers_seeds, + &self.instruction.__remaining_accounts, + ) + } +} + +#[derive(Clone, Debug)] +struct SetGovernanceDelegateCpiBuilderInstruction<'a, 'b> { + __program: &'b solana_account_info::AccountInfo<'a>, + current_delegate_or_owner: Option<&'b solana_account_info::AccountInfo<'a>>, + token_owner_record: Option<&'b solana_account_info::AccountInfo<'a>>, + new_governance_delegate: Option, + /// Additional instruction accounts `(AccountInfo, is_writable, is_signer)`. + __remaining_accounts: Vec<(&'b solana_account_info::AccountInfo<'a>, bool, bool)>, +} diff --git a/e2e/governance/src/generated/instructions/set_realm_authority.rs b/e2e/governance/src/generated/instructions/set_realm_authority.rs new file mode 100644 index 0000000..eeb20a8 --- /dev/null +++ b/e2e/governance/src/generated/instructions/set_realm_authority.rs @@ -0,0 +1,423 @@ +//! This code was AUTOGENERATED using the codama library. +//! Please DO NOT EDIT THIS FILE, instead use visitors +//! to add features, then rerun codama to update it. +//! +//! +//! + +use crate::generated::types::SetRealmAuthorityAction; +use borsh::BorshDeserialize; +use borsh::BorshSerialize; + +pub const SET_REALM_AUTHORITY_DISCRIMINATOR: u8 = 21; + +/// Accounts. +#[derive(Debug)] +pub struct SetRealmAuthority { + pub realm_account: solana_pubkey::Pubkey, + + pub realm_authority: solana_pubkey::Pubkey, + /// Must be one of the realm governances when set + pub new_realm_authority: Option, +} + +impl SetRealmAuthority { + pub fn instruction( + &self, + args: SetRealmAuthorityInstructionArgs, + ) -> solana_instruction::Instruction { + self.instruction_with_remaining_accounts(args, &[]) + } + #[allow(clippy::arithmetic_side_effects)] + #[allow(clippy::vec_init_then_push)] + pub fn instruction_with_remaining_accounts( + &self, + args: SetRealmAuthorityInstructionArgs, + remaining_accounts: &[solana_instruction::AccountMeta], + ) -> solana_instruction::Instruction { + let mut accounts = Vec::with_capacity(3 + remaining_accounts.len()); + accounts.push(solana_instruction::AccountMeta::new( + self.realm_account, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.realm_authority, + true, + )); + if let Some(new_realm_authority) = self.new_realm_authority { + accounts.push(solana_instruction::AccountMeta::new_readonly( + new_realm_authority, + false, + )); + } else { + accounts.push(solana_instruction::AccountMeta::new_readonly( + crate::SPL_GOVERNANCE_ID, + false, + )); + } + accounts.extend_from_slice(remaining_accounts); + let mut data = SetRealmAuthorityInstructionData::new() + .try_to_vec() + .unwrap(); + let mut args = args.try_to_vec().unwrap(); + data.append(&mut args); + + solana_instruction::Instruction { + program_id: crate::SPL_GOVERNANCE_ID, + accounts, + data, + } + } +} + +#[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct SetRealmAuthorityInstructionData { + discriminator: u8, +} + +impl SetRealmAuthorityInstructionData { + pub fn new() -> Self { + Self { discriminator: 21 } + } + + pub(crate) fn try_to_vec(&self) -> Result, std::io::Error> { + borsh::to_vec(self) + } +} + +impl Default for SetRealmAuthorityInstructionData { + fn default() -> Self { + Self::new() + } +} + +#[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct SetRealmAuthorityInstructionArgs { + pub action: SetRealmAuthorityAction, +} + +impl SetRealmAuthorityInstructionArgs { + pub(crate) fn try_to_vec(&self) -> Result, std::io::Error> { + borsh::to_vec(self) + } +} + +/// Instruction builder for `SetRealmAuthority`. +/// +/// ### Accounts: +/// +/// 0. `[writable]` realm_account +/// 1. `[signer]` realm_authority +/// 2. `[optional]` new_realm_authority +#[derive(Clone, Debug, Default)] +pub struct SetRealmAuthorityBuilder { + realm_account: Option, + realm_authority: Option, + new_realm_authority: Option, + action: Option, + __remaining_accounts: Vec, +} + +impl SetRealmAuthorityBuilder { + pub fn new() -> Self { + Self::default() + } + #[inline(always)] + pub fn realm_account(&mut self, realm_account: solana_pubkey::Pubkey) -> &mut Self { + self.realm_account = Some(realm_account); + self + } + #[inline(always)] + pub fn realm_authority(&mut self, realm_authority: solana_pubkey::Pubkey) -> &mut Self { + self.realm_authority = Some(realm_authority); + self + } + /// `[optional account]` + /// Must be one of the realm governances when set + #[inline(always)] + pub fn new_realm_authority( + &mut self, + new_realm_authority: Option, + ) -> &mut Self { + self.new_realm_authority = new_realm_authority; + self + } + #[inline(always)] + pub fn action(&mut self, action: SetRealmAuthorityAction) -> &mut Self { + self.action = Some(action); + self + } + /// Add an additional account to the instruction. + #[inline(always)] + pub fn add_remaining_account(&mut self, account: solana_instruction::AccountMeta) -> &mut Self { + self.__remaining_accounts.push(account); + self + } + /// Add additional accounts to the instruction. + #[inline(always)] + pub fn add_remaining_accounts( + &mut self, + accounts: &[solana_instruction::AccountMeta], + ) -> &mut Self { + self.__remaining_accounts.extend_from_slice(accounts); + self + } + #[allow(clippy::clone_on_copy)] + pub fn instruction(&self) -> solana_instruction::Instruction { + let accounts = SetRealmAuthority { + realm_account: self.realm_account.expect("realm_account is not set"), + realm_authority: self.realm_authority.expect("realm_authority is not set"), + new_realm_authority: self.new_realm_authority, + }; + let args = SetRealmAuthorityInstructionArgs { + action: self.action.clone().expect("action is not set"), + }; + + accounts.instruction_with_remaining_accounts(args, &self.__remaining_accounts) + } +} + +/// `set_realm_authority` CPI accounts. +pub struct SetRealmAuthorityCpiAccounts<'a, 'b> { + pub realm_account: &'b solana_account_info::AccountInfo<'a>, + + pub realm_authority: &'b solana_account_info::AccountInfo<'a>, + /// Must be one of the realm governances when set + pub new_realm_authority: Option<&'b solana_account_info::AccountInfo<'a>>, +} + +/// `set_realm_authority` CPI instruction. +pub struct SetRealmAuthorityCpi<'a, 'b> { + /// The program to invoke. + pub __program: &'b solana_account_info::AccountInfo<'a>, + + pub realm_account: &'b solana_account_info::AccountInfo<'a>, + + pub realm_authority: &'b solana_account_info::AccountInfo<'a>, + /// Must be one of the realm governances when set + pub new_realm_authority: Option<&'b solana_account_info::AccountInfo<'a>>, + /// The arguments for the instruction. + pub __args: SetRealmAuthorityInstructionArgs, +} + +impl<'a, 'b> SetRealmAuthorityCpi<'a, 'b> { + pub fn new( + program: &'b solana_account_info::AccountInfo<'a>, + accounts: SetRealmAuthorityCpiAccounts<'a, 'b>, + args: SetRealmAuthorityInstructionArgs, + ) -> Self { + Self { + __program: program, + realm_account: accounts.realm_account, + realm_authority: accounts.realm_authority, + new_realm_authority: accounts.new_realm_authority, + __args: args, + } + } + #[inline(always)] + pub fn invoke(&self) -> solana_program_error::ProgramResult { + self.invoke_signed_with_remaining_accounts(&[], &[]) + } + #[inline(always)] + pub fn invoke_with_remaining_accounts( + &self, + remaining_accounts: &[(&'b solana_account_info::AccountInfo<'a>, bool, bool)], + ) -> solana_program_error::ProgramResult { + self.invoke_signed_with_remaining_accounts(&[], remaining_accounts) + } + #[inline(always)] + pub fn invoke_signed(&self, signers_seeds: &[&[&[u8]]]) -> solana_program_error::ProgramResult { + self.invoke_signed_with_remaining_accounts(signers_seeds, &[]) + } + #[allow(clippy::arithmetic_side_effects)] + #[allow(clippy::clone_on_copy)] + #[allow(clippy::vec_init_then_push)] + pub fn invoke_signed_with_remaining_accounts( + &self, + signers_seeds: &[&[&[u8]]], + remaining_accounts: &[(&'b solana_account_info::AccountInfo<'a>, bool, bool)], + ) -> solana_program_error::ProgramResult { + let mut accounts = Vec::with_capacity(3 + remaining_accounts.len()); + accounts.push(solana_instruction::AccountMeta::new( + *self.realm_account.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.realm_authority.key, + true, + )); + if let Some(new_realm_authority) = self.new_realm_authority { + accounts.push(solana_instruction::AccountMeta::new_readonly( + *new_realm_authority.key, + false, + )); + } else { + accounts.push(solana_instruction::AccountMeta::new_readonly( + crate::SPL_GOVERNANCE_ID, + false, + )); + } + remaining_accounts.iter().for_each(|remaining_account| { + accounts.push(solana_instruction::AccountMeta { + pubkey: *remaining_account.0.key, + is_signer: remaining_account.1, + is_writable: remaining_account.2, + }) + }); + let mut data = SetRealmAuthorityInstructionData::new() + .try_to_vec() + .unwrap(); + let mut args = self.__args.try_to_vec().unwrap(); + data.append(&mut args); + + let instruction = solana_instruction::Instruction { + program_id: crate::SPL_GOVERNANCE_ID, + accounts, + data, + }; + let mut account_infos = Vec::with_capacity(4 + remaining_accounts.len()); + account_infos.push(self.__program.clone()); + account_infos.push(self.realm_account.clone()); + account_infos.push(self.realm_authority.clone()); + if let Some(new_realm_authority) = self.new_realm_authority { + account_infos.push(new_realm_authority.clone()); + } + remaining_accounts + .iter() + .for_each(|remaining_account| account_infos.push(remaining_account.0.clone())); + + if signers_seeds.is_empty() { + solana_cpi::invoke(&instruction, &account_infos) + } else { + solana_cpi::invoke_signed(&instruction, &account_infos, signers_seeds) + } + } +} + +/// Instruction builder for `SetRealmAuthority` via CPI. +/// +/// ### Accounts: +/// +/// 0. `[writable]` realm_account +/// 1. `[signer]` realm_authority +/// 2. `[optional]` new_realm_authority +#[derive(Clone, Debug)] +pub struct SetRealmAuthorityCpiBuilder<'a, 'b> { + instruction: Box>, +} + +impl<'a, 'b> SetRealmAuthorityCpiBuilder<'a, 'b> { + pub fn new(program: &'b solana_account_info::AccountInfo<'a>) -> Self { + let instruction = Box::new(SetRealmAuthorityCpiBuilderInstruction { + __program: program, + realm_account: None, + realm_authority: None, + new_realm_authority: None, + action: None, + __remaining_accounts: Vec::new(), + }); + Self { instruction } + } + #[inline(always)] + pub fn realm_account( + &mut self, + realm_account: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.realm_account = Some(realm_account); + self + } + #[inline(always)] + pub fn realm_authority( + &mut self, + realm_authority: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.realm_authority = Some(realm_authority); + self + } + /// `[optional account]` + /// Must be one of the realm governances when set + #[inline(always)] + pub fn new_realm_authority( + &mut self, + new_realm_authority: Option<&'b solana_account_info::AccountInfo<'a>>, + ) -> &mut Self { + self.instruction.new_realm_authority = new_realm_authority; + self + } + #[inline(always)] + pub fn action(&mut self, action: SetRealmAuthorityAction) -> &mut Self { + self.instruction.action = Some(action); + self + } + /// Add an additional account to the instruction. + #[inline(always)] + pub fn add_remaining_account( + &mut self, + account: &'b solana_account_info::AccountInfo<'a>, + is_writable: bool, + is_signer: bool, + ) -> &mut Self { + self.instruction + .__remaining_accounts + .push((account, is_writable, is_signer)); + self + } + /// Add additional accounts to the instruction. + /// + /// Each account is represented by a tuple of the `AccountInfo`, a `bool` indicating whether the account is writable or not, + /// and a `bool` indicating whether the account is a signer or not. + #[inline(always)] + pub fn add_remaining_accounts( + &mut self, + accounts: &[(&'b solana_account_info::AccountInfo<'a>, bool, bool)], + ) -> &mut Self { + self.instruction + .__remaining_accounts + .extend_from_slice(accounts); + self + } + #[inline(always)] + pub fn invoke(&self) -> solana_program_error::ProgramResult { + self.invoke_signed(&[]) + } + #[allow(clippy::clone_on_copy)] + #[allow(clippy::vec_init_then_push)] + pub fn invoke_signed(&self, signers_seeds: &[&[&[u8]]]) -> solana_program_error::ProgramResult { + let args = SetRealmAuthorityInstructionArgs { + action: self.instruction.action.clone().expect("action is not set"), + }; + let instruction = SetRealmAuthorityCpi { + __program: self.instruction.__program, + + realm_account: self + .instruction + .realm_account + .expect("realm_account is not set"), + + realm_authority: self + .instruction + .realm_authority + .expect("realm_authority is not set"), + + new_realm_authority: self.instruction.new_realm_authority, + __args: args, + }; + instruction.invoke_signed_with_remaining_accounts( + signers_seeds, + &self.instruction.__remaining_accounts, + ) + } +} + +#[derive(Clone, Debug)] +struct SetRealmAuthorityCpiBuilderInstruction<'a, 'b> { + __program: &'b solana_account_info::AccountInfo<'a>, + realm_account: Option<&'b solana_account_info::AccountInfo<'a>>, + realm_authority: Option<&'b solana_account_info::AccountInfo<'a>>, + new_realm_authority: Option<&'b solana_account_info::AccountInfo<'a>>, + action: Option, + /// Additional instruction accounts `(AccountInfo, is_writable, is_signer)`. + __remaining_accounts: Vec<(&'b solana_account_info::AccountInfo<'a>, bool, bool)>, +} diff --git a/e2e/governance/src/generated/instructions/set_realm_config.rs b/e2e/governance/src/generated/instructions/set_realm_config.rs new file mode 100644 index 0000000..ab27076 --- /dev/null +++ b/e2e/governance/src/generated/instructions/set_realm_config.rs @@ -0,0 +1,919 @@ +//! This code was AUTOGENERATED using the codama library. +//! Please DO NOT EDIT THIS FILE, instead use visitors +//! to add features, then rerun codama to update it. +//! +//! +//! + +use crate::generated::types::RealmConfigParams; +use borsh::BorshDeserialize; +use borsh::BorshSerialize; + +pub const SET_REALM_CONFIG_DISCRIMINATOR: u8 = 22; + +/// Accounts. +#[derive(Debug)] +pub struct SetRealmConfig { + pub realm_account: solana_pubkey::Pubkey, + + pub realm_authority: solana_pubkey::Pubkey, + /// Council Token Mint - optional. + /// Note: In the current version it's only possible to remove council mint (set it to None) + /// After setting council to None it won't be possible to withdraw the tokens from the Realm any longer. + /// If that's required then it must be done before executing this instruction + pub council_token_mint: Option, + /// Optional unless council is used. seeds=['governance', realm, council_mint] + pub council_token_holding_account: Option, + + pub system_program: solana_pubkey::Pubkey, + /// RealmConfig account. seeds=['realm-config', realm] + pub realm_config: solana_pubkey::Pubkey, + /// Optional Community Voter Weight Addin Program Id + pub community_voter_weight_addin_program_id: Option, + /// Optional Max Community Voter Weight Addin Program Id + pub max_community_voter_weight_addin_program_id: Option, + /// Optional Council Voter Weight Adding Program Id + pub council_voter_weight_addin_program_id: Option, + /// Optional Max Council Voter Weight Addin Program Id + pub max_council_voter_weight_addin_program_id: Option, + /// Optional Payer. Required if RealmConfig doesn't exist and needs to be created + pub payer: Option, +} + +impl SetRealmConfig { + pub fn instruction( + &self, + args: SetRealmConfigInstructionArgs, + ) -> solana_instruction::Instruction { + self.instruction_with_remaining_accounts(args, &[]) + } + #[allow(clippy::arithmetic_side_effects)] + #[allow(clippy::vec_init_then_push)] + pub fn instruction_with_remaining_accounts( + &self, + args: SetRealmConfigInstructionArgs, + remaining_accounts: &[solana_instruction::AccountMeta], + ) -> solana_instruction::Instruction { + let mut accounts = Vec::with_capacity(11 + remaining_accounts.len()); + accounts.push(solana_instruction::AccountMeta::new( + self.realm_account, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.realm_authority, + true, + )); + if let Some(council_token_mint) = self.council_token_mint { + accounts.push(solana_instruction::AccountMeta::new_readonly( + council_token_mint, + false, + )); + } else { + accounts.push(solana_instruction::AccountMeta::new_readonly( + crate::SPL_GOVERNANCE_ID, + false, + )); + } + if let Some(council_token_holding_account) = self.council_token_holding_account { + accounts.push(solana_instruction::AccountMeta::new( + council_token_holding_account, + false, + )); + } else { + accounts.push(solana_instruction::AccountMeta::new_readonly( + crate::SPL_GOVERNANCE_ID, + false, + )); + } + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.system_program, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + self.realm_config, + false, + )); + if let Some(community_voter_weight_addin_program_id) = + self.community_voter_weight_addin_program_id + { + accounts.push(solana_instruction::AccountMeta::new_readonly( + community_voter_weight_addin_program_id, + false, + )); + } else { + accounts.push(solana_instruction::AccountMeta::new_readonly( + crate::SPL_GOVERNANCE_ID, + false, + )); + } + if let Some(max_community_voter_weight_addin_program_id) = + self.max_community_voter_weight_addin_program_id + { + accounts.push(solana_instruction::AccountMeta::new_readonly( + max_community_voter_weight_addin_program_id, + false, + )); + } else { + accounts.push(solana_instruction::AccountMeta::new_readonly( + crate::SPL_GOVERNANCE_ID, + false, + )); + } + if let Some(council_voter_weight_addin_program_id) = + self.council_voter_weight_addin_program_id + { + accounts.push(solana_instruction::AccountMeta::new_readonly( + council_voter_weight_addin_program_id, + false, + )); + } else { + accounts.push(solana_instruction::AccountMeta::new_readonly( + crate::SPL_GOVERNANCE_ID, + false, + )); + } + if let Some(max_council_voter_weight_addin_program_id) = + self.max_council_voter_weight_addin_program_id + { + accounts.push(solana_instruction::AccountMeta::new_readonly( + max_council_voter_weight_addin_program_id, + false, + )); + } else { + accounts.push(solana_instruction::AccountMeta::new_readonly( + crate::SPL_GOVERNANCE_ID, + false, + )); + } + if let Some(payer) = self.payer { + accounts.push(solana_instruction::AccountMeta::new_readonly(payer, true)); + } else { + accounts.push(solana_instruction::AccountMeta::new_readonly( + crate::SPL_GOVERNANCE_ID, + false, + )); + } + accounts.extend_from_slice(remaining_accounts); + let mut data = SetRealmConfigInstructionData::new().try_to_vec().unwrap(); + let mut args = args.try_to_vec().unwrap(); + data.append(&mut args); + + solana_instruction::Instruction { + program_id: crate::SPL_GOVERNANCE_ID, + accounts, + data, + } + } +} + +#[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct SetRealmConfigInstructionData { + discriminator: u8, +} + +impl SetRealmConfigInstructionData { + pub fn new() -> Self { + Self { discriminator: 22 } + } + + pub(crate) fn try_to_vec(&self) -> Result, std::io::Error> { + borsh::to_vec(self) + } +} + +impl Default for SetRealmConfigInstructionData { + fn default() -> Self { + Self::new() + } +} + +#[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct SetRealmConfigInstructionArgs { + pub config_args: RealmConfigParams, +} + +impl SetRealmConfigInstructionArgs { + pub(crate) fn try_to_vec(&self) -> Result, std::io::Error> { + borsh::to_vec(self) + } +} + +/// Instruction builder for `SetRealmConfig`. +/// +/// ### Accounts: +/// +/// 0. `[writable]` realm_account +/// 1. `[signer]` realm_authority +/// 2. `[optional]` council_token_mint +/// 3. `[writable, optional]` council_token_holding_account +/// 4. `[optional]` system_program (default to `11111111111111111111111111111111`) +/// 5. `[writable]` realm_config +/// 6. `[optional]` community_voter_weight_addin_program_id +/// 7. `[optional]` max_community_voter_weight_addin_program_id +/// 8. `[optional]` council_voter_weight_addin_program_id +/// 9. `[optional]` max_council_voter_weight_addin_program_id +/// 10. `[signer, optional]` payer +#[derive(Clone, Debug, Default)] +pub struct SetRealmConfigBuilder { + realm_account: Option, + realm_authority: Option, + council_token_mint: Option, + council_token_holding_account: Option, + system_program: Option, + realm_config: Option, + community_voter_weight_addin_program_id: Option, + max_community_voter_weight_addin_program_id: Option, + council_voter_weight_addin_program_id: Option, + max_council_voter_weight_addin_program_id: Option, + payer: Option, + config_args: Option, + __remaining_accounts: Vec, +} + +impl SetRealmConfigBuilder { + pub fn new() -> Self { + Self::default() + } + #[inline(always)] + pub fn realm_account(&mut self, realm_account: solana_pubkey::Pubkey) -> &mut Self { + self.realm_account = Some(realm_account); + self + } + #[inline(always)] + pub fn realm_authority(&mut self, realm_authority: solana_pubkey::Pubkey) -> &mut Self { + self.realm_authority = Some(realm_authority); + self + } + /// `[optional account]` + /// Council Token Mint - optional. + /// Note: In the current version it's only possible to remove council mint (set it to None) + /// After setting council to None it won't be possible to withdraw the tokens from the Realm any longer. + /// If that's required then it must be done before executing this instruction + #[inline(always)] + pub fn council_token_mint( + &mut self, + council_token_mint: Option, + ) -> &mut Self { + self.council_token_mint = council_token_mint; + self + } + /// `[optional account]` + /// Optional unless council is used. seeds=['governance', realm, council_mint] + #[inline(always)] + pub fn council_token_holding_account( + &mut self, + council_token_holding_account: Option, + ) -> &mut Self { + self.council_token_holding_account = council_token_holding_account; + self + } + /// `[optional account, default to '11111111111111111111111111111111']` + #[inline(always)] + pub fn system_program(&mut self, system_program: solana_pubkey::Pubkey) -> &mut Self { + self.system_program = Some(system_program); + self + } + /// RealmConfig account. seeds=['realm-config', realm] + #[inline(always)] + pub fn realm_config(&mut self, realm_config: solana_pubkey::Pubkey) -> &mut Self { + self.realm_config = Some(realm_config); + self + } + /// `[optional account]` + /// Optional Community Voter Weight Addin Program Id + #[inline(always)] + pub fn community_voter_weight_addin_program_id( + &mut self, + community_voter_weight_addin_program_id: Option, + ) -> &mut Self { + self.community_voter_weight_addin_program_id = community_voter_weight_addin_program_id; + self + } + /// `[optional account]` + /// Optional Max Community Voter Weight Addin Program Id + #[inline(always)] + pub fn max_community_voter_weight_addin_program_id( + &mut self, + max_community_voter_weight_addin_program_id: Option, + ) -> &mut Self { + self.max_community_voter_weight_addin_program_id = + max_community_voter_weight_addin_program_id; + self + } + /// `[optional account]` + /// Optional Council Voter Weight Adding Program Id + #[inline(always)] + pub fn council_voter_weight_addin_program_id( + &mut self, + council_voter_weight_addin_program_id: Option, + ) -> &mut Self { + self.council_voter_weight_addin_program_id = council_voter_weight_addin_program_id; + self + } + /// `[optional account]` + /// Optional Max Council Voter Weight Addin Program Id + #[inline(always)] + pub fn max_council_voter_weight_addin_program_id( + &mut self, + max_council_voter_weight_addin_program_id: Option, + ) -> &mut Self { + self.max_council_voter_weight_addin_program_id = max_council_voter_weight_addin_program_id; + self + } + /// `[optional account]` + /// Optional Payer. Required if RealmConfig doesn't exist and needs to be created + #[inline(always)] + pub fn payer(&mut self, payer: Option) -> &mut Self { + self.payer = payer; + self + } + #[inline(always)] + pub fn config_args(&mut self, config_args: RealmConfigParams) -> &mut Self { + self.config_args = Some(config_args); + self + } + /// Add an additional account to the instruction. + #[inline(always)] + pub fn add_remaining_account(&mut self, account: solana_instruction::AccountMeta) -> &mut Self { + self.__remaining_accounts.push(account); + self + } + /// Add additional accounts to the instruction. + #[inline(always)] + pub fn add_remaining_accounts( + &mut self, + accounts: &[solana_instruction::AccountMeta], + ) -> &mut Self { + self.__remaining_accounts.extend_from_slice(accounts); + self + } + #[allow(clippy::clone_on_copy)] + pub fn instruction(&self) -> solana_instruction::Instruction { + let accounts = SetRealmConfig { + realm_account: self.realm_account.expect("realm_account is not set"), + realm_authority: self.realm_authority.expect("realm_authority is not set"), + council_token_mint: self.council_token_mint, + council_token_holding_account: self.council_token_holding_account, + system_program: self + .system_program + .unwrap_or(solana_pubkey::pubkey!("11111111111111111111111111111111")), + realm_config: self.realm_config.expect("realm_config is not set"), + community_voter_weight_addin_program_id: self.community_voter_weight_addin_program_id, + max_community_voter_weight_addin_program_id: self + .max_community_voter_weight_addin_program_id, + council_voter_weight_addin_program_id: self.council_voter_weight_addin_program_id, + max_council_voter_weight_addin_program_id: self + .max_council_voter_weight_addin_program_id, + payer: self.payer, + }; + let args = SetRealmConfigInstructionArgs { + config_args: self.config_args.clone().expect("config_args is not set"), + }; + + accounts.instruction_with_remaining_accounts(args, &self.__remaining_accounts) + } +} + +/// `set_realm_config` CPI accounts. +pub struct SetRealmConfigCpiAccounts<'a, 'b> { + pub realm_account: &'b solana_account_info::AccountInfo<'a>, + + pub realm_authority: &'b solana_account_info::AccountInfo<'a>, + /// Council Token Mint - optional. + /// Note: In the current version it's only possible to remove council mint (set it to None) + /// After setting council to None it won't be possible to withdraw the tokens from the Realm any longer. + /// If that's required then it must be done before executing this instruction + pub council_token_mint: Option<&'b solana_account_info::AccountInfo<'a>>, + /// Optional unless council is used. seeds=['governance', realm, council_mint] + pub council_token_holding_account: Option<&'b solana_account_info::AccountInfo<'a>>, + + pub system_program: &'b solana_account_info::AccountInfo<'a>, + /// RealmConfig account. seeds=['realm-config', realm] + pub realm_config: &'b solana_account_info::AccountInfo<'a>, + /// Optional Community Voter Weight Addin Program Id + pub community_voter_weight_addin_program_id: Option<&'b solana_account_info::AccountInfo<'a>>, + /// Optional Max Community Voter Weight Addin Program Id + pub max_community_voter_weight_addin_program_id: + Option<&'b solana_account_info::AccountInfo<'a>>, + /// Optional Council Voter Weight Adding Program Id + pub council_voter_weight_addin_program_id: Option<&'b solana_account_info::AccountInfo<'a>>, + /// Optional Max Council Voter Weight Addin Program Id + pub max_council_voter_weight_addin_program_id: Option<&'b solana_account_info::AccountInfo<'a>>, + /// Optional Payer. Required if RealmConfig doesn't exist and needs to be created + pub payer: Option<&'b solana_account_info::AccountInfo<'a>>, +} + +/// `set_realm_config` CPI instruction. +pub struct SetRealmConfigCpi<'a, 'b> { + /// The program to invoke. + pub __program: &'b solana_account_info::AccountInfo<'a>, + + pub realm_account: &'b solana_account_info::AccountInfo<'a>, + + pub realm_authority: &'b solana_account_info::AccountInfo<'a>, + /// Council Token Mint - optional. + /// Note: In the current version it's only possible to remove council mint (set it to None) + /// After setting council to None it won't be possible to withdraw the tokens from the Realm any longer. + /// If that's required then it must be done before executing this instruction + pub council_token_mint: Option<&'b solana_account_info::AccountInfo<'a>>, + /// Optional unless council is used. seeds=['governance', realm, council_mint] + pub council_token_holding_account: Option<&'b solana_account_info::AccountInfo<'a>>, + + pub system_program: &'b solana_account_info::AccountInfo<'a>, + /// RealmConfig account. seeds=['realm-config', realm] + pub realm_config: &'b solana_account_info::AccountInfo<'a>, + /// Optional Community Voter Weight Addin Program Id + pub community_voter_weight_addin_program_id: Option<&'b solana_account_info::AccountInfo<'a>>, + /// Optional Max Community Voter Weight Addin Program Id + pub max_community_voter_weight_addin_program_id: + Option<&'b solana_account_info::AccountInfo<'a>>, + /// Optional Council Voter Weight Adding Program Id + pub council_voter_weight_addin_program_id: Option<&'b solana_account_info::AccountInfo<'a>>, + /// Optional Max Council Voter Weight Addin Program Id + pub max_council_voter_weight_addin_program_id: Option<&'b solana_account_info::AccountInfo<'a>>, + /// Optional Payer. Required if RealmConfig doesn't exist and needs to be created + pub payer: Option<&'b solana_account_info::AccountInfo<'a>>, + /// The arguments for the instruction. + pub __args: SetRealmConfigInstructionArgs, +} + +impl<'a, 'b> SetRealmConfigCpi<'a, 'b> { + pub fn new( + program: &'b solana_account_info::AccountInfo<'a>, + accounts: SetRealmConfigCpiAccounts<'a, 'b>, + args: SetRealmConfigInstructionArgs, + ) -> Self { + Self { + __program: program, + realm_account: accounts.realm_account, + realm_authority: accounts.realm_authority, + council_token_mint: accounts.council_token_mint, + council_token_holding_account: accounts.council_token_holding_account, + system_program: accounts.system_program, + realm_config: accounts.realm_config, + community_voter_weight_addin_program_id: accounts + .community_voter_weight_addin_program_id, + max_community_voter_weight_addin_program_id: accounts + .max_community_voter_weight_addin_program_id, + council_voter_weight_addin_program_id: accounts.council_voter_weight_addin_program_id, + max_council_voter_weight_addin_program_id: accounts + .max_council_voter_weight_addin_program_id, + payer: accounts.payer, + __args: args, + } + } + #[inline(always)] + pub fn invoke(&self) -> solana_program_error::ProgramResult { + self.invoke_signed_with_remaining_accounts(&[], &[]) + } + #[inline(always)] + pub fn invoke_with_remaining_accounts( + &self, + remaining_accounts: &[(&'b solana_account_info::AccountInfo<'a>, bool, bool)], + ) -> solana_program_error::ProgramResult { + self.invoke_signed_with_remaining_accounts(&[], remaining_accounts) + } + #[inline(always)] + pub fn invoke_signed(&self, signers_seeds: &[&[&[u8]]]) -> solana_program_error::ProgramResult { + self.invoke_signed_with_remaining_accounts(signers_seeds, &[]) + } + #[allow(clippy::arithmetic_side_effects)] + #[allow(clippy::clone_on_copy)] + #[allow(clippy::vec_init_then_push)] + pub fn invoke_signed_with_remaining_accounts( + &self, + signers_seeds: &[&[&[u8]]], + remaining_accounts: &[(&'b solana_account_info::AccountInfo<'a>, bool, bool)], + ) -> solana_program_error::ProgramResult { + let mut accounts = Vec::with_capacity(11 + remaining_accounts.len()); + accounts.push(solana_instruction::AccountMeta::new( + *self.realm_account.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.realm_authority.key, + true, + )); + if let Some(council_token_mint) = self.council_token_mint { + accounts.push(solana_instruction::AccountMeta::new_readonly( + *council_token_mint.key, + false, + )); + } else { + accounts.push(solana_instruction::AccountMeta::new_readonly( + crate::SPL_GOVERNANCE_ID, + false, + )); + } + if let Some(council_token_holding_account) = self.council_token_holding_account { + accounts.push(solana_instruction::AccountMeta::new( + *council_token_holding_account.key, + false, + )); + } else { + accounts.push(solana_instruction::AccountMeta::new_readonly( + crate::SPL_GOVERNANCE_ID, + false, + )); + } + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.system_program.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + *self.realm_config.key, + false, + )); + if let Some(community_voter_weight_addin_program_id) = + self.community_voter_weight_addin_program_id + { + accounts.push(solana_instruction::AccountMeta::new_readonly( + *community_voter_weight_addin_program_id.key, + false, + )); + } else { + accounts.push(solana_instruction::AccountMeta::new_readonly( + crate::SPL_GOVERNANCE_ID, + false, + )); + } + if let Some(max_community_voter_weight_addin_program_id) = + self.max_community_voter_weight_addin_program_id + { + accounts.push(solana_instruction::AccountMeta::new_readonly( + *max_community_voter_weight_addin_program_id.key, + false, + )); + } else { + accounts.push(solana_instruction::AccountMeta::new_readonly( + crate::SPL_GOVERNANCE_ID, + false, + )); + } + if let Some(council_voter_weight_addin_program_id) = + self.council_voter_weight_addin_program_id + { + accounts.push(solana_instruction::AccountMeta::new_readonly( + *council_voter_weight_addin_program_id.key, + false, + )); + } else { + accounts.push(solana_instruction::AccountMeta::new_readonly( + crate::SPL_GOVERNANCE_ID, + false, + )); + } + if let Some(max_council_voter_weight_addin_program_id) = + self.max_council_voter_weight_addin_program_id + { + accounts.push(solana_instruction::AccountMeta::new_readonly( + *max_council_voter_weight_addin_program_id.key, + false, + )); + } else { + accounts.push(solana_instruction::AccountMeta::new_readonly( + crate::SPL_GOVERNANCE_ID, + false, + )); + } + if let Some(payer) = self.payer { + accounts.push(solana_instruction::AccountMeta::new_readonly( + *payer.key, true, + )); + } else { + accounts.push(solana_instruction::AccountMeta::new_readonly( + crate::SPL_GOVERNANCE_ID, + false, + )); + } + remaining_accounts.iter().for_each(|remaining_account| { + accounts.push(solana_instruction::AccountMeta { + pubkey: *remaining_account.0.key, + is_signer: remaining_account.1, + is_writable: remaining_account.2, + }) + }); + let mut data = SetRealmConfigInstructionData::new().try_to_vec().unwrap(); + let mut args = self.__args.try_to_vec().unwrap(); + data.append(&mut args); + + let instruction = solana_instruction::Instruction { + program_id: crate::SPL_GOVERNANCE_ID, + accounts, + data, + }; + let mut account_infos = Vec::with_capacity(12 + remaining_accounts.len()); + account_infos.push(self.__program.clone()); + account_infos.push(self.realm_account.clone()); + account_infos.push(self.realm_authority.clone()); + if let Some(council_token_mint) = self.council_token_mint { + account_infos.push(council_token_mint.clone()); + } + if let Some(council_token_holding_account) = self.council_token_holding_account { + account_infos.push(council_token_holding_account.clone()); + } + account_infos.push(self.system_program.clone()); + account_infos.push(self.realm_config.clone()); + if let Some(community_voter_weight_addin_program_id) = + self.community_voter_weight_addin_program_id + { + account_infos.push(community_voter_weight_addin_program_id.clone()); + } + if let Some(max_community_voter_weight_addin_program_id) = + self.max_community_voter_weight_addin_program_id + { + account_infos.push(max_community_voter_weight_addin_program_id.clone()); + } + if let Some(council_voter_weight_addin_program_id) = + self.council_voter_weight_addin_program_id + { + account_infos.push(council_voter_weight_addin_program_id.clone()); + } + if let Some(max_council_voter_weight_addin_program_id) = + self.max_council_voter_weight_addin_program_id + { + account_infos.push(max_council_voter_weight_addin_program_id.clone()); + } + if let Some(payer) = self.payer { + account_infos.push(payer.clone()); + } + remaining_accounts + .iter() + .for_each(|remaining_account| account_infos.push(remaining_account.0.clone())); + + if signers_seeds.is_empty() { + solana_cpi::invoke(&instruction, &account_infos) + } else { + solana_cpi::invoke_signed(&instruction, &account_infos, signers_seeds) + } + } +} + +/// Instruction builder for `SetRealmConfig` via CPI. +/// +/// ### Accounts: +/// +/// 0. `[writable]` realm_account +/// 1. `[signer]` realm_authority +/// 2. `[optional]` council_token_mint +/// 3. `[writable, optional]` council_token_holding_account +/// 4. `[]` system_program +/// 5. `[writable]` realm_config +/// 6. `[optional]` community_voter_weight_addin_program_id +/// 7. `[optional]` max_community_voter_weight_addin_program_id +/// 8. `[optional]` council_voter_weight_addin_program_id +/// 9. `[optional]` max_council_voter_weight_addin_program_id +/// 10. `[signer, optional]` payer +#[derive(Clone, Debug)] +pub struct SetRealmConfigCpiBuilder<'a, 'b> { + instruction: Box>, +} + +impl<'a, 'b> SetRealmConfigCpiBuilder<'a, 'b> { + pub fn new(program: &'b solana_account_info::AccountInfo<'a>) -> Self { + let instruction = Box::new(SetRealmConfigCpiBuilderInstruction { + __program: program, + realm_account: None, + realm_authority: None, + council_token_mint: None, + council_token_holding_account: None, + system_program: None, + realm_config: None, + community_voter_weight_addin_program_id: None, + max_community_voter_weight_addin_program_id: None, + council_voter_weight_addin_program_id: None, + max_council_voter_weight_addin_program_id: None, + payer: None, + config_args: None, + __remaining_accounts: Vec::new(), + }); + Self { instruction } + } + #[inline(always)] + pub fn realm_account( + &mut self, + realm_account: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.realm_account = Some(realm_account); + self + } + #[inline(always)] + pub fn realm_authority( + &mut self, + realm_authority: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.realm_authority = Some(realm_authority); + self + } + /// `[optional account]` + /// Council Token Mint - optional. + /// Note: In the current version it's only possible to remove council mint (set it to None) + /// After setting council to None it won't be possible to withdraw the tokens from the Realm any longer. + /// If that's required then it must be done before executing this instruction + #[inline(always)] + pub fn council_token_mint( + &mut self, + council_token_mint: Option<&'b solana_account_info::AccountInfo<'a>>, + ) -> &mut Self { + self.instruction.council_token_mint = council_token_mint; + self + } + /// `[optional account]` + /// Optional unless council is used. seeds=['governance', realm, council_mint] + #[inline(always)] + pub fn council_token_holding_account( + &mut self, + council_token_holding_account: Option<&'b solana_account_info::AccountInfo<'a>>, + ) -> &mut Self { + self.instruction.council_token_holding_account = council_token_holding_account; + self + } + #[inline(always)] + pub fn system_program( + &mut self, + system_program: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.system_program = Some(system_program); + self + } + /// RealmConfig account. seeds=['realm-config', realm] + #[inline(always)] + pub fn realm_config( + &mut self, + realm_config: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.realm_config = Some(realm_config); + self + } + /// `[optional account]` + /// Optional Community Voter Weight Addin Program Id + #[inline(always)] + pub fn community_voter_weight_addin_program_id( + &mut self, + community_voter_weight_addin_program_id: Option<&'b solana_account_info::AccountInfo<'a>>, + ) -> &mut Self { + self.instruction.community_voter_weight_addin_program_id = + community_voter_weight_addin_program_id; + self + } + /// `[optional account]` + /// Optional Max Community Voter Weight Addin Program Id + #[inline(always)] + pub fn max_community_voter_weight_addin_program_id( + &mut self, + max_community_voter_weight_addin_program_id: Option< + &'b solana_account_info::AccountInfo<'a>, + >, + ) -> &mut Self { + self.instruction.max_community_voter_weight_addin_program_id = + max_community_voter_weight_addin_program_id; + self + } + /// `[optional account]` + /// Optional Council Voter Weight Adding Program Id + #[inline(always)] + pub fn council_voter_weight_addin_program_id( + &mut self, + council_voter_weight_addin_program_id: Option<&'b solana_account_info::AccountInfo<'a>>, + ) -> &mut Self { + self.instruction.council_voter_weight_addin_program_id = + council_voter_weight_addin_program_id; + self + } + /// `[optional account]` + /// Optional Max Council Voter Weight Addin Program Id + #[inline(always)] + pub fn max_council_voter_weight_addin_program_id( + &mut self, + max_council_voter_weight_addin_program_id: Option<&'b solana_account_info::AccountInfo<'a>>, + ) -> &mut Self { + self.instruction.max_council_voter_weight_addin_program_id = + max_council_voter_weight_addin_program_id; + self + } + /// `[optional account]` + /// Optional Payer. Required if RealmConfig doesn't exist and needs to be created + #[inline(always)] + pub fn payer(&mut self, payer: Option<&'b solana_account_info::AccountInfo<'a>>) -> &mut Self { + self.instruction.payer = payer; + self + } + #[inline(always)] + pub fn config_args(&mut self, config_args: RealmConfigParams) -> &mut Self { + self.instruction.config_args = Some(config_args); + self + } + /// Add an additional account to the instruction. + #[inline(always)] + pub fn add_remaining_account( + &mut self, + account: &'b solana_account_info::AccountInfo<'a>, + is_writable: bool, + is_signer: bool, + ) -> &mut Self { + self.instruction + .__remaining_accounts + .push((account, is_writable, is_signer)); + self + } + /// Add additional accounts to the instruction. + /// + /// Each account is represented by a tuple of the `AccountInfo`, a `bool` indicating whether the account is writable or not, + /// and a `bool` indicating whether the account is a signer or not. + #[inline(always)] + pub fn add_remaining_accounts( + &mut self, + accounts: &[(&'b solana_account_info::AccountInfo<'a>, bool, bool)], + ) -> &mut Self { + self.instruction + .__remaining_accounts + .extend_from_slice(accounts); + self + } + #[inline(always)] + pub fn invoke(&self) -> solana_program_error::ProgramResult { + self.invoke_signed(&[]) + } + #[allow(clippy::clone_on_copy)] + #[allow(clippy::vec_init_then_push)] + pub fn invoke_signed(&self, signers_seeds: &[&[&[u8]]]) -> solana_program_error::ProgramResult { + let args = SetRealmConfigInstructionArgs { + config_args: self + .instruction + .config_args + .clone() + .expect("config_args is not set"), + }; + let instruction = SetRealmConfigCpi { + __program: self.instruction.__program, + + realm_account: self + .instruction + .realm_account + .expect("realm_account is not set"), + + realm_authority: self + .instruction + .realm_authority + .expect("realm_authority is not set"), + + council_token_mint: self.instruction.council_token_mint, + + council_token_holding_account: self.instruction.council_token_holding_account, + + system_program: self + .instruction + .system_program + .expect("system_program is not set"), + + realm_config: self + .instruction + .realm_config + .expect("realm_config is not set"), + + community_voter_weight_addin_program_id: self + .instruction + .community_voter_weight_addin_program_id, + + max_community_voter_weight_addin_program_id: self + .instruction + .max_community_voter_weight_addin_program_id, + + council_voter_weight_addin_program_id: self + .instruction + .council_voter_weight_addin_program_id, + + max_council_voter_weight_addin_program_id: self + .instruction + .max_council_voter_weight_addin_program_id, + + payer: self.instruction.payer, + __args: args, + }; + instruction.invoke_signed_with_remaining_accounts( + signers_seeds, + &self.instruction.__remaining_accounts, + ) + } +} + +#[derive(Clone, Debug)] +struct SetRealmConfigCpiBuilderInstruction<'a, 'b> { + __program: &'b solana_account_info::AccountInfo<'a>, + realm_account: Option<&'b solana_account_info::AccountInfo<'a>>, + realm_authority: Option<&'b solana_account_info::AccountInfo<'a>>, + council_token_mint: Option<&'b solana_account_info::AccountInfo<'a>>, + council_token_holding_account: Option<&'b solana_account_info::AccountInfo<'a>>, + system_program: Option<&'b solana_account_info::AccountInfo<'a>>, + realm_config: Option<&'b solana_account_info::AccountInfo<'a>>, + community_voter_weight_addin_program_id: Option<&'b solana_account_info::AccountInfo<'a>>, + max_community_voter_weight_addin_program_id: Option<&'b solana_account_info::AccountInfo<'a>>, + council_voter_weight_addin_program_id: Option<&'b solana_account_info::AccountInfo<'a>>, + max_council_voter_weight_addin_program_id: Option<&'b solana_account_info::AccountInfo<'a>>, + payer: Option<&'b solana_account_info::AccountInfo<'a>>, + config_args: Option, + /// Additional instruction accounts `(AccountInfo, is_writable, is_signer)`. + __remaining_accounts: Vec<(&'b solana_account_info::AccountInfo<'a>, bool, bool)>, +} diff --git a/e2e/governance/src/generated/instructions/sign_off_proposal.rs b/e2e/governance/src/generated/instructions/sign_off_proposal.rs new file mode 100644 index 0000000..436fa66 --- /dev/null +++ b/e2e/governance/src/generated/instructions/sign_off_proposal.rs @@ -0,0 +1,454 @@ +//! This code was AUTOGENERATED using the codama library. +//! Please DO NOT EDIT THIS FILE, instead use visitors +//! to add features, then rerun codama to update it. +//! +//! +//! + +use borsh::BorshDeserialize; +use borsh::BorshSerialize; + +pub const SIGN_OFF_PROPOSAL_DISCRIMINATOR: u8 = 12; + +/// Accounts. +#[derive(Debug)] +pub struct SignOffProposal { + pub realm_account: solana_pubkey::Pubkey, + + pub governance_account: solana_pubkey::Pubkey, + + pub proposal_account: solana_pubkey::Pubkey, + /// Signatory account signing off the Proposal. + /// Or Proposal owner if the owner hasn't appointed any signatories + pub signatory_account: solana_pubkey::Pubkey, + /// TokenOwnerRecord for the Proposal owner, required when the owner signs off the Proposal. + /// Or `[writable]` SignatoryRecord account, required when non owner signs off the Proposal + pub token_owner_record: solana_pubkey::Pubkey, +} + +impl SignOffProposal { + pub fn instruction(&self) -> solana_instruction::Instruction { + self.instruction_with_remaining_accounts(&[]) + } + #[allow(clippy::arithmetic_side_effects)] + #[allow(clippy::vec_init_then_push)] + pub fn instruction_with_remaining_accounts( + &self, + remaining_accounts: &[solana_instruction::AccountMeta], + ) -> solana_instruction::Instruction { + let mut accounts = Vec::with_capacity(5 + remaining_accounts.len()); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.realm_account, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.governance_account, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + self.proposal_account, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.signatory_account, + true, + )); + accounts.push(solana_instruction::AccountMeta::new( + self.token_owner_record, + false, + )); + accounts.extend_from_slice(remaining_accounts); + let data = SignOffProposalInstructionData::new().try_to_vec().unwrap(); + + solana_instruction::Instruction { + program_id: crate::SPL_GOVERNANCE_ID, + accounts, + data, + } + } +} + +#[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct SignOffProposalInstructionData { + discriminator: u8, +} + +impl SignOffProposalInstructionData { + pub fn new() -> Self { + Self { discriminator: 12 } + } + + pub(crate) fn try_to_vec(&self) -> Result, std::io::Error> { + borsh::to_vec(self) + } +} + +impl Default for SignOffProposalInstructionData { + fn default() -> Self { + Self::new() + } +} + +/// Instruction builder for `SignOffProposal`. +/// +/// ### Accounts: +/// +/// 0. `[]` realm_account +/// 1. `[]` governance_account +/// 2. `[writable]` proposal_account +/// 3. `[signer]` signatory_account +/// 4. `[writable]` token_owner_record +#[derive(Clone, Debug, Default)] +pub struct SignOffProposalBuilder { + realm_account: Option, + governance_account: Option, + proposal_account: Option, + signatory_account: Option, + token_owner_record: Option, + __remaining_accounts: Vec, +} + +impl SignOffProposalBuilder { + pub fn new() -> Self { + Self::default() + } + #[inline(always)] + pub fn realm_account(&mut self, realm_account: solana_pubkey::Pubkey) -> &mut Self { + self.realm_account = Some(realm_account); + self + } + #[inline(always)] + pub fn governance_account(&mut self, governance_account: solana_pubkey::Pubkey) -> &mut Self { + self.governance_account = Some(governance_account); + self + } + #[inline(always)] + pub fn proposal_account(&mut self, proposal_account: solana_pubkey::Pubkey) -> &mut Self { + self.proposal_account = Some(proposal_account); + self + } + /// Signatory account signing off the Proposal. + /// Or Proposal owner if the owner hasn't appointed any signatories + #[inline(always)] + pub fn signatory_account(&mut self, signatory_account: solana_pubkey::Pubkey) -> &mut Self { + self.signatory_account = Some(signatory_account); + self + } + /// TokenOwnerRecord for the Proposal owner, required when the owner signs off the Proposal. + /// Or `[writable]` SignatoryRecord account, required when non owner signs off the Proposal + #[inline(always)] + pub fn token_owner_record(&mut self, token_owner_record: solana_pubkey::Pubkey) -> &mut Self { + self.token_owner_record = Some(token_owner_record); + self + } + /// Add an additional account to the instruction. + #[inline(always)] + pub fn add_remaining_account(&mut self, account: solana_instruction::AccountMeta) -> &mut Self { + self.__remaining_accounts.push(account); + self + } + /// Add additional accounts to the instruction. + #[inline(always)] + pub fn add_remaining_accounts( + &mut self, + accounts: &[solana_instruction::AccountMeta], + ) -> &mut Self { + self.__remaining_accounts.extend_from_slice(accounts); + self + } + #[allow(clippy::clone_on_copy)] + pub fn instruction(&self) -> solana_instruction::Instruction { + let accounts = SignOffProposal { + realm_account: self.realm_account.expect("realm_account is not set"), + governance_account: self + .governance_account + .expect("governance_account is not set"), + proposal_account: self.proposal_account.expect("proposal_account is not set"), + signatory_account: self + .signatory_account + .expect("signatory_account is not set"), + token_owner_record: self + .token_owner_record + .expect("token_owner_record is not set"), + }; + + accounts.instruction_with_remaining_accounts(&self.__remaining_accounts) + } +} + +/// `sign_off_proposal` CPI accounts. +pub struct SignOffProposalCpiAccounts<'a, 'b> { + pub realm_account: &'b solana_account_info::AccountInfo<'a>, + + pub governance_account: &'b solana_account_info::AccountInfo<'a>, + + pub proposal_account: &'b solana_account_info::AccountInfo<'a>, + /// Signatory account signing off the Proposal. + /// Or Proposal owner if the owner hasn't appointed any signatories + pub signatory_account: &'b solana_account_info::AccountInfo<'a>, + /// TokenOwnerRecord for the Proposal owner, required when the owner signs off the Proposal. + /// Or `[writable]` SignatoryRecord account, required when non owner signs off the Proposal + pub token_owner_record: &'b solana_account_info::AccountInfo<'a>, +} + +/// `sign_off_proposal` CPI instruction. +pub struct SignOffProposalCpi<'a, 'b> { + /// The program to invoke. + pub __program: &'b solana_account_info::AccountInfo<'a>, + + pub realm_account: &'b solana_account_info::AccountInfo<'a>, + + pub governance_account: &'b solana_account_info::AccountInfo<'a>, + + pub proposal_account: &'b solana_account_info::AccountInfo<'a>, + /// Signatory account signing off the Proposal. + /// Or Proposal owner if the owner hasn't appointed any signatories + pub signatory_account: &'b solana_account_info::AccountInfo<'a>, + /// TokenOwnerRecord for the Proposal owner, required when the owner signs off the Proposal. + /// Or `[writable]` SignatoryRecord account, required when non owner signs off the Proposal + pub token_owner_record: &'b solana_account_info::AccountInfo<'a>, +} + +impl<'a, 'b> SignOffProposalCpi<'a, 'b> { + pub fn new( + program: &'b solana_account_info::AccountInfo<'a>, + accounts: SignOffProposalCpiAccounts<'a, 'b>, + ) -> Self { + Self { + __program: program, + realm_account: accounts.realm_account, + governance_account: accounts.governance_account, + proposal_account: accounts.proposal_account, + signatory_account: accounts.signatory_account, + token_owner_record: accounts.token_owner_record, + } + } + #[inline(always)] + pub fn invoke(&self) -> solana_program_error::ProgramResult { + self.invoke_signed_with_remaining_accounts(&[], &[]) + } + #[inline(always)] + pub fn invoke_with_remaining_accounts( + &self, + remaining_accounts: &[(&'b solana_account_info::AccountInfo<'a>, bool, bool)], + ) -> solana_program_error::ProgramResult { + self.invoke_signed_with_remaining_accounts(&[], remaining_accounts) + } + #[inline(always)] + pub fn invoke_signed(&self, signers_seeds: &[&[&[u8]]]) -> solana_program_error::ProgramResult { + self.invoke_signed_with_remaining_accounts(signers_seeds, &[]) + } + #[allow(clippy::arithmetic_side_effects)] + #[allow(clippy::clone_on_copy)] + #[allow(clippy::vec_init_then_push)] + pub fn invoke_signed_with_remaining_accounts( + &self, + signers_seeds: &[&[&[u8]]], + remaining_accounts: &[(&'b solana_account_info::AccountInfo<'a>, bool, bool)], + ) -> solana_program_error::ProgramResult { + let mut accounts = Vec::with_capacity(5 + remaining_accounts.len()); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.realm_account.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.governance_account.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + *self.proposal_account.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.signatory_account.key, + true, + )); + accounts.push(solana_instruction::AccountMeta::new( + *self.token_owner_record.key, + false, + )); + remaining_accounts.iter().for_each(|remaining_account| { + accounts.push(solana_instruction::AccountMeta { + pubkey: *remaining_account.0.key, + is_signer: remaining_account.1, + is_writable: remaining_account.2, + }) + }); + let data = SignOffProposalInstructionData::new().try_to_vec().unwrap(); + + let instruction = solana_instruction::Instruction { + program_id: crate::SPL_GOVERNANCE_ID, + accounts, + data, + }; + let mut account_infos = Vec::with_capacity(6 + remaining_accounts.len()); + account_infos.push(self.__program.clone()); + account_infos.push(self.realm_account.clone()); + account_infos.push(self.governance_account.clone()); + account_infos.push(self.proposal_account.clone()); + account_infos.push(self.signatory_account.clone()); + account_infos.push(self.token_owner_record.clone()); + remaining_accounts + .iter() + .for_each(|remaining_account| account_infos.push(remaining_account.0.clone())); + + if signers_seeds.is_empty() { + solana_cpi::invoke(&instruction, &account_infos) + } else { + solana_cpi::invoke_signed(&instruction, &account_infos, signers_seeds) + } + } +} + +/// Instruction builder for `SignOffProposal` via CPI. +/// +/// ### Accounts: +/// +/// 0. `[]` realm_account +/// 1. `[]` governance_account +/// 2. `[writable]` proposal_account +/// 3. `[signer]` signatory_account +/// 4. `[writable]` token_owner_record +#[derive(Clone, Debug)] +pub struct SignOffProposalCpiBuilder<'a, 'b> { + instruction: Box>, +} + +impl<'a, 'b> SignOffProposalCpiBuilder<'a, 'b> { + pub fn new(program: &'b solana_account_info::AccountInfo<'a>) -> Self { + let instruction = Box::new(SignOffProposalCpiBuilderInstruction { + __program: program, + realm_account: None, + governance_account: None, + proposal_account: None, + signatory_account: None, + token_owner_record: None, + __remaining_accounts: Vec::new(), + }); + Self { instruction } + } + #[inline(always)] + pub fn realm_account( + &mut self, + realm_account: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.realm_account = Some(realm_account); + self + } + #[inline(always)] + pub fn governance_account( + &mut self, + governance_account: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.governance_account = Some(governance_account); + self + } + #[inline(always)] + pub fn proposal_account( + &mut self, + proposal_account: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.proposal_account = Some(proposal_account); + self + } + /// Signatory account signing off the Proposal. + /// Or Proposal owner if the owner hasn't appointed any signatories + #[inline(always)] + pub fn signatory_account( + &mut self, + signatory_account: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.signatory_account = Some(signatory_account); + self + } + /// TokenOwnerRecord for the Proposal owner, required when the owner signs off the Proposal. + /// Or `[writable]` SignatoryRecord account, required when non owner signs off the Proposal + #[inline(always)] + pub fn token_owner_record( + &mut self, + token_owner_record: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.token_owner_record = Some(token_owner_record); + self + } + /// Add an additional account to the instruction. + #[inline(always)] + pub fn add_remaining_account( + &mut self, + account: &'b solana_account_info::AccountInfo<'a>, + is_writable: bool, + is_signer: bool, + ) -> &mut Self { + self.instruction + .__remaining_accounts + .push((account, is_writable, is_signer)); + self + } + /// Add additional accounts to the instruction. + /// + /// Each account is represented by a tuple of the `AccountInfo`, a `bool` indicating whether the account is writable or not, + /// and a `bool` indicating whether the account is a signer or not. + #[inline(always)] + pub fn add_remaining_accounts( + &mut self, + accounts: &[(&'b solana_account_info::AccountInfo<'a>, bool, bool)], + ) -> &mut Self { + self.instruction + .__remaining_accounts + .extend_from_slice(accounts); + self + } + #[inline(always)] + pub fn invoke(&self) -> solana_program_error::ProgramResult { + self.invoke_signed(&[]) + } + #[allow(clippy::clone_on_copy)] + #[allow(clippy::vec_init_then_push)] + pub fn invoke_signed(&self, signers_seeds: &[&[&[u8]]]) -> solana_program_error::ProgramResult { + let instruction = SignOffProposalCpi { + __program: self.instruction.__program, + + realm_account: self + .instruction + .realm_account + .expect("realm_account is not set"), + + governance_account: self + .instruction + .governance_account + .expect("governance_account is not set"), + + proposal_account: self + .instruction + .proposal_account + .expect("proposal_account is not set"), + + signatory_account: self + .instruction + .signatory_account + .expect("signatory_account is not set"), + + token_owner_record: self + .instruction + .token_owner_record + .expect("token_owner_record is not set"), + }; + instruction.invoke_signed_with_remaining_accounts( + signers_seeds, + &self.instruction.__remaining_accounts, + ) + } +} + +#[derive(Clone, Debug)] +struct SignOffProposalCpiBuilderInstruction<'a, 'b> { + __program: &'b solana_account_info::AccountInfo<'a>, + realm_account: Option<&'b solana_account_info::AccountInfo<'a>>, + governance_account: Option<&'b solana_account_info::AccountInfo<'a>>, + proposal_account: Option<&'b solana_account_info::AccountInfo<'a>>, + signatory_account: Option<&'b solana_account_info::AccountInfo<'a>>, + token_owner_record: Option<&'b solana_account_info::AccountInfo<'a>>, + /// Additional instruction accounts `(AccountInfo, is_writable, is_signer)`. + __remaining_accounts: Vec<(&'b solana_account_info::AccountInfo<'a>, bool, bool)>, +} diff --git a/e2e/governance/src/generated/instructions/update_program_metadata.rs b/e2e/governance/src/generated/instructions/update_program_metadata.rs new file mode 100644 index 0000000..fbb3cfa --- /dev/null +++ b/e2e/governance/src/generated/instructions/update_program_metadata.rs @@ -0,0 +1,363 @@ +//! This code was AUTOGENERATED using the codama library. +//! Please DO NOT EDIT THIS FILE, instead use visitors +//! to add features, then rerun codama to update it. +//! +//! +//! + +use borsh::BorshDeserialize; +use borsh::BorshSerialize; + +pub const UPDATE_PROGRAM_METADATA_DISCRIMINATOR: u8 = 24; + +/// Accounts. +#[derive(Debug)] +pub struct UpdateProgramMetadata { + /// seeds=['metadata'] + pub program_metadata_account: solana_pubkey::Pubkey, + + pub payer: solana_pubkey::Pubkey, + + pub system_program: solana_pubkey::Pubkey, +} + +impl UpdateProgramMetadata { + pub fn instruction(&self) -> solana_instruction::Instruction { + self.instruction_with_remaining_accounts(&[]) + } + #[allow(clippy::arithmetic_side_effects)] + #[allow(clippy::vec_init_then_push)] + pub fn instruction_with_remaining_accounts( + &self, + remaining_accounts: &[solana_instruction::AccountMeta], + ) -> solana_instruction::Instruction { + let mut accounts = Vec::with_capacity(3 + remaining_accounts.len()); + accounts.push(solana_instruction::AccountMeta::new( + self.program_metadata_account, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.payer, true, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.system_program, + false, + )); + accounts.extend_from_slice(remaining_accounts); + let data = UpdateProgramMetadataInstructionData::new() + .try_to_vec() + .unwrap(); + + solana_instruction::Instruction { + program_id: crate::SPL_GOVERNANCE_ID, + accounts, + data, + } + } +} + +#[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct UpdateProgramMetadataInstructionData { + discriminator: u8, +} + +impl UpdateProgramMetadataInstructionData { + pub fn new() -> Self { + Self { discriminator: 24 } + } + + pub(crate) fn try_to_vec(&self) -> Result, std::io::Error> { + borsh::to_vec(self) + } +} + +impl Default for UpdateProgramMetadataInstructionData { + fn default() -> Self { + Self::new() + } +} + +/// Instruction builder for `UpdateProgramMetadata`. +/// +/// ### Accounts: +/// +/// 0. `[writable]` program_metadata_account +/// 1. `[signer]` payer +/// 2. `[optional]` system_program (default to `11111111111111111111111111111111`) +#[derive(Clone, Debug, Default)] +pub struct UpdateProgramMetadataBuilder { + program_metadata_account: Option, + payer: Option, + system_program: Option, + __remaining_accounts: Vec, +} + +impl UpdateProgramMetadataBuilder { + pub fn new() -> Self { + Self::default() + } + /// seeds=['metadata'] + #[inline(always)] + pub fn program_metadata_account( + &mut self, + program_metadata_account: solana_pubkey::Pubkey, + ) -> &mut Self { + self.program_metadata_account = Some(program_metadata_account); + self + } + #[inline(always)] + pub fn payer(&mut self, payer: solana_pubkey::Pubkey) -> &mut Self { + self.payer = Some(payer); + self + } + /// `[optional account, default to '11111111111111111111111111111111']` + #[inline(always)] + pub fn system_program(&mut self, system_program: solana_pubkey::Pubkey) -> &mut Self { + self.system_program = Some(system_program); + self + } + /// Add an additional account to the instruction. + #[inline(always)] + pub fn add_remaining_account(&mut self, account: solana_instruction::AccountMeta) -> &mut Self { + self.__remaining_accounts.push(account); + self + } + /// Add additional accounts to the instruction. + #[inline(always)] + pub fn add_remaining_accounts( + &mut self, + accounts: &[solana_instruction::AccountMeta], + ) -> &mut Self { + self.__remaining_accounts.extend_from_slice(accounts); + self + } + #[allow(clippy::clone_on_copy)] + pub fn instruction(&self) -> solana_instruction::Instruction { + let accounts = UpdateProgramMetadata { + program_metadata_account: self + .program_metadata_account + .expect("program_metadata_account is not set"), + payer: self.payer.expect("payer is not set"), + system_program: self + .system_program + .unwrap_or(solana_pubkey::pubkey!("11111111111111111111111111111111")), + }; + + accounts.instruction_with_remaining_accounts(&self.__remaining_accounts) + } +} + +/// `update_program_metadata` CPI accounts. +pub struct UpdateProgramMetadataCpiAccounts<'a, 'b> { + /// seeds=['metadata'] + pub program_metadata_account: &'b solana_account_info::AccountInfo<'a>, + + pub payer: &'b solana_account_info::AccountInfo<'a>, + + pub system_program: &'b solana_account_info::AccountInfo<'a>, +} + +/// `update_program_metadata` CPI instruction. +pub struct UpdateProgramMetadataCpi<'a, 'b> { + /// The program to invoke. + pub __program: &'b solana_account_info::AccountInfo<'a>, + /// seeds=['metadata'] + pub program_metadata_account: &'b solana_account_info::AccountInfo<'a>, + + pub payer: &'b solana_account_info::AccountInfo<'a>, + + pub system_program: &'b solana_account_info::AccountInfo<'a>, +} + +impl<'a, 'b> UpdateProgramMetadataCpi<'a, 'b> { + pub fn new( + program: &'b solana_account_info::AccountInfo<'a>, + accounts: UpdateProgramMetadataCpiAccounts<'a, 'b>, + ) -> Self { + Self { + __program: program, + program_metadata_account: accounts.program_metadata_account, + payer: accounts.payer, + system_program: accounts.system_program, + } + } + #[inline(always)] + pub fn invoke(&self) -> solana_program_error::ProgramResult { + self.invoke_signed_with_remaining_accounts(&[], &[]) + } + #[inline(always)] + pub fn invoke_with_remaining_accounts( + &self, + remaining_accounts: &[(&'b solana_account_info::AccountInfo<'a>, bool, bool)], + ) -> solana_program_error::ProgramResult { + self.invoke_signed_with_remaining_accounts(&[], remaining_accounts) + } + #[inline(always)] + pub fn invoke_signed(&self, signers_seeds: &[&[&[u8]]]) -> solana_program_error::ProgramResult { + self.invoke_signed_with_remaining_accounts(signers_seeds, &[]) + } + #[allow(clippy::arithmetic_side_effects)] + #[allow(clippy::clone_on_copy)] + #[allow(clippy::vec_init_then_push)] + pub fn invoke_signed_with_remaining_accounts( + &self, + signers_seeds: &[&[&[u8]]], + remaining_accounts: &[(&'b solana_account_info::AccountInfo<'a>, bool, bool)], + ) -> solana_program_error::ProgramResult { + let mut accounts = Vec::with_capacity(3 + remaining_accounts.len()); + accounts.push(solana_instruction::AccountMeta::new( + *self.program_metadata_account.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.payer.key, + true, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.system_program.key, + false, + )); + remaining_accounts.iter().for_each(|remaining_account| { + accounts.push(solana_instruction::AccountMeta { + pubkey: *remaining_account.0.key, + is_signer: remaining_account.1, + is_writable: remaining_account.2, + }) + }); + let data = UpdateProgramMetadataInstructionData::new() + .try_to_vec() + .unwrap(); + + let instruction = solana_instruction::Instruction { + program_id: crate::SPL_GOVERNANCE_ID, + accounts, + data, + }; + let mut account_infos = Vec::with_capacity(4 + remaining_accounts.len()); + account_infos.push(self.__program.clone()); + account_infos.push(self.program_metadata_account.clone()); + account_infos.push(self.payer.clone()); + account_infos.push(self.system_program.clone()); + remaining_accounts + .iter() + .for_each(|remaining_account| account_infos.push(remaining_account.0.clone())); + + if signers_seeds.is_empty() { + solana_cpi::invoke(&instruction, &account_infos) + } else { + solana_cpi::invoke_signed(&instruction, &account_infos, signers_seeds) + } + } +} + +/// Instruction builder for `UpdateProgramMetadata` via CPI. +/// +/// ### Accounts: +/// +/// 0. `[writable]` program_metadata_account +/// 1. `[signer]` payer +/// 2. `[]` system_program +#[derive(Clone, Debug)] +pub struct UpdateProgramMetadataCpiBuilder<'a, 'b> { + instruction: Box>, +} + +impl<'a, 'b> UpdateProgramMetadataCpiBuilder<'a, 'b> { + pub fn new(program: &'b solana_account_info::AccountInfo<'a>) -> Self { + let instruction = Box::new(UpdateProgramMetadataCpiBuilderInstruction { + __program: program, + program_metadata_account: None, + payer: None, + system_program: None, + __remaining_accounts: Vec::new(), + }); + Self { instruction } + } + /// seeds=['metadata'] + #[inline(always)] + pub fn program_metadata_account( + &mut self, + program_metadata_account: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.program_metadata_account = Some(program_metadata_account); + self + } + #[inline(always)] + pub fn payer(&mut self, payer: &'b solana_account_info::AccountInfo<'a>) -> &mut Self { + self.instruction.payer = Some(payer); + self + } + #[inline(always)] + pub fn system_program( + &mut self, + system_program: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.system_program = Some(system_program); + self + } + /// Add an additional account to the instruction. + #[inline(always)] + pub fn add_remaining_account( + &mut self, + account: &'b solana_account_info::AccountInfo<'a>, + is_writable: bool, + is_signer: bool, + ) -> &mut Self { + self.instruction + .__remaining_accounts + .push((account, is_writable, is_signer)); + self + } + /// Add additional accounts to the instruction. + /// + /// Each account is represented by a tuple of the `AccountInfo`, a `bool` indicating whether the account is writable or not, + /// and a `bool` indicating whether the account is a signer or not. + #[inline(always)] + pub fn add_remaining_accounts( + &mut self, + accounts: &[(&'b solana_account_info::AccountInfo<'a>, bool, bool)], + ) -> &mut Self { + self.instruction + .__remaining_accounts + .extend_from_slice(accounts); + self + } + #[inline(always)] + pub fn invoke(&self) -> solana_program_error::ProgramResult { + self.invoke_signed(&[]) + } + #[allow(clippy::clone_on_copy)] + #[allow(clippy::vec_init_then_push)] + pub fn invoke_signed(&self, signers_seeds: &[&[&[u8]]]) -> solana_program_error::ProgramResult { + let instruction = UpdateProgramMetadataCpi { + __program: self.instruction.__program, + + program_metadata_account: self + .instruction + .program_metadata_account + .expect("program_metadata_account is not set"), + + payer: self.instruction.payer.expect("payer is not set"), + + system_program: self + .instruction + .system_program + .expect("system_program is not set"), + }; + instruction.invoke_signed_with_remaining_accounts( + signers_seeds, + &self.instruction.__remaining_accounts, + ) + } +} + +#[derive(Clone, Debug)] +struct UpdateProgramMetadataCpiBuilderInstruction<'a, 'b> { + __program: &'b solana_account_info::AccountInfo<'a>, + program_metadata_account: Option<&'b solana_account_info::AccountInfo<'a>>, + payer: Option<&'b solana_account_info::AccountInfo<'a>>, + system_program: Option<&'b solana_account_info::AccountInfo<'a>>, + /// Additional instruction accounts `(AccountInfo, is_writable, is_signer)`. + __remaining_accounts: Vec<(&'b solana_account_info::AccountInfo<'a>, bool, bool)>, +} diff --git a/e2e/governance/src/generated/instructions/withdraw_governing_tokens.rs b/e2e/governance/src/generated/instructions/withdraw_governing_tokens.rs new file mode 100644 index 0000000..434989f --- /dev/null +++ b/e2e/governance/src/generated/instructions/withdraw_governing_tokens.rs @@ -0,0 +1,552 @@ +//! This code was AUTOGENERATED using the codama library. +//! Please DO NOT EDIT THIS FILE, instead use visitors +//! to add features, then rerun codama to update it. +//! +//! +//! + +use borsh::BorshDeserialize; +use borsh::BorshSerialize; + +pub const WITHDRAW_GOVERNING_TOKENS_DISCRIMINATOR: u8 = 2; + +/// Accounts. +#[derive(Debug)] +pub struct WithdrawGoverningTokens { + pub realm_account: solana_pubkey::Pubkey, + /// seeds=['governance', realm, governing_token_mint] + pub governing_token_holding_account: solana_pubkey::Pubkey, + /// All tokens will be transferred to this account + pub governing_token_destination_account: solana_pubkey::Pubkey, + + pub governing_token_owner_account: solana_pubkey::Pubkey, + /// seeds=['governance',realm, governing_token_mint, governing_token_owner] + pub token_owner_record: solana_pubkey::Pubkey, + + pub token_program: solana_pubkey::Pubkey, + /// seeds=['realm-config', realm] + pub realm_config_account: solana_pubkey::Pubkey, +} + +impl WithdrawGoverningTokens { + pub fn instruction(&self) -> solana_instruction::Instruction { + self.instruction_with_remaining_accounts(&[]) + } + #[allow(clippy::arithmetic_side_effects)] + #[allow(clippy::vec_init_then_push)] + pub fn instruction_with_remaining_accounts( + &self, + remaining_accounts: &[solana_instruction::AccountMeta], + ) -> solana_instruction::Instruction { + let mut accounts = Vec::with_capacity(7 + remaining_accounts.len()); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.realm_account, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + self.governing_token_holding_account, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + self.governing_token_destination_account, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.governing_token_owner_account, + true, + )); + accounts.push(solana_instruction::AccountMeta::new( + self.token_owner_record, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.token_program, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.realm_config_account, + false, + )); + accounts.extend_from_slice(remaining_accounts); + let data = WithdrawGoverningTokensInstructionData::new() + .try_to_vec() + .unwrap(); + + solana_instruction::Instruction { + program_id: crate::SPL_GOVERNANCE_ID, + accounts, + data, + } + } +} + +#[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct WithdrawGoverningTokensInstructionData { + discriminator: u8, +} + +impl WithdrawGoverningTokensInstructionData { + pub fn new() -> Self { + Self { discriminator: 2 } + } + + pub(crate) fn try_to_vec(&self) -> Result, std::io::Error> { + borsh::to_vec(self) + } +} + +impl Default for WithdrawGoverningTokensInstructionData { + fn default() -> Self { + Self::new() + } +} + +/// Instruction builder for `WithdrawGoverningTokens`. +/// +/// ### Accounts: +/// +/// 0. `[]` realm_account +/// 1. `[writable]` governing_token_holding_account +/// 2. `[writable]` governing_token_destination_account +/// 3. `[signer]` governing_token_owner_account +/// 4. `[writable]` token_owner_record +/// 5. `[optional]` token_program (default to `TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA`) +/// 6. `[]` realm_config_account +#[derive(Clone, Debug, Default)] +pub struct WithdrawGoverningTokensBuilder { + realm_account: Option, + governing_token_holding_account: Option, + governing_token_destination_account: Option, + governing_token_owner_account: Option, + token_owner_record: Option, + token_program: Option, + realm_config_account: Option, + __remaining_accounts: Vec, +} + +impl WithdrawGoverningTokensBuilder { + pub fn new() -> Self { + Self::default() + } + #[inline(always)] + pub fn realm_account(&mut self, realm_account: solana_pubkey::Pubkey) -> &mut Self { + self.realm_account = Some(realm_account); + self + } + /// seeds=['governance', realm, governing_token_mint] + #[inline(always)] + pub fn governing_token_holding_account( + &mut self, + governing_token_holding_account: solana_pubkey::Pubkey, + ) -> &mut Self { + self.governing_token_holding_account = Some(governing_token_holding_account); + self + } + /// All tokens will be transferred to this account + #[inline(always)] + pub fn governing_token_destination_account( + &mut self, + governing_token_destination_account: solana_pubkey::Pubkey, + ) -> &mut Self { + self.governing_token_destination_account = Some(governing_token_destination_account); + self + } + #[inline(always)] + pub fn governing_token_owner_account( + &mut self, + governing_token_owner_account: solana_pubkey::Pubkey, + ) -> &mut Self { + self.governing_token_owner_account = Some(governing_token_owner_account); + self + } + /// seeds=['governance',realm, governing_token_mint, governing_token_owner] + #[inline(always)] + pub fn token_owner_record(&mut self, token_owner_record: solana_pubkey::Pubkey) -> &mut Self { + self.token_owner_record = Some(token_owner_record); + self + } + /// `[optional account, default to 'TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA']` + #[inline(always)] + pub fn token_program(&mut self, token_program: solana_pubkey::Pubkey) -> &mut Self { + self.token_program = Some(token_program); + self + } + /// seeds=['realm-config', realm] + #[inline(always)] + pub fn realm_config_account( + &mut self, + realm_config_account: solana_pubkey::Pubkey, + ) -> &mut Self { + self.realm_config_account = Some(realm_config_account); + self + } + /// Add an additional account to the instruction. + #[inline(always)] + pub fn add_remaining_account(&mut self, account: solana_instruction::AccountMeta) -> &mut Self { + self.__remaining_accounts.push(account); + self + } + /// Add additional accounts to the instruction. + #[inline(always)] + pub fn add_remaining_accounts( + &mut self, + accounts: &[solana_instruction::AccountMeta], + ) -> &mut Self { + self.__remaining_accounts.extend_from_slice(accounts); + self + } + #[allow(clippy::clone_on_copy)] + pub fn instruction(&self) -> solana_instruction::Instruction { + let accounts = WithdrawGoverningTokens { + realm_account: self.realm_account.expect("realm_account is not set"), + governing_token_holding_account: self + .governing_token_holding_account + .expect("governing_token_holding_account is not set"), + governing_token_destination_account: self + .governing_token_destination_account + .expect("governing_token_destination_account is not set"), + governing_token_owner_account: self + .governing_token_owner_account + .expect("governing_token_owner_account is not set"), + token_owner_record: self + .token_owner_record + .expect("token_owner_record is not set"), + token_program: self.token_program.unwrap_or(solana_pubkey::pubkey!( + "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA" + )), + realm_config_account: self + .realm_config_account + .expect("realm_config_account is not set"), + }; + + accounts.instruction_with_remaining_accounts(&self.__remaining_accounts) + } +} + +/// `withdraw_governing_tokens` CPI accounts. +pub struct WithdrawGoverningTokensCpiAccounts<'a, 'b> { + pub realm_account: &'b solana_account_info::AccountInfo<'a>, + /// seeds=['governance', realm, governing_token_mint] + pub governing_token_holding_account: &'b solana_account_info::AccountInfo<'a>, + /// All tokens will be transferred to this account + pub governing_token_destination_account: &'b solana_account_info::AccountInfo<'a>, + + pub governing_token_owner_account: &'b solana_account_info::AccountInfo<'a>, + /// seeds=['governance',realm, governing_token_mint, governing_token_owner] + pub token_owner_record: &'b solana_account_info::AccountInfo<'a>, + + pub token_program: &'b solana_account_info::AccountInfo<'a>, + /// seeds=['realm-config', realm] + pub realm_config_account: &'b solana_account_info::AccountInfo<'a>, +} + +/// `withdraw_governing_tokens` CPI instruction. +pub struct WithdrawGoverningTokensCpi<'a, 'b> { + /// The program to invoke. + pub __program: &'b solana_account_info::AccountInfo<'a>, + + pub realm_account: &'b solana_account_info::AccountInfo<'a>, + /// seeds=['governance', realm, governing_token_mint] + pub governing_token_holding_account: &'b solana_account_info::AccountInfo<'a>, + /// All tokens will be transferred to this account + pub governing_token_destination_account: &'b solana_account_info::AccountInfo<'a>, + + pub governing_token_owner_account: &'b solana_account_info::AccountInfo<'a>, + /// seeds=['governance',realm, governing_token_mint, governing_token_owner] + pub token_owner_record: &'b solana_account_info::AccountInfo<'a>, + + pub token_program: &'b solana_account_info::AccountInfo<'a>, + /// seeds=['realm-config', realm] + pub realm_config_account: &'b solana_account_info::AccountInfo<'a>, +} + +impl<'a, 'b> WithdrawGoverningTokensCpi<'a, 'b> { + pub fn new( + program: &'b solana_account_info::AccountInfo<'a>, + accounts: WithdrawGoverningTokensCpiAccounts<'a, 'b>, + ) -> Self { + Self { + __program: program, + realm_account: accounts.realm_account, + governing_token_holding_account: accounts.governing_token_holding_account, + governing_token_destination_account: accounts.governing_token_destination_account, + governing_token_owner_account: accounts.governing_token_owner_account, + token_owner_record: accounts.token_owner_record, + token_program: accounts.token_program, + realm_config_account: accounts.realm_config_account, + } + } + #[inline(always)] + pub fn invoke(&self) -> solana_program_error::ProgramResult { + self.invoke_signed_with_remaining_accounts(&[], &[]) + } + #[inline(always)] + pub fn invoke_with_remaining_accounts( + &self, + remaining_accounts: &[(&'b solana_account_info::AccountInfo<'a>, bool, bool)], + ) -> solana_program_error::ProgramResult { + self.invoke_signed_with_remaining_accounts(&[], remaining_accounts) + } + #[inline(always)] + pub fn invoke_signed(&self, signers_seeds: &[&[&[u8]]]) -> solana_program_error::ProgramResult { + self.invoke_signed_with_remaining_accounts(signers_seeds, &[]) + } + #[allow(clippy::arithmetic_side_effects)] + #[allow(clippy::clone_on_copy)] + #[allow(clippy::vec_init_then_push)] + pub fn invoke_signed_with_remaining_accounts( + &self, + signers_seeds: &[&[&[u8]]], + remaining_accounts: &[(&'b solana_account_info::AccountInfo<'a>, bool, bool)], + ) -> solana_program_error::ProgramResult { + let mut accounts = Vec::with_capacity(7 + remaining_accounts.len()); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.realm_account.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + *self.governing_token_holding_account.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + *self.governing_token_destination_account.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.governing_token_owner_account.key, + true, + )); + accounts.push(solana_instruction::AccountMeta::new( + *self.token_owner_record.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.token_program.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.realm_config_account.key, + false, + )); + remaining_accounts.iter().for_each(|remaining_account| { + accounts.push(solana_instruction::AccountMeta { + pubkey: *remaining_account.0.key, + is_signer: remaining_account.1, + is_writable: remaining_account.2, + }) + }); + let data = WithdrawGoverningTokensInstructionData::new() + .try_to_vec() + .unwrap(); + + let instruction = solana_instruction::Instruction { + program_id: crate::SPL_GOVERNANCE_ID, + accounts, + data, + }; + let mut account_infos = Vec::with_capacity(8 + remaining_accounts.len()); + account_infos.push(self.__program.clone()); + account_infos.push(self.realm_account.clone()); + account_infos.push(self.governing_token_holding_account.clone()); + account_infos.push(self.governing_token_destination_account.clone()); + account_infos.push(self.governing_token_owner_account.clone()); + account_infos.push(self.token_owner_record.clone()); + account_infos.push(self.token_program.clone()); + account_infos.push(self.realm_config_account.clone()); + remaining_accounts + .iter() + .for_each(|remaining_account| account_infos.push(remaining_account.0.clone())); + + if signers_seeds.is_empty() { + solana_cpi::invoke(&instruction, &account_infos) + } else { + solana_cpi::invoke_signed(&instruction, &account_infos, signers_seeds) + } + } +} + +/// Instruction builder for `WithdrawGoverningTokens` via CPI. +/// +/// ### Accounts: +/// +/// 0. `[]` realm_account +/// 1. `[writable]` governing_token_holding_account +/// 2. `[writable]` governing_token_destination_account +/// 3. `[signer]` governing_token_owner_account +/// 4. `[writable]` token_owner_record +/// 5. `[]` token_program +/// 6. `[]` realm_config_account +#[derive(Clone, Debug)] +pub struct WithdrawGoverningTokensCpiBuilder<'a, 'b> { + instruction: Box>, +} + +impl<'a, 'b> WithdrawGoverningTokensCpiBuilder<'a, 'b> { + pub fn new(program: &'b solana_account_info::AccountInfo<'a>) -> Self { + let instruction = Box::new(WithdrawGoverningTokensCpiBuilderInstruction { + __program: program, + realm_account: None, + governing_token_holding_account: None, + governing_token_destination_account: None, + governing_token_owner_account: None, + token_owner_record: None, + token_program: None, + realm_config_account: None, + __remaining_accounts: Vec::new(), + }); + Self { instruction } + } + #[inline(always)] + pub fn realm_account( + &mut self, + realm_account: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.realm_account = Some(realm_account); + self + } + /// seeds=['governance', realm, governing_token_mint] + #[inline(always)] + pub fn governing_token_holding_account( + &mut self, + governing_token_holding_account: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.governing_token_holding_account = Some(governing_token_holding_account); + self + } + /// All tokens will be transferred to this account + #[inline(always)] + pub fn governing_token_destination_account( + &mut self, + governing_token_destination_account: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.governing_token_destination_account = + Some(governing_token_destination_account); + self + } + #[inline(always)] + pub fn governing_token_owner_account( + &mut self, + governing_token_owner_account: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.governing_token_owner_account = Some(governing_token_owner_account); + self + } + /// seeds=['governance',realm, governing_token_mint, governing_token_owner] + #[inline(always)] + pub fn token_owner_record( + &mut self, + token_owner_record: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.token_owner_record = Some(token_owner_record); + self + } + #[inline(always)] + pub fn token_program( + &mut self, + token_program: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.token_program = Some(token_program); + self + } + /// seeds=['realm-config', realm] + #[inline(always)] + pub fn realm_config_account( + &mut self, + realm_config_account: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.realm_config_account = Some(realm_config_account); + self + } + /// Add an additional account to the instruction. + #[inline(always)] + pub fn add_remaining_account( + &mut self, + account: &'b solana_account_info::AccountInfo<'a>, + is_writable: bool, + is_signer: bool, + ) -> &mut Self { + self.instruction + .__remaining_accounts + .push((account, is_writable, is_signer)); + self + } + /// Add additional accounts to the instruction. + /// + /// Each account is represented by a tuple of the `AccountInfo`, a `bool` indicating whether the account is writable or not, + /// and a `bool` indicating whether the account is a signer or not. + #[inline(always)] + pub fn add_remaining_accounts( + &mut self, + accounts: &[(&'b solana_account_info::AccountInfo<'a>, bool, bool)], + ) -> &mut Self { + self.instruction + .__remaining_accounts + .extend_from_slice(accounts); + self + } + #[inline(always)] + pub fn invoke(&self) -> solana_program_error::ProgramResult { + self.invoke_signed(&[]) + } + #[allow(clippy::clone_on_copy)] + #[allow(clippy::vec_init_then_push)] + pub fn invoke_signed(&self, signers_seeds: &[&[&[u8]]]) -> solana_program_error::ProgramResult { + let instruction = WithdrawGoverningTokensCpi { + __program: self.instruction.__program, + + realm_account: self + .instruction + .realm_account + .expect("realm_account is not set"), + + governing_token_holding_account: self + .instruction + .governing_token_holding_account + .expect("governing_token_holding_account is not set"), + + governing_token_destination_account: self + .instruction + .governing_token_destination_account + .expect("governing_token_destination_account is not set"), + + governing_token_owner_account: self + .instruction + .governing_token_owner_account + .expect("governing_token_owner_account is not set"), + + token_owner_record: self + .instruction + .token_owner_record + .expect("token_owner_record is not set"), + + token_program: self + .instruction + .token_program + .expect("token_program is not set"), + + realm_config_account: self + .instruction + .realm_config_account + .expect("realm_config_account is not set"), + }; + instruction.invoke_signed_with_remaining_accounts( + signers_seeds, + &self.instruction.__remaining_accounts, + ) + } +} + +#[derive(Clone, Debug)] +struct WithdrawGoverningTokensCpiBuilderInstruction<'a, 'b> { + __program: &'b solana_account_info::AccountInfo<'a>, + realm_account: Option<&'b solana_account_info::AccountInfo<'a>>, + governing_token_holding_account: Option<&'b solana_account_info::AccountInfo<'a>>, + governing_token_destination_account: Option<&'b solana_account_info::AccountInfo<'a>>, + governing_token_owner_account: Option<&'b solana_account_info::AccountInfo<'a>>, + token_owner_record: Option<&'b solana_account_info::AccountInfo<'a>>, + token_program: Option<&'b solana_account_info::AccountInfo<'a>>, + realm_config_account: Option<&'b solana_account_info::AccountInfo<'a>>, + /// Additional instruction accounts `(AccountInfo, is_writable, is_signer)`. + __remaining_accounts: Vec<(&'b solana_account_info::AccountInfo<'a>, bool, bool)>, +} diff --git a/e2e/governance/src/generated/mod.rs b/e2e/governance/src/generated/mod.rs new file mode 100644 index 0000000..e0d740a --- /dev/null +++ b/e2e/governance/src/generated/mod.rs @@ -0,0 +1,15 @@ +//! This code was AUTOGENERATED using the codama library. +//! Please DO NOT EDIT THIS FILE, instead use visitors +//! to add features, then rerun codama to update it. +//! +//! +//! + +pub mod accounts; +pub mod errors; +pub mod instructions; +pub mod programs; +pub mod shared; +pub mod types; + +pub(crate) use programs::*; diff --git a/e2e/governance/src/generated/pdas/community_token_holding.rs b/e2e/governance/src/generated/pdas/community_token_holding.rs new file mode 100644 index 0000000..889d1b9 --- /dev/null +++ b/e2e/governance/src/generated/pdas/community_token_holding.rs @@ -0,0 +1,42 @@ +//! This code was AUTOGENERATED using the codama library. +//! Please DO NOT EDIT THIS FILE, instead use visitors +//! to add features, then rerun codama to update it. +//! +//! +//! + +use crate::SPL_GOVERNANCE_ID; + + + pub const COMMUNITY_TOKEN_HOLDING_SEED: &'static [u8] = b"governance"; + +pub fn create_community_token_holding_pda( + realm: solana_pubkey::Pubkey, + community_mint: solana_pubkey::Pubkey, + bump: u8, +) -> Result { + solana_pubkey::Pubkey::create_program_address( + &[ + COMMUNITY_TOKEN_HOLDING_SEED, + realm.as_ref(), + community_mint.as_ref(), + &[bump], + ], + &SPL_GOVERNANCE_ID, + ) +} + +pub fn find_community_token_holding_pda( + realm: &solana_pubkey::Pubkey, + community_mint: &solana_pubkey::Pubkey, + ) -> (solana_pubkey::Pubkey, u8) { + solana_pubkey::Pubkey::find_program_address( + &[ + COMMUNITY_TOKEN_HOLDING_SEED, + realm.as_ref(), + community_mint.as_ref(), + ], + &SPL_GOVERNANCE_ID, + ) +} + diff --git a/e2e/governance/src/generated/pdas/council_token_holding.rs b/e2e/governance/src/generated/pdas/council_token_holding.rs new file mode 100644 index 0000000..85e0a52 --- /dev/null +++ b/e2e/governance/src/generated/pdas/council_token_holding.rs @@ -0,0 +1,42 @@ +//! This code was AUTOGENERATED using the codama library. +//! Please DO NOT EDIT THIS FILE, instead use visitors +//! to add features, then rerun codama to update it. +//! +//! +//! + +use crate::SPL_GOVERNANCE_ID; + + + pub const COUNCIL_TOKEN_HOLDING_SEED: &'static [u8] = b"governance"; + +pub fn create_council_token_holding_pda( + realm: solana_pubkey::Pubkey, + council_mint: solana_pubkey::Pubkey, + bump: u8, +) -> Result { + solana_pubkey::Pubkey::create_program_address( + &[ + COUNCIL_TOKEN_HOLDING_SEED, + realm.as_ref(), + council_mint.as_ref(), + &[bump], + ], + &SPL_GOVERNANCE_ID, + ) +} + +pub fn find_council_token_holding_pda( + realm: &solana_pubkey::Pubkey, + council_mint: &solana_pubkey::Pubkey, + ) -> (solana_pubkey::Pubkey, u8) { + solana_pubkey::Pubkey::find_program_address( + &[ + COUNCIL_TOKEN_HOLDING_SEED, + realm.as_ref(), + council_mint.as_ref(), + ], + &SPL_GOVERNANCE_ID, + ) +} + diff --git a/e2e/governance/src/generated/pdas/governance.rs b/e2e/governance/src/generated/pdas/governance.rs new file mode 100644 index 0000000..f075a20 --- /dev/null +++ b/e2e/governance/src/generated/pdas/governance.rs @@ -0,0 +1,42 @@ +//! This code was AUTOGENERATED using the codama library. +//! Please DO NOT EDIT THIS FILE, instead use visitors +//! to add features, then rerun codama to update it. +//! +//! +//! + +use crate::SPL_GOVERNANCE_ID; + + + pub const GOVERNANCE_SEED: &'static [u8] = b"account-governance"; + +pub fn create_governance_pda( + realm: solana_pubkey::Pubkey, + seed: solana_pubkey::Pubkey, + bump: u8, +) -> Result { + solana_pubkey::Pubkey::create_program_address( + &[ + GOVERNANCE_SEED, + realm.as_ref(), + seed.as_ref(), + &[bump], + ], + &SPL_GOVERNANCE_ID, + ) +} + +pub fn find_governance_pda( + realm: &solana_pubkey::Pubkey, + seed: &solana_pubkey::Pubkey, + ) -> (solana_pubkey::Pubkey, u8) { + solana_pubkey::Pubkey::find_program_address( + &[ + GOVERNANCE_SEED, + realm.as_ref(), + seed.as_ref(), + ], + &SPL_GOVERNANCE_ID, + ) +} + diff --git a/e2e/governance/src/generated/pdas/governing_token_holding.rs b/e2e/governance/src/generated/pdas/governing_token_holding.rs new file mode 100644 index 0000000..4a89c93 --- /dev/null +++ b/e2e/governance/src/generated/pdas/governing_token_holding.rs @@ -0,0 +1,42 @@ +//! This code was AUTOGENERATED using the codama library. +//! Please DO NOT EDIT THIS FILE, instead use visitors +//! to add features, then rerun codama to update it. +//! +//! +//! + +use crate::SPL_GOVERNANCE_ID; + + + pub const GOVERNING_TOKEN_HOLDING_SEED: &'static [u8] = b"governance"; + +pub fn create_governing_token_holding_pda( + realm: solana_pubkey::Pubkey, + governing_token_mint: solana_pubkey::Pubkey, + bump: u8, +) -> Result { + solana_pubkey::Pubkey::create_program_address( + &[ + GOVERNING_TOKEN_HOLDING_SEED, + realm.as_ref(), + governing_token_mint.as_ref(), + &[bump], + ], + &SPL_GOVERNANCE_ID, + ) +} + +pub fn find_governing_token_holding_pda( + realm: &solana_pubkey::Pubkey, + governing_token_mint: &solana_pubkey::Pubkey, + ) -> (solana_pubkey::Pubkey, u8) { + solana_pubkey::Pubkey::find_program_address( + &[ + GOVERNING_TOKEN_HOLDING_SEED, + realm.as_ref(), + governing_token_mint.as_ref(), + ], + &SPL_GOVERNANCE_ID, + ) +} + diff --git a/e2e/governance/src/generated/pdas/mod.rs b/e2e/governance/src/generated/pdas/mod.rs new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/e2e/governance/src/generated/pdas/mod.rs @@ -0,0 +1 @@ + diff --git a/e2e/governance/src/generated/pdas/native_treasury.rs b/e2e/governance/src/generated/pdas/native_treasury.rs new file mode 100644 index 0000000..54e36f6 --- /dev/null +++ b/e2e/governance/src/generated/pdas/native_treasury.rs @@ -0,0 +1,38 @@ +//! This code was AUTOGENERATED using the codama library. +//! Please DO NOT EDIT THIS FILE, instead use visitors +//! to add features, then rerun codama to update it. +//! +//! +//! + +use crate::SPL_GOVERNANCE_ID; + + + pub const NATIVE_TREASURY_SEED: &'static [u8] = b"native-treasury"; + +pub fn create_native_treasury_pda( + governance: solana_pubkey::Pubkey, + bump: u8, +) -> Result { + solana_pubkey::Pubkey::create_program_address( + &[ + NATIVE_TREASURY_SEED, + governance.as_ref(), + &[bump], + ], + &SPL_GOVERNANCE_ID, + ) +} + +pub fn find_native_treasury_pda( + governance: &solana_pubkey::Pubkey, + ) -> (solana_pubkey::Pubkey, u8) { + solana_pubkey::Pubkey::find_program_address( + &[ + NATIVE_TREASURY_SEED, + governance.as_ref(), + ], + &SPL_GOVERNANCE_ID, + ) +} + diff --git a/e2e/governance/src/generated/pdas/proposal.rs b/e2e/governance/src/generated/pdas/proposal.rs new file mode 100644 index 0000000..109bc99 --- /dev/null +++ b/e2e/governance/src/generated/pdas/proposal.rs @@ -0,0 +1,46 @@ +//! This code was AUTOGENERATED using the codama library. +//! Please DO NOT EDIT THIS FILE, instead use visitors +//! to add features, then rerun codama to update it. +//! +//! +//! + +use crate::SPL_GOVERNANCE_ID; + + + pub const PROPOSAL_SEED: &'static [u8] = b"governance"; + +pub fn create_proposal_pda( + governance: solana_pubkey::Pubkey, + governing_token_mint: solana_pubkey::Pubkey, + proposal_seed: solana_pubkey::Pubkey, + bump: u8, +) -> Result { + solana_pubkey::Pubkey::create_program_address( + &[ + PROPOSAL_SEED, + governance.as_ref(), + governing_token_mint.as_ref(), + proposal_seed.as_ref(), + &[bump], + ], + &SPL_GOVERNANCE_ID, + ) +} + +pub fn find_proposal_pda( + governance: &solana_pubkey::Pubkey, + governing_token_mint: &solana_pubkey::Pubkey, + proposal_seed: &solana_pubkey::Pubkey, + ) -> (solana_pubkey::Pubkey, u8) { + solana_pubkey::Pubkey::find_program_address( + &[ + PROPOSAL_SEED, + governance.as_ref(), + governing_token_mint.as_ref(), + proposal_seed.as_ref(), + ], + &SPL_GOVERNANCE_ID, + ) +} + diff --git a/e2e/governance/src/generated/pdas/proposal_deposit.rs b/e2e/governance/src/generated/pdas/proposal_deposit.rs new file mode 100644 index 0000000..207b043 --- /dev/null +++ b/e2e/governance/src/generated/pdas/proposal_deposit.rs @@ -0,0 +1,42 @@ +//! This code was AUTOGENERATED using the codama library. +//! Please DO NOT EDIT THIS FILE, instead use visitors +//! to add features, then rerun codama to update it. +//! +//! +//! + +use crate::SPL_GOVERNANCE_ID; + + + pub const PROPOSAL_DEPOSIT_SEED: &'static [u8] = b"proposal-deposit"; + +pub fn create_proposal_deposit_pda( + proposal: solana_pubkey::Pubkey, + deposit_payer: solana_pubkey::Pubkey, + bump: u8, +) -> Result { + solana_pubkey::Pubkey::create_program_address( + &[ + PROPOSAL_DEPOSIT_SEED, + proposal.as_ref(), + deposit_payer.as_ref(), + &[bump], + ], + &SPL_GOVERNANCE_ID, + ) +} + +pub fn find_proposal_deposit_pda( + proposal: &solana_pubkey::Pubkey, + deposit_payer: &solana_pubkey::Pubkey, + ) -> (solana_pubkey::Pubkey, u8) { + solana_pubkey::Pubkey::find_program_address( + &[ + PROPOSAL_DEPOSIT_SEED, + proposal.as_ref(), + deposit_payer.as_ref(), + ], + &SPL_GOVERNANCE_ID, + ) +} + diff --git a/e2e/governance/src/generated/pdas/proposal_transaction.rs b/e2e/governance/src/generated/pdas/proposal_transaction.rs new file mode 100644 index 0000000..a107021 --- /dev/null +++ b/e2e/governance/src/generated/pdas/proposal_transaction.rs @@ -0,0 +1,46 @@ +//! This code was AUTOGENERATED using the codama library. +//! Please DO NOT EDIT THIS FILE, instead use visitors +//! to add features, then rerun codama to update it. +//! +//! +//! + +use crate::SPL_GOVERNANCE_ID; + + + pub const PROPOSAL_TRANSACTION_SEED: &'static [u8] = b"governance"; + +pub fn create_proposal_transaction_pda( + proposal: solana_pubkey::Pubkey, + option_index: u8, + index: u16, + bump: u8, +) -> Result { + solana_pubkey::Pubkey::create_program_address( + &[ + PROPOSAL_TRANSACTION_SEED, + proposal.as_ref(), + option_index.to_string().as_ref(), + index.to_string().as_ref(), + &[bump], + ], + &SPL_GOVERNANCE_ID, + ) +} + +pub fn find_proposal_transaction_pda( + proposal: &solana_pubkey::Pubkey, + option_index: u8, + index: u16, + ) -> (solana_pubkey::Pubkey, u8) { + solana_pubkey::Pubkey::find_program_address( + &[ + PROPOSAL_TRANSACTION_SEED, + proposal.as_ref(), + option_index.to_string().as_ref(), + index.to_string().as_ref(), + ], + &SPL_GOVERNANCE_ID, + ) +} + diff --git a/e2e/governance/src/generated/pdas/realm.rs b/e2e/governance/src/generated/pdas/realm.rs new file mode 100644 index 0000000..1d72486 --- /dev/null +++ b/e2e/governance/src/generated/pdas/realm.rs @@ -0,0 +1,38 @@ +//! This code was AUTOGENERATED using the codama library. +//! Please DO NOT EDIT THIS FILE, instead use visitors +//! to add features, then rerun codama to update it. +//! +//! +//! + +use crate::SPL_GOVERNANCE_ID; + + + pub const REALM_SEED: &'static [u8] = b"governance"; + +pub fn create_realm_pda( + name: RemainderStr, + bump: u8, +) -> Result { + solana_pubkey::Pubkey::create_program_address( + &[ + REALM_SEED, + name.to_string().as_ref(), + &[bump], + ], + &SPL_GOVERNANCE_ID, + ) +} + +pub fn find_realm_pda( + name: RemainderStr, + ) -> (solana_pubkey::Pubkey, u8) { + solana_pubkey::Pubkey::find_program_address( + &[ + REALM_SEED, + name.to_string().as_ref(), + ], + &SPL_GOVERNANCE_ID, + ) +} + diff --git a/e2e/governance/src/generated/pdas/realm_config.rs b/e2e/governance/src/generated/pdas/realm_config.rs new file mode 100644 index 0000000..ee86683 --- /dev/null +++ b/e2e/governance/src/generated/pdas/realm_config.rs @@ -0,0 +1,38 @@ +//! This code was AUTOGENERATED using the codama library. +//! Please DO NOT EDIT THIS FILE, instead use visitors +//! to add features, then rerun codama to update it. +//! +//! +//! + +use crate::SPL_GOVERNANCE_ID; + + + pub const REALM_CONFIG_SEED: &'static [u8] = b"realm-config"; + +pub fn create_realm_config_pda( + realm: solana_pubkey::Pubkey, + bump: u8, +) -> Result { + solana_pubkey::Pubkey::create_program_address( + &[ + REALM_CONFIG_SEED, + realm.as_ref(), + &[bump], + ], + &SPL_GOVERNANCE_ID, + ) +} + +pub fn find_realm_config_pda( + realm: &solana_pubkey::Pubkey, + ) -> (solana_pubkey::Pubkey, u8) { + solana_pubkey::Pubkey::find_program_address( + &[ + REALM_CONFIG_SEED, + realm.as_ref(), + ], + &SPL_GOVERNANCE_ID, + ) +} + diff --git a/e2e/governance/src/generated/pdas/required_signatory.rs b/e2e/governance/src/generated/pdas/required_signatory.rs new file mode 100644 index 0000000..f53afd5 --- /dev/null +++ b/e2e/governance/src/generated/pdas/required_signatory.rs @@ -0,0 +1,42 @@ +//! This code was AUTOGENERATED using the codama library. +//! Please DO NOT EDIT THIS FILE, instead use visitors +//! to add features, then rerun codama to update it. +//! +//! +//! + +use crate::SPL_GOVERNANCE_ID; + + + pub const REQUIRED_SIGNATORY_SEED: &'static [u8] = b"required-signatory"; + +pub fn create_required_signatory_pda( + governance: solana_pubkey::Pubkey, + signatory: solana_pubkey::Pubkey, + bump: u8, +) -> Result { + solana_pubkey::Pubkey::create_program_address( + &[ + REQUIRED_SIGNATORY_SEED, + governance.as_ref(), + signatory.as_ref(), + &[bump], + ], + &SPL_GOVERNANCE_ID, + ) +} + +pub fn find_required_signatory_pda( + governance: &solana_pubkey::Pubkey, + signatory: &solana_pubkey::Pubkey, + ) -> (solana_pubkey::Pubkey, u8) { + solana_pubkey::Pubkey::find_program_address( + &[ + REQUIRED_SIGNATORY_SEED, + governance.as_ref(), + signatory.as_ref(), + ], + &SPL_GOVERNANCE_ID, + ) +} + diff --git a/e2e/governance/src/generated/pdas/signatory_record.rs b/e2e/governance/src/generated/pdas/signatory_record.rs new file mode 100644 index 0000000..295b3e3 --- /dev/null +++ b/e2e/governance/src/generated/pdas/signatory_record.rs @@ -0,0 +1,42 @@ +//! This code was AUTOGENERATED using the codama library. +//! Please DO NOT EDIT THIS FILE, instead use visitors +//! to add features, then rerun codama to update it. +//! +//! +//! + +use crate::SPL_GOVERNANCE_ID; + + + pub const SIGNATORY_RECORD_SEED: &'static [u8] = b"governance"; + +pub fn create_signatory_record_pda( + proposal: solana_pubkey::Pubkey, + signatory: solana_pubkey::Pubkey, + bump: u8, +) -> Result { + solana_pubkey::Pubkey::create_program_address( + &[ + SIGNATORY_RECORD_SEED, + proposal.as_ref(), + signatory.as_ref(), + &[bump], + ], + &SPL_GOVERNANCE_ID, + ) +} + +pub fn find_signatory_record_pda( + proposal: &solana_pubkey::Pubkey, + signatory: &solana_pubkey::Pubkey, + ) -> (solana_pubkey::Pubkey, u8) { + solana_pubkey::Pubkey::find_program_address( + &[ + SIGNATORY_RECORD_SEED, + proposal.as_ref(), + signatory.as_ref(), + ], + &SPL_GOVERNANCE_ID, + ) +} + diff --git a/e2e/governance/src/generated/pdas/token_owner_record.rs b/e2e/governance/src/generated/pdas/token_owner_record.rs new file mode 100644 index 0000000..a7672e5 --- /dev/null +++ b/e2e/governance/src/generated/pdas/token_owner_record.rs @@ -0,0 +1,46 @@ +//! This code was AUTOGENERATED using the codama library. +//! Please DO NOT EDIT THIS FILE, instead use visitors +//! to add features, then rerun codama to update it. +//! +//! +//! + +use crate::SPL_GOVERNANCE_ID; + + + pub const TOKEN_OWNER_RECORD_SEED: &'static [u8] = b"governance"; + +pub fn create_token_owner_record_pda( + realm: solana_pubkey::Pubkey, + governing_token_mint: solana_pubkey::Pubkey, + governing_token_owner: solana_pubkey::Pubkey, + bump: u8, +) -> Result { + solana_pubkey::Pubkey::create_program_address( + &[ + TOKEN_OWNER_RECORD_SEED, + realm.as_ref(), + governing_token_mint.as_ref(), + governing_token_owner.as_ref(), + &[bump], + ], + &SPL_GOVERNANCE_ID, + ) +} + +pub fn find_token_owner_record_pda( + realm: &solana_pubkey::Pubkey, + governing_token_mint: &solana_pubkey::Pubkey, + governing_token_owner: &solana_pubkey::Pubkey, + ) -> (solana_pubkey::Pubkey, u8) { + solana_pubkey::Pubkey::find_program_address( + &[ + TOKEN_OWNER_RECORD_SEED, + realm.as_ref(), + governing_token_mint.as_ref(), + governing_token_owner.as_ref(), + ], + &SPL_GOVERNANCE_ID, + ) +} + diff --git a/e2e/governance/src/generated/pdas/vote_record.rs b/e2e/governance/src/generated/pdas/vote_record.rs new file mode 100644 index 0000000..4443f88 --- /dev/null +++ b/e2e/governance/src/generated/pdas/vote_record.rs @@ -0,0 +1,42 @@ +//! This code was AUTOGENERATED using the codama library. +//! Please DO NOT EDIT THIS FILE, instead use visitors +//! to add features, then rerun codama to update it. +//! +//! +//! + +use crate::SPL_GOVERNANCE_ID; + + + pub const VOTE_RECORD_SEED: &'static [u8] = b"governance"; + +pub fn create_vote_record_pda( + proposal: solana_pubkey::Pubkey, + token_owner_record: solana_pubkey::Pubkey, + bump: u8, +) -> Result { + solana_pubkey::Pubkey::create_program_address( + &[ + VOTE_RECORD_SEED, + proposal.as_ref(), + token_owner_record.as_ref(), + &[bump], + ], + &SPL_GOVERNANCE_ID, + ) +} + +pub fn find_vote_record_pda( + proposal: &solana_pubkey::Pubkey, + token_owner_record: &solana_pubkey::Pubkey, + ) -> (solana_pubkey::Pubkey, u8) { + solana_pubkey::Pubkey::find_program_address( + &[ + VOTE_RECORD_SEED, + proposal.as_ref(), + token_owner_record.as_ref(), + ], + &SPL_GOVERNANCE_ID, + ) +} + diff --git a/e2e/governance/src/generated/programs.rs b/e2e/governance/src/generated/programs.rs new file mode 100644 index 0000000..1a3d43e --- /dev/null +++ b/e2e/governance/src/generated/programs.rs @@ -0,0 +1,11 @@ +//! This code was AUTOGENERATED using the codama library. +//! Please DO NOT EDIT THIS FILE, instead use visitors +//! to add features, then rerun codama to update it. +//! +//! +//! + +use solana_pubkey::{pubkey, Pubkey}; + +/// `spl_governance` program ID. +pub const SPL_GOVERNANCE_ID: Pubkey = pubkey!("GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw"); diff --git a/e2e/governance/src/generated/shared.rs b/e2e/governance/src/generated/shared.rs new file mode 100644 index 0000000..71b906d --- /dev/null +++ b/e2e/governance/src/generated/shared.rs @@ -0,0 +1,21 @@ +//! This code was AUTOGENERATED using the codama library. +//! Please DO NOT EDIT THIS FILE, instead use visitors +//! to add features, then rerun codama to update it. +//! +//! +//! + +#[cfg(feature = "fetch")] +#[derive(Debug, Clone)] +pub struct DecodedAccount { + pub address: solana_pubkey::Pubkey, + pub account: solana_account::Account, + pub data: T, +} + +#[cfg(feature = "fetch")] +#[derive(Debug, Clone)] +pub enum MaybeAccount { + Exists(DecodedAccount), + NotFound(solana_pubkey::Pubkey), +} diff --git a/e2e/governance/src/generated/types/account_meta_data.rs b/e2e/governance/src/generated/types/account_meta_data.rs new file mode 100644 index 0000000..c15ed18 --- /dev/null +++ b/e2e/governance/src/generated/types/account_meta_data.rs @@ -0,0 +1,22 @@ +//! This code was AUTOGENERATED using the codama library. +//! Please DO NOT EDIT THIS FILE, instead use visitors +//! to add features, then rerun codama to update it. +//! +//! +//! + +use borsh::BorshDeserialize; +use borsh::BorshSerialize; +use solana_pubkey::Pubkey; + +#[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct AccountMetaData { + #[cfg_attr( + feature = "serde", + serde(with = "serde_with::As::") + )] + pub pubkey: Pubkey, + pub is_signer: bool, + pub is_writable: bool, +} diff --git a/e2e/governance/src/generated/types/governance_account_type.rs b/e2e/governance/src/generated/types/governance_account_type.rs new file mode 100644 index 0000000..5554407 --- /dev/null +++ b/e2e/governance/src/generated/types/governance_account_type.rs @@ -0,0 +1,51 @@ +//! This code was AUTOGENERATED using the codama library. +//! Please DO NOT EDIT THIS FILE, instead use visitors +//! to add features, then rerun codama to update it. +//! +//! +//! + +use borsh::BorshDeserialize; +use borsh::BorshSerialize; +use num_derive::FromPrimitive; + +#[derive( + BorshSerialize, + BorshDeserialize, + Clone, + Debug, + Eq, + PartialEq, + Copy, + PartialOrd, + Hash, + FromPrimitive, +)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub enum GovernanceAccountType { + Uninitialized, + RealmV1, + TokenOwnerRecordV1, + GovernanceV1, + ProgramGovernanceV1, + ProposalV1, + SignatoryRecordV1, + VoteRecordV1, + ProposalInstructionV1, + MintGovernanceV1, + TokenGovernanceV1, + RealmConfig, + VoteRecordV2, + ProposalTransactionV2, + ProposalV2, + ProgramMetadata, + RealmV2, + TokenOwnerRecordV2, + GovernanceV2, + ProgramGovernanceV2, + MintGovernanceV2, + TokenGovernanceV2, + SignatoryRecordV2, + ProposalDeposit, + RequiredSignatory, +} diff --git a/e2e/governance/src/generated/types/governance_config.rs b/e2e/governance/src/generated/types/governance_config.rs new file mode 100644 index 0000000..d84716c --- /dev/null +++ b/e2e/governance/src/generated/types/governance_config.rs @@ -0,0 +1,28 @@ +//! This code was AUTOGENERATED using the codama library. +//! Please DO NOT EDIT THIS FILE, instead use visitors +//! to add features, then rerun codama to update it. +//! +//! +//! + +use crate::generated::types::VoteThreshold; +use crate::generated::types::VoteTipping; +use borsh::BorshDeserialize; +use borsh::BorshSerialize; + +#[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct GovernanceConfig { + pub community_vote_threshold: VoteThreshold, + pub min_community_weight_to_create_proposal: u64, + pub min_transaction_hold_up_time: u32, + pub voting_base_time: u32, + pub community_vote_tipping: VoteTipping, + pub council_vote_threshold: VoteThreshold, + pub council_veto_vote_threshold: VoteThreshold, + pub min_council_weight_to_create_proposal: u64, + pub council_vote_tipping: VoteTipping, + pub community_veto_vote_threshold: VoteThreshold, + pub voting_cool_off_time: u32, + pub deposit_exempt_proposal_count: u8, +} diff --git a/e2e/governance/src/generated/types/governance_instruction_v1.rs b/e2e/governance/src/generated/types/governance_instruction_v1.rs new file mode 100644 index 0000000..fbef779 --- /dev/null +++ b/e2e/governance/src/generated/types/governance_instruction_v1.rs @@ -0,0 +1,22 @@ +//! This code was AUTOGENERATED using the codama library. +//! Please DO NOT EDIT THIS FILE, instead use visitors +//! to add features, then rerun codama to update it. +//! +//! +//! + +use crate::generated::types::RealmConfigParamsV1; +use borsh::BorshDeserialize; +use borsh::BorshSerialize; + +#[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub enum GovernanceInstructionV1 { + CreateRealm { + name: String, + config_args: RealmConfigParamsV1, + }, + DepositGoverningTokens { + amount: u64, + }, +} diff --git a/e2e/governance/src/generated/types/governing_token_config.rs b/e2e/governance/src/generated/types/governing_token_config.rs new file mode 100644 index 0000000..55bf0fe --- /dev/null +++ b/e2e/governance/src/generated/types/governing_token_config.rs @@ -0,0 +1,20 @@ +//! This code was AUTOGENERATED using the codama library. +//! Please DO NOT EDIT THIS FILE, instead use visitors +//! to add features, then rerun codama to update it. +//! +//! +//! + +use crate::generated::types::GoverningTokenType; +use borsh::BorshDeserialize; +use borsh::BorshSerialize; +use solana_pubkey::Pubkey; + +#[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct GoverningTokenConfig { + pub voter_weight_addin: Option, + pub max_voter_weight_addin: Option, + pub token_type: GoverningTokenType, + pub reserved: [u8; 8], +} diff --git a/e2e/governance/src/generated/types/governing_token_config_account_args.rs b/e2e/governance/src/generated/types/governing_token_config_account_args.rs new file mode 100644 index 0000000..a536aba --- /dev/null +++ b/e2e/governance/src/generated/types/governing_token_config_account_args.rs @@ -0,0 +1,19 @@ +//! This code was AUTOGENERATED using the codama library. +//! Please DO NOT EDIT THIS FILE, instead use visitors +//! to add features, then rerun codama to update it. +//! +//! +//! + +use crate::generated::types::GoverningTokenType; +use borsh::BorshDeserialize; +use borsh::BorshSerialize; +use solana_pubkey::Pubkey; + +#[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct GoverningTokenConfigAccountArgs { + pub voter_weight_addin: Option, + pub max_voter_weight_addin: Option, + pub token_type: GoverningTokenType, +} diff --git a/e2e/governance/src/generated/types/governing_token_config_params.rs b/e2e/governance/src/generated/types/governing_token_config_params.rs new file mode 100644 index 0000000..997da2a --- /dev/null +++ b/e2e/governance/src/generated/types/governing_token_config_params.rs @@ -0,0 +1,18 @@ +//! This code was AUTOGENERATED using the codama library. +//! Please DO NOT EDIT THIS FILE, instead use visitors +//! to add features, then rerun codama to update it. +//! +//! +//! + +use crate::generated::types::GoverningTokenType; +use borsh::BorshDeserialize; +use borsh::BorshSerialize; + +#[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct GoverningTokenConfigParams { + pub use_voter_weight_addin: bool, + pub use_max_voter_weight_addin: bool, + pub token_type: GoverningTokenType, +} diff --git a/e2e/governance/src/generated/types/governing_token_type.rs b/e2e/governance/src/generated/types/governing_token_type.rs new file mode 100644 index 0000000..38414f2 --- /dev/null +++ b/e2e/governance/src/generated/types/governing_token_type.rs @@ -0,0 +1,29 @@ +//! This code was AUTOGENERATED using the codama library. +//! Please DO NOT EDIT THIS FILE, instead use visitors +//! to add features, then rerun codama to update it. +//! +//! +//! + +use borsh::BorshDeserialize; +use borsh::BorshSerialize; +use num_derive::FromPrimitive; + +#[derive( + BorshSerialize, + BorshDeserialize, + Clone, + Debug, + Eq, + PartialEq, + Copy, + PartialOrd, + Hash, + FromPrimitive, +)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub enum GoverningTokenType { + Liquid, + Membership, + Dormant, +} diff --git a/e2e/governance/src/generated/types/instruction_data.rs b/e2e/governance/src/generated/types/instruction_data.rs new file mode 100644 index 0000000..c4d309b --- /dev/null +++ b/e2e/governance/src/generated/types/instruction_data.rs @@ -0,0 +1,23 @@ +//! This code was AUTOGENERATED using the codama library. +//! Please DO NOT EDIT THIS FILE, instead use visitors +//! to add features, then rerun codama to update it. +//! +//! +//! + +use crate::generated::types::AccountMetaData; +use borsh::BorshDeserialize; +use borsh::BorshSerialize; +use solana_pubkey::Pubkey; + +#[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct InstructionData { + #[cfg_attr( + feature = "serde", + serde(with = "serde_with::As::") + )] + pub program_id: Pubkey, + pub accounts: Vec, + pub data: Vec, +} diff --git a/e2e/governance/src/generated/types/instruction_execution_flags.rs b/e2e/governance/src/generated/types/instruction_execution_flags.rs new file mode 100644 index 0000000..e7d6fbf --- /dev/null +++ b/e2e/governance/src/generated/types/instruction_execution_flags.rs @@ -0,0 +1,29 @@ +//! This code was AUTOGENERATED using the codama library. +//! Please DO NOT EDIT THIS FILE, instead use visitors +//! to add features, then rerun codama to update it. +//! +//! +//! + +use borsh::BorshDeserialize; +use borsh::BorshSerialize; +use num_derive::FromPrimitive; + +#[derive( + BorshSerialize, + BorshDeserialize, + Clone, + Debug, + Eq, + PartialEq, + Copy, + PartialOrd, + Hash, + FromPrimitive, +)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub enum InstructionExecutionFlags { + None, + Ordered, + UseTransaction, +} diff --git a/e2e/governance/src/generated/types/mint_max_voter_weight_source.rs b/e2e/governance/src/generated/types/mint_max_voter_weight_source.rs new file mode 100644 index 0000000..b37c7a7 --- /dev/null +++ b/e2e/governance/src/generated/types/mint_max_voter_weight_source.rs @@ -0,0 +1,16 @@ +//! This code was AUTOGENERATED using the codama library. +//! Please DO NOT EDIT THIS FILE, instead use visitors +//! to add features, then rerun codama to update it. +//! +//! +//! + +use borsh::BorshDeserialize; +use borsh::BorshSerialize; + +#[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub enum MintMaxVoterWeightSource { + SupplyFraction(u64), + Absolute(u64), +} diff --git a/e2e/governance/src/generated/types/mod.rs b/e2e/governance/src/generated/types/mod.rs new file mode 100644 index 0000000..b5b6bae --- /dev/null +++ b/e2e/governance/src/generated/types/mod.rs @@ -0,0 +1,72 @@ +//! This code was AUTOGENERATED using the codama library. +//! Please DO NOT EDIT THIS FILE, instead use visitors +//! to add features, then rerun codama to update it. +//! +//! +//! + +pub(crate) mod r#account_meta_data; +pub(crate) mod r#governance_account_type; +pub(crate) mod r#governance_config; +pub(crate) mod r#governance_instruction_v1; +pub(crate) mod r#governing_token_config; +pub(crate) mod r#governing_token_config_account_args; +pub(crate) mod r#governing_token_config_params; +pub(crate) mod r#governing_token_type; +pub(crate) mod r#instruction_data; +pub(crate) mod r#instruction_execution_flags; +pub(crate) mod r#mint_max_voter_weight_source; +pub(crate) mod r#multi_choice_type; +pub(crate) mod r#native_treasury; +pub(crate) mod r#option_vote_result; +pub(crate) mod r#proposal_option; +pub(crate) mod r#proposal_state; +pub(crate) mod r#realm_config; +pub(crate) mod r#realm_config_params; +pub(crate) mod r#realm_config_params_v1; +pub(crate) mod r#reserved110; +pub(crate) mod r#reserved119; +pub(crate) mod r#set_realm_authority_action; +pub(crate) mod r#slot; +pub(crate) mod r#transaction_execution_status; +pub(crate) mod r#unix_timestamp; +pub(crate) mod r#vote; +pub(crate) mod r#vote_choice; +pub(crate) mod r#vote_kind; +pub(crate) mod r#vote_threshold; +pub(crate) mod r#vote_tipping; +pub(crate) mod r#vote_type; +pub(crate) mod r#vote_weight_v1; + +pub use self::r#account_meta_data::*; +pub use self::r#governance_account_type::*; +pub use self::r#governance_config::*; +pub use self::r#governance_instruction_v1::*; +pub use self::r#governing_token_config::*; +pub use self::r#governing_token_config_account_args::*; +pub use self::r#governing_token_config_params::*; +pub use self::r#governing_token_type::*; +pub use self::r#instruction_data::*; +pub use self::r#instruction_execution_flags::*; +pub use self::r#mint_max_voter_weight_source::*; +pub use self::r#multi_choice_type::*; +pub use self::r#native_treasury::*; +pub use self::r#option_vote_result::*; +pub use self::r#proposal_option::*; +pub use self::r#proposal_state::*; +pub use self::r#realm_config::*; +pub use self::r#realm_config_params::*; +pub use self::r#realm_config_params_v1::*; +pub use self::r#reserved110::*; +pub use self::r#reserved119::*; +pub use self::r#set_realm_authority_action::*; +pub use self::r#slot::*; +pub use self::r#transaction_execution_status::*; +pub use self::r#unix_timestamp::*; +pub use self::r#vote::*; +pub use self::r#vote_choice::*; +pub use self::r#vote_kind::*; +pub use self::r#vote_threshold::*; +pub use self::r#vote_tipping::*; +pub use self::r#vote_type::*; +pub use self::r#vote_weight_v1::*; diff --git a/e2e/governance/src/generated/types/multi_choice_type.rs b/e2e/governance/src/generated/types/multi_choice_type.rs new file mode 100644 index 0000000..711e515 --- /dev/null +++ b/e2e/governance/src/generated/types/multi_choice_type.rs @@ -0,0 +1,28 @@ +//! This code was AUTOGENERATED using the codama library. +//! Please DO NOT EDIT THIS FILE, instead use visitors +//! to add features, then rerun codama to update it. +//! +//! +//! + +use borsh::BorshDeserialize; +use borsh::BorshSerialize; +use num_derive::FromPrimitive; + +#[derive( + BorshSerialize, + BorshDeserialize, + Clone, + Debug, + Eq, + PartialEq, + Copy, + PartialOrd, + Hash, + FromPrimitive, +)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub enum MultiChoiceType { + FullWeight, + Weighted, +} diff --git a/e2e/governance/src/generated/types/native_treasury.rs b/e2e/governance/src/generated/types/native_treasury.rs new file mode 100644 index 0000000..5fa3f7c --- /dev/null +++ b/e2e/governance/src/generated/types/native_treasury.rs @@ -0,0 +1,13 @@ +//! This code was AUTOGENERATED using the codama library. +//! Please DO NOT EDIT THIS FILE, instead use visitors +//! to add features, then rerun codama to update it. +//! +//! +//! + +use borsh::BorshDeserialize; +use borsh::BorshSerialize; + +#[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct NativeTreasury {} diff --git a/e2e/governance/src/generated/types/option_vote_result.rs b/e2e/governance/src/generated/types/option_vote_result.rs new file mode 100644 index 0000000..395fc8d --- /dev/null +++ b/e2e/governance/src/generated/types/option_vote_result.rs @@ -0,0 +1,29 @@ +//! This code was AUTOGENERATED using the codama library. +//! Please DO NOT EDIT THIS FILE, instead use visitors +//! to add features, then rerun codama to update it. +//! +//! +//! + +use borsh::BorshDeserialize; +use borsh::BorshSerialize; +use num_derive::FromPrimitive; + +#[derive( + BorshSerialize, + BorshDeserialize, + Clone, + Debug, + Eq, + PartialEq, + Copy, + PartialOrd, + Hash, + FromPrimitive, +)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub enum OptionVoteResult { + None, + Succeeded, + Defeated, +} diff --git a/e2e/governance/src/generated/types/proposal_option.rs b/e2e/governance/src/generated/types/proposal_option.rs new file mode 100644 index 0000000..e594325 --- /dev/null +++ b/e2e/governance/src/generated/types/proposal_option.rs @@ -0,0 +1,21 @@ +//! This code was AUTOGENERATED using the codama library. +//! Please DO NOT EDIT THIS FILE, instead use visitors +//! to add features, then rerun codama to update it. +//! +//! +//! + +use crate::generated::types::OptionVoteResult; +use borsh::BorshDeserialize; +use borsh::BorshSerialize; + +#[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct ProposalOption { + pub label: String, + pub vote_weight: u64, + pub vote_result: OptionVoteResult, + pub transactions_executed_count: u16, + pub transactions_count: u16, + pub transactions_next_index: u16, +} diff --git a/e2e/governance/src/generated/types/proposal_state.rs b/e2e/governance/src/generated/types/proposal_state.rs new file mode 100644 index 0000000..21ca864 --- /dev/null +++ b/e2e/governance/src/generated/types/proposal_state.rs @@ -0,0 +1,36 @@ +//! This code was AUTOGENERATED using the codama library. +//! Please DO NOT EDIT THIS FILE, instead use visitors +//! to add features, then rerun codama to update it. +//! +//! +//! + +use borsh::BorshDeserialize; +use borsh::BorshSerialize; +use num_derive::FromPrimitive; + +#[derive( + BorshSerialize, + BorshDeserialize, + Clone, + Debug, + Eq, + PartialEq, + Copy, + PartialOrd, + Hash, + FromPrimitive, +)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub enum ProposalState { + Draft, + SigningOff, + Voting, + Succeeded, + Executing, + Completed, + Cancelled, + Defeated, + ExecutingWithErrors, + Vetoed, +} diff --git a/e2e/governance/src/generated/types/realm_config.rs b/e2e/governance/src/generated/types/realm_config.rs new file mode 100644 index 0000000..c102325 --- /dev/null +++ b/e2e/governance/src/generated/types/realm_config.rs @@ -0,0 +1,22 @@ +//! This code was AUTOGENERATED using the codama library. +//! Please DO NOT EDIT THIS FILE, instead use visitors +//! to add features, then rerun codama to update it. +//! +//! +//! + +use crate::generated::types::MintMaxVoterWeightSource; +use borsh::BorshDeserialize; +use borsh::BorshSerialize; +use solana_pubkey::Pubkey; + +#[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct RealmConfig { + pub legacy1: u8, + pub legacy2: u8, + pub reserved: [u8; 6], + pub min_community_weight_to_create_governance: u64, + pub community_mint_max_voter_weight_source: MintMaxVoterWeightSource, + pub council_mint: Option, +} diff --git a/e2e/governance/src/generated/types/realm_config_params.rs b/e2e/governance/src/generated/types/realm_config_params.rs new file mode 100644 index 0000000..7675c7d --- /dev/null +++ b/e2e/governance/src/generated/types/realm_config_params.rs @@ -0,0 +1,21 @@ +//! This code was AUTOGENERATED using the codama library. +//! Please DO NOT EDIT THIS FILE, instead use visitors +//! to add features, then rerun codama to update it. +//! +//! +//! + +use crate::generated::types::GoverningTokenConfigParams; +use crate::generated::types::MintMaxVoterWeightSource; +use borsh::BorshDeserialize; +use borsh::BorshSerialize; + +#[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct RealmConfigParams { + pub use_council_mint: bool, + pub min_community_weight_to_create_governance: u64, + pub community_mint_max_voter_weight_source: MintMaxVoterWeightSource, + pub community_token_config_args: GoverningTokenConfigParams, + pub council_token_config_args: GoverningTokenConfigParams, +} diff --git a/e2e/governance/src/generated/types/realm_config_params_v1.rs b/e2e/governance/src/generated/types/realm_config_params_v1.rs new file mode 100644 index 0000000..3c5ad52 --- /dev/null +++ b/e2e/governance/src/generated/types/realm_config_params_v1.rs @@ -0,0 +1,18 @@ +//! This code was AUTOGENERATED using the codama library. +//! Please DO NOT EDIT THIS FILE, instead use visitors +//! to add features, then rerun codama to update it. +//! +//! +//! + +use crate::generated::types::MintMaxVoterWeightSource; +use borsh::BorshDeserialize; +use borsh::BorshSerialize; + +#[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct RealmConfigParamsV1 { + pub use_council_mint: bool, + pub min_community_weight_to_create_governance: u64, + pub community_mint_max_voter_weight_source: MintMaxVoterWeightSource, +} diff --git a/e2e/governance/src/generated/types/reserved110.rs b/e2e/governance/src/generated/types/reserved110.rs new file mode 100644 index 0000000..3f64489 --- /dev/null +++ b/e2e/governance/src/generated/types/reserved110.rs @@ -0,0 +1,18 @@ +//! This code was AUTOGENERATED using the codama library. +//! Please DO NOT EDIT THIS FILE, instead use visitors +//! to add features, then rerun codama to update it. +//! +//! +//! + +use borsh::BorshDeserialize; +use borsh::BorshSerialize; + +#[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct Reserved110 { + #[cfg_attr(feature = "serde", serde(with = "serde_big_array::BigArray"))] + pub reserved64: [u8; 64], + pub reserved32: [u8; 32], + pub reserved14: [u8; 14], +} diff --git a/e2e/governance/src/generated/types/reserved119.rs b/e2e/governance/src/generated/types/reserved119.rs new file mode 100644 index 0000000..e669cd9 --- /dev/null +++ b/e2e/governance/src/generated/types/reserved119.rs @@ -0,0 +1,18 @@ +//! This code was AUTOGENERATED using the codama library. +//! Please DO NOT EDIT THIS FILE, instead use visitors +//! to add features, then rerun codama to update it. +//! +//! +//! + +use borsh::BorshDeserialize; +use borsh::BorshSerialize; + +#[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct Reserved119 { + #[cfg_attr(feature = "serde", serde(with = "serde_big_array::BigArray"))] + pub reserved64: [u8; 64], + pub reserved32: [u8; 32], + pub reserved23: [u8; 23], +} diff --git a/e2e/governance/src/generated/types/set_realm_authority_action.rs b/e2e/governance/src/generated/types/set_realm_authority_action.rs new file mode 100644 index 0000000..10f16ab --- /dev/null +++ b/e2e/governance/src/generated/types/set_realm_authority_action.rs @@ -0,0 +1,29 @@ +//! This code was AUTOGENERATED using the codama library. +//! Please DO NOT EDIT THIS FILE, instead use visitors +//! to add features, then rerun codama to update it. +//! +//! +//! + +use borsh::BorshDeserialize; +use borsh::BorshSerialize; +use num_derive::FromPrimitive; + +#[derive( + BorshSerialize, + BorshDeserialize, + Clone, + Debug, + Eq, + PartialEq, + Copy, + PartialOrd, + Hash, + FromPrimitive, +)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub enum SetRealmAuthorityAction { + SetUnchecked, + SetChecked, + Remove, +} diff --git a/e2e/governance/src/generated/types/slot.rs b/e2e/governance/src/generated/types/slot.rs new file mode 100644 index 0000000..f804032 --- /dev/null +++ b/e2e/governance/src/generated/types/slot.rs @@ -0,0 +1,8 @@ +//! This code was AUTOGENERATED using the codama library. +//! Please DO NOT EDIT THIS FILE, instead use visitors +//! to add features, then rerun codama to update it. +//! +//! +//! + +pub type Slot = u64; diff --git a/e2e/governance/src/generated/types/transaction_execution_status.rs b/e2e/governance/src/generated/types/transaction_execution_status.rs new file mode 100644 index 0000000..af34c69 --- /dev/null +++ b/e2e/governance/src/generated/types/transaction_execution_status.rs @@ -0,0 +1,29 @@ +//! This code was AUTOGENERATED using the codama library. +//! Please DO NOT EDIT THIS FILE, instead use visitors +//! to add features, then rerun codama to update it. +//! +//! +//! + +use borsh::BorshDeserialize; +use borsh::BorshSerialize; +use num_derive::FromPrimitive; + +#[derive( + BorshSerialize, + BorshDeserialize, + Clone, + Debug, + Eq, + PartialEq, + Copy, + PartialOrd, + Hash, + FromPrimitive, +)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub enum TransactionExecutionStatus { + None, + Success, + Error, +} diff --git a/e2e/governance/src/generated/types/unix_timestamp.rs b/e2e/governance/src/generated/types/unix_timestamp.rs new file mode 100644 index 0000000..62d0860 --- /dev/null +++ b/e2e/governance/src/generated/types/unix_timestamp.rs @@ -0,0 +1,8 @@ +//! This code was AUTOGENERATED using the codama library. +//! Please DO NOT EDIT THIS FILE, instead use visitors +//! to add features, then rerun codama to update it. +//! +//! +//! + +pub type UnixTimestamp = i64; diff --git a/e2e/governance/src/generated/types/vote.rs b/e2e/governance/src/generated/types/vote.rs new file mode 100644 index 0000000..6f1aa4f --- /dev/null +++ b/e2e/governance/src/generated/types/vote.rs @@ -0,0 +1,19 @@ +//! This code was AUTOGENERATED using the codama library. +//! Please DO NOT EDIT THIS FILE, instead use visitors +//! to add features, then rerun codama to update it. +//! +//! +//! + +use crate::generated::types::VoteChoice; +use borsh::BorshDeserialize; +use borsh::BorshSerialize; + +#[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub enum Vote { + Approve(Vec), + Deny, + Abstain, + Veto, +} diff --git a/e2e/governance/src/generated/types/vote_choice.rs b/e2e/governance/src/generated/types/vote_choice.rs new file mode 100644 index 0000000..e6459ce --- /dev/null +++ b/e2e/governance/src/generated/types/vote_choice.rs @@ -0,0 +1,16 @@ +//! This code was AUTOGENERATED using the codama library. +//! Please DO NOT EDIT THIS FILE, instead use visitors +//! to add features, then rerun codama to update it. +//! +//! +//! + +use borsh::BorshDeserialize; +use borsh::BorshSerialize; + +#[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct VoteChoice { + pub rank: u8, + pub weight_percentage: u8, +} diff --git a/e2e/governance/src/generated/types/vote_kind.rs b/e2e/governance/src/generated/types/vote_kind.rs new file mode 100644 index 0000000..51d6ef8 --- /dev/null +++ b/e2e/governance/src/generated/types/vote_kind.rs @@ -0,0 +1,28 @@ +//! This code was AUTOGENERATED using the codama library. +//! Please DO NOT EDIT THIS FILE, instead use visitors +//! to add features, then rerun codama to update it. +//! +//! +//! + +use borsh::BorshDeserialize; +use borsh::BorshSerialize; +use num_derive::FromPrimitive; + +#[derive( + BorshSerialize, + BorshDeserialize, + Clone, + Debug, + Eq, + PartialEq, + Copy, + PartialOrd, + Hash, + FromPrimitive, +)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub enum VoteKind { + Electorate, + Veto, +} diff --git a/e2e/governance/src/generated/types/vote_threshold.rs b/e2e/governance/src/generated/types/vote_threshold.rs new file mode 100644 index 0000000..e608373 --- /dev/null +++ b/e2e/governance/src/generated/types/vote_threshold.rs @@ -0,0 +1,17 @@ +//! This code was AUTOGENERATED using the codama library. +//! Please DO NOT EDIT THIS FILE, instead use visitors +//! to add features, then rerun codama to update it. +//! +//! +//! + +use borsh::BorshDeserialize; +use borsh::BorshSerialize; + +#[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub enum VoteThreshold { + YesVotePercentage(u8), + QuorumPercentage(u8), + Disabled, +} diff --git a/e2e/governance/src/generated/types/vote_tipping.rs b/e2e/governance/src/generated/types/vote_tipping.rs new file mode 100644 index 0000000..5c5a149 --- /dev/null +++ b/e2e/governance/src/generated/types/vote_tipping.rs @@ -0,0 +1,29 @@ +//! This code was AUTOGENERATED using the codama library. +//! Please DO NOT EDIT THIS FILE, instead use visitors +//! to add features, then rerun codama to update it. +//! +//! +//! + +use borsh::BorshDeserialize; +use borsh::BorshSerialize; +use num_derive::FromPrimitive; + +#[derive( + BorshSerialize, + BorshDeserialize, + Clone, + Debug, + Eq, + PartialEq, + Copy, + PartialOrd, + Hash, + FromPrimitive, +)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub enum VoteTipping { + Strict, + Early, + Disabled, +} diff --git a/e2e/governance/src/generated/types/vote_type.rs b/e2e/governance/src/generated/types/vote_type.rs new file mode 100644 index 0000000..16266c2 --- /dev/null +++ b/e2e/governance/src/generated/types/vote_type.rs @@ -0,0 +1,22 @@ +//! This code was AUTOGENERATED using the codama library. +//! Please DO NOT EDIT THIS FILE, instead use visitors +//! to add features, then rerun codama to update it. +//! +//! +//! + +use crate::generated::types::MultiChoiceType; +use borsh::BorshDeserialize; +use borsh::BorshSerialize; + +#[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub enum VoteType { + SingleChoice, + MultiChoice { + choice_type: MultiChoiceType, + min_voter_options: u8, + max_voter_options: u8, + max_winning_options: u8, + }, +} diff --git a/e2e/governance/src/generated/types/vote_weight_v1.rs b/e2e/governance/src/generated/types/vote_weight_v1.rs new file mode 100644 index 0000000..bb13f94 --- /dev/null +++ b/e2e/governance/src/generated/types/vote_weight_v1.rs @@ -0,0 +1,16 @@ +//! This code was AUTOGENERATED using the codama library. +//! Please DO NOT EDIT THIS FILE, instead use visitors +//! to add features, then rerun codama to update it. +//! +//! +//! + +use borsh::BorshDeserialize; +use borsh::BorshSerialize; + +#[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub enum VoteWeightV1 { + Yes(u64), + No(u64), +} diff --git a/e2e/governance/src/lib.rs b/e2e/governance/src/lib.rs new file mode 100644 index 0000000..19f9287 --- /dev/null +++ b/e2e/governance/src/lib.rs @@ -0,0 +1,4 @@ +mod generated; + +pub use generated::programs::SPL_GOVERNANCE_ID as ID; +pub use generated::*; diff --git a/src/getRenderMapVisitor.ts b/src/getRenderMapVisitor.ts index 55e65a1..0b94fe2 100644 --- a/src/getRenderMapVisitor.ts +++ b/src/getRenderMapVisitor.ts @@ -3,12 +3,12 @@ import { getAllAccounts, getAllDefinedTypes, getAllInstructionsWithSubs, + getAllPdas, getAllPrograms, InstructionNode, isNode, isNodeFilter, pascalCase, - ProgramNode, resolveNestedTypeNode, snakeCase, structTypeNodeFromInstructionArgumentNodes, @@ -17,6 +17,7 @@ import { import { addToRenderMap, createRenderMap, mergeRenderMaps } from '@codama/renderers-core'; import { extendVisitor, + findProgramNodeFromPath, LinkableDictionary, NodeStack, pipe, @@ -53,7 +54,6 @@ export type GetRenderMapOptions = { export function getRenderMapVisitor(options: GetRenderMapOptions = {}) { const linkables = new LinkableDictionary(); const stack = new NodeStack(); - let program: ProgramNode | null = null; const renderParentInstructions = options.renderParentInstructions ?? false; const dependencyMap = options.dependencyMap ?? {}; @@ -68,11 +68,16 @@ export function getRenderMapVisitor(options: GetRenderMapOptions = {}) { return pipe( staticVisitor(() => createRenderMap(), { - keys: ['rootNode', 'programNode', 'instructionNode', 'accountNode', 'definedTypeNode'], + keys: ['rootNode', 'programNode', 'instructionNode', 'accountNode', 'definedTypeNode', 'pdaNode'], }), v => extendVisitor(v, { visitAccount(node) { + const accountPath = stack.getPath('accountNode'); + const program = findProgramNodeFromPath(accountPath); + if (!program) { + throw new Error('Account must be visited inside a program.'); + } const typeManifest = visit(node, typeManifestVisitor); // Discriminator constants. @@ -149,6 +154,11 @@ export function getRenderMapVisitor(options: GetRenderMapOptions = {}) { }, visitInstruction(node) { + const instructionPath = stack.getPath('instructionNode'); + const program = findProgramNodeFromPath(instructionPath); + if (!program) { + throw new Error('Instruction must be visited inside a program.'); + } // Imports. const imports = new ImportMap(); @@ -255,14 +265,61 @@ export function getRenderMapVisitor(options: GetRenderMapOptions = {}) { }); }, + visitPda(node) { + const pdaPath = stack.getPath('pdaNode'); + const program = findProgramNodeFromPath(pdaPath); + if (!program) { + throw new Error('PDA must be visited inside a program.'); + } + const imports = new ImportMap(); + + // Process seeds + const seeds = node.seeds.map(seed => { + if (isNode(seed, 'variablePdaSeedNode')) { + const seedManifest = visit(seed.type, typeManifestVisitor); + imports.mergeWith(seedManifest.imports); + const resolvedType = resolveNestedTypeNode(seed.type); + return { ...seed, resolvedType, typeManifest: seedManifest }; + } + if (isNode(seed.value, 'programIdValueNode')) { + return seed; + } + const seedManifest = visit(seed.type, typeManifestVisitor); + const valueManifest = renderValueNode(seed.value, getImportFrom, true); + imports.mergeWith(valueManifest.imports); + const resolvedType = resolveNestedTypeNode(seed.type); + return { ...seed, resolvedType, typeManifest: seedManifest, valueManifest }; + }); + + const hasVariableSeeds = node.seeds.filter(isNodeFilter('variablePdaSeedNode')).length > 0; + const constantSeeds = seeds + .filter(isNodeFilter('constantPdaSeedNode')) + .filter(seed => !isNode(seed.value, 'programIdValueNode')); + + const programAddress = node.programId ?? program?.publicKey; + + return createRenderMap(`pdas/${snakeCase(node.name)}.rs`, { + content: render('pdasPage.njk', { + constantSeeds, + hasVariableSeeds, + imports: imports.toString(dependencyMap), + pda: node, + program, + programAddress, + seeds, + }), + imports, + }); + }, + visitProgram(node, { self }) { - program = node; let renders = mergeRenderMaps([ ...node.accounts.map(account => visit(account, self)), ...node.definedTypes.map(type => visit(type, self)), ...getAllInstructionsWithSubs(node, { leavesOnly: !renderParentInstructions, }).map(ix => visit(ix, self)), + ...node.pdas.map(pda => visit(pda, self)), ]); // Errors. @@ -277,7 +334,6 @@ export function getRenderMapVisitor(options: GetRenderMapOptions = {}) { }); } - program = null; return renders; }, @@ -287,6 +343,7 @@ export function getRenderMapVisitor(options: GetRenderMapOptions = {}) { const instructionsToExport = getAllInstructionsWithSubs(node, { leavesOnly: !renderParentInstructions, }); + const pdasToExport = getAllPdas(node); const definedTypesToExport = getAllDefinedTypes(node); const hasAnythingToExport = programsToExport.length > 0 || @@ -299,6 +356,7 @@ export function getRenderMapVisitor(options: GetRenderMapOptions = {}) { definedTypesToExport, hasAnythingToExport, instructionsToExport, + pdasToExport, programsToExport, root: node, }; @@ -318,6 +376,10 @@ export function getRenderMapVisitor(options: GetRenderMapOptions = {}) { ? { content: render('instructionsMod.njk', ctx), imports: new ImportMap() } : undefined, ['mod.rs']: { content: render('rootMod.njk', ctx), imports: new ImportMap() }, + ['pdas/mod.rs']: + pdasToExport.length > 0 + ? { content: render('pdasMod.njk', ctx), imports: new ImportMap() } + : undefined, ['programs.rs']: programsToExport.length > 0 ? { content: render('programsMod.njk', ctx), imports: new ImportMap() } diff --git a/src/utils/render.ts b/src/utils/render.ts index 0dcff19..df8a24a 100644 --- a/src/utils/render.ts +++ b/src/utils/render.ts @@ -6,7 +6,7 @@ import nunjucks, { ConfigureOptions as NunJucksOptions } from 'nunjucks'; export function rustDocblock(docs: string[]): string { if (docs.length <= 0) return ''; - const lines = docs.map(doc => `/// ${doc}`); + const lines = docs.flatMap(doc => doc.split('\n')).map(doc => `/// ${doc}`); return `${lines.join('\n')}\n`; } diff --git a/test/pdasPage.test.ts b/test/pdasPage.test.ts new file mode 100644 index 0000000..99cfd37 --- /dev/null +++ b/test/pdasPage.test.ts @@ -0,0 +1,163 @@ +import { + constantPdaSeedNodeFromString, + constantPdaSeedNode, + pdaNode, + programNode, + publicKeyTypeNode, + variablePdaSeedNode, + numberTypeNode, + numberValueNode, + bytesTypeNode, + fixedSizeTypeNode, + rootNode, +} from '@codama/nodes'; +import { getFromRenderMap } from '@codama/renderers-core'; +import { visit } from '@codama/visitors-core'; +import { test } from 'vitest'; + +import { getRenderMapVisitor } from '../src'; +import { codeContains } from './_setup'; + +test('it renders a standalone PDA with variable seeds', () => { + // Given a program with a PDA that has variable seeds. + const node = programNode({ + name: 'myProgram', + publicKey: 'TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA', + pdas: [ + pdaNode({ + name: 'myPda', + seeds: [ + constantPdaSeedNodeFromString('utf8', 'metadata'), + variablePdaSeedNode('mint', publicKeyTypeNode()), + ], + }), + ], + }); + + // When we render it. + const renderMap = visit(node, getRenderMapVisitor()); + + // Then we expect a standalone PDA file to be created. + codeContains(getFromRenderMap(renderMap, 'pdas/my_pda.rs'), [ + 'pub const MY_PDA_SEED: &\'static [u8] = b"metadata";', + 'pub fn create_my_pda_pda(', + 'mint: solana_pubkey::Pubkey,', + 'bump: u8,', + 'pub fn find_my_pda_pda(', + 'mint: &solana_pubkey::Pubkey,', + '-> (solana_pubkey::Pubkey, u8)', + ]); +}); + +test('it renders a PDA with only constant seeds', () => { + // Given a program with a PDA that has only constant seeds. + const node = programNode({ + name: 'myProgram', + publicKey: 'TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA', + pdas: [ + pdaNode({ + name: 'configPda', + seeds: [ + constantPdaSeedNodeFromString('utf8', 'config'), + constantPdaSeedNode(numberTypeNode('u64'), numberValueNode(1)), + ], + }), + ], + }); + + // When we render it. + const renderMap = visit(node, getRenderMapVisitor()); + + // Then we expect the PDA functions without variable parameters. + codeContains(getFromRenderMap(renderMap, 'pdas/config_pda.rs'), [ + 'pub const CONFIG_PDA_SEED_0: &\'static [u8] = b"config";', + 'pub const CONFIG_PDA_SEED_1: &\'static [u8] = b1;', + 'pub fn create_config_pda_pda(', + 'bump: u8,', + 'pub fn find_config_pda_pda(', + ') -> (solana_pubkey::Pubkey, u8)', + ]); +}); + +test('it renders a PDA with byte array seeds', () => { + // Given a program with a PDA that has byte array seeds. + const node = programNode({ + name: 'myProgram', + publicKey: 'TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA', + pdas: [ + pdaNode({ + name: 'hashPda', + seeds: [ + constantPdaSeedNodeFromString('utf8', 'hash'), + variablePdaSeedNode('dataHash', fixedSizeTypeNode(bytesTypeNode(), 32)), + ], + }), + ], + }); + + // When we render it. + const renderMap = visit(node, getRenderMapVisitor()); + + // Then we expect the byte array to be handled correctly. + codeContains(getFromRenderMap(renderMap, 'pdas/hash_pda.rs'), [ + 'pub const HASH_PDA_SEED: &\'static [u8] = b"hash";', + 'pub fn create_hash_pda_pda(', + 'data_hash: [u8; 32],', + '&data_hash,', + 'pub fn find_hash_pda_pda(', + 'data_hash: [u8; 32],', + ]); +}); + +test('it renders a PDA module file', () => { + // Given a root node with a program containing multiple PDAs. + const program = programNode({ + name: 'myProgram', + publicKey: 'TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA', + pdas: [ + pdaNode({ + name: 'firstPda', + seeds: [constantPdaSeedNodeFromString('utf8', 'first')], + }), + pdaNode({ + name: 'secondPda', + seeds: [constantPdaSeedNodeFromString('utf8', 'second')], + }), + ], + }); + const node = rootNode(program); + + // When we render it. + const renderMap = visit(node, getRenderMapVisitor()); + + // Then we expect a module file to be created. + codeContains(getFromRenderMap(renderMap, 'pdas/mod.rs'), [ + 'pub mod first_pda;', + 'pub mod second_pda;', + 'pub use self::first_pda::*;', + 'pub use self::second_pda::*;', + ]); +}); + +test('it includes PDAs module in the root mod file', () => { + // Given a root node with a program containing PDAs. + const program = programNode({ + name: 'myProgram', + publicKey: 'TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA', + pdas: [ + pdaNode({ + name: 'myPda', + seeds: [constantPdaSeedNodeFromString('utf8', 'test')], + }), + ], + }); + const node = rootNode(program); + + // When we render it. + const renderMap = visit(node, getRenderMapVisitor()); + + // Then we expect the pdas module to be included in the root mod. + codeContains(getFromRenderMap(renderMap, 'mod.rs'), [ + 'pub mod pdas;', + ]); +}); \ No newline at end of file From aa65f2124ca217b90524ea981c89905374f9079a Mon Sep 17 00:00:00 2001 From: Ian Macalinao Date: Thu, 9 Oct 2025 12:34:12 +0800 Subject: [PATCH 11/24] add governance to test projects --- e2e/test.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/e2e/test.sh b/e2e/test.sh index 498b7a4..8274c91 100755 --- a/e2e/test.sh +++ b/e2e/test.sh @@ -18,5 +18,6 @@ function test_anchor_project() { test_project dummy test_project system test_project memo +test_project governance # test_project meteora # TODO: uncomment after some internal fixes test_anchor_project anchor \ No newline at end of file From bd00d41c6c3b35253934a8546c9fd29a2b3e3c3c Mon Sep 17 00:00:00 2001 From: Ian Macalinao Date: Thu, 9 Oct 2025 12:41:05 +0800 Subject: [PATCH 12/24] fix generation again --- .changeset/tired-rules-rule.md | 5 ++ e2e/governance/src/generated/mod.rs | 1 + .../generated/pdas/community_token_holding.rs | 40 ++++++++-------- .../generated/pdas/council_token_holding.rs | 40 ++++++++-------- .../src/generated/pdas/governance.rs | 37 +++++--------- .../generated/pdas/governing_token_holding.rs | 40 ++++++++-------- e2e/governance/src/generated/pdas/mod.rs | 28 +++++++++++ .../src/generated/pdas/native_treasury.rs | 31 ++++-------- e2e/governance/src/generated/pdas/proposal.rs | 48 +++++++++---------- .../src/generated/pdas/proposal_deposit.rs | 40 ++++++++-------- .../generated/pdas/proposal_transaction.rs | 48 +++++++++---------- e2e/governance/src/generated/pdas/realm.rs | 31 ++++-------- .../src/generated/pdas/realm_config.rs | 31 ++++-------- .../src/generated/pdas/required_signatory.rs | 40 ++++++++-------- .../src/generated/pdas/signatory_record.rs | 38 +++++++-------- .../src/generated/pdas/token_owner_record.rs | 48 +++++++++---------- .../src/generated/pdas/vote_record.rs | 40 ++++++++-------- test/pdasPage.test.ts | 25 +++++----- 18 files changed, 290 insertions(+), 321 deletions(-) create mode 100644 .changeset/tired-rules-rule.md diff --git a/.changeset/tired-rules-rule.md b/.changeset/tired-rules-rule.md new file mode 100644 index 0000000..6574b56 --- /dev/null +++ b/.changeset/tired-rules-rule.md @@ -0,0 +1,5 @@ +--- +'@codama/renderers-rust': patch +--- + +Add support for PDA generation diff --git a/e2e/governance/src/generated/mod.rs b/e2e/governance/src/generated/mod.rs index e0d740a..d37d822 100644 --- a/e2e/governance/src/generated/mod.rs +++ b/e2e/governance/src/generated/mod.rs @@ -8,6 +8,7 @@ pub mod accounts; pub mod errors; pub mod instructions; +pub mod pdas; pub mod programs; pub mod shared; pub mod types; diff --git a/e2e/governance/src/generated/pdas/community_token_holding.rs b/e2e/governance/src/generated/pdas/community_token_holding.rs index 889d1b9..ebc98bb 100644 --- a/e2e/governance/src/generated/pdas/community_token_holding.rs +++ b/e2e/governance/src/generated/pdas/community_token_holding.rs @@ -7,36 +7,34 @@ use crate::SPL_GOVERNANCE_ID; +pub const COMMUNITY_TOKEN_HOLDING_SEED: &'static [u8] = b"governance"; - pub const COMMUNITY_TOKEN_HOLDING_SEED: &'static [u8] = b"governance"; - pub fn create_community_token_holding_pda( - realm: solana_pubkey::Pubkey, - community_mint: solana_pubkey::Pubkey, - bump: u8, + realm: solana_pubkey::Pubkey, + community_mint: solana_pubkey::Pubkey, + bump: u8, ) -> Result { solana_pubkey::Pubkey::create_program_address( &[ - COMMUNITY_TOKEN_HOLDING_SEED, - realm.as_ref(), - community_mint.as_ref(), - &[bump], + COMMUNITY_TOKEN_HOLDING_SEED, + realm.as_ref(), + community_mint.as_ref(), + &[bump], ], - &SPL_GOVERNANCE_ID, - ) + &SPL_GOVERNANCE_ID, + ) } pub fn find_community_token_holding_pda( - realm: &solana_pubkey::Pubkey, - community_mint: &solana_pubkey::Pubkey, - ) -> (solana_pubkey::Pubkey, u8) { + realm: &solana_pubkey::Pubkey, + community_mint: &solana_pubkey::Pubkey, +) -> (solana_pubkey::Pubkey, u8) { solana_pubkey::Pubkey::find_program_address( &[ - COMMUNITY_TOKEN_HOLDING_SEED, - realm.as_ref(), - community_mint.as_ref(), - ], - &SPL_GOVERNANCE_ID, - ) + COMMUNITY_TOKEN_HOLDING_SEED, + realm.as_ref(), + community_mint.as_ref(), + ], + &SPL_GOVERNANCE_ID, + ) } - diff --git a/e2e/governance/src/generated/pdas/council_token_holding.rs b/e2e/governance/src/generated/pdas/council_token_holding.rs index 85e0a52..b5da294 100644 --- a/e2e/governance/src/generated/pdas/council_token_holding.rs +++ b/e2e/governance/src/generated/pdas/council_token_holding.rs @@ -7,36 +7,34 @@ use crate::SPL_GOVERNANCE_ID; +pub const COUNCIL_TOKEN_HOLDING_SEED: &'static [u8] = b"governance"; - pub const COUNCIL_TOKEN_HOLDING_SEED: &'static [u8] = b"governance"; - pub fn create_council_token_holding_pda( - realm: solana_pubkey::Pubkey, - council_mint: solana_pubkey::Pubkey, - bump: u8, + realm: solana_pubkey::Pubkey, + council_mint: solana_pubkey::Pubkey, + bump: u8, ) -> Result { solana_pubkey::Pubkey::create_program_address( &[ - COUNCIL_TOKEN_HOLDING_SEED, - realm.as_ref(), - council_mint.as_ref(), - &[bump], + COUNCIL_TOKEN_HOLDING_SEED, + realm.as_ref(), + council_mint.as_ref(), + &[bump], ], - &SPL_GOVERNANCE_ID, - ) + &SPL_GOVERNANCE_ID, + ) } pub fn find_council_token_holding_pda( - realm: &solana_pubkey::Pubkey, - council_mint: &solana_pubkey::Pubkey, - ) -> (solana_pubkey::Pubkey, u8) { + realm: &solana_pubkey::Pubkey, + council_mint: &solana_pubkey::Pubkey, +) -> (solana_pubkey::Pubkey, u8) { solana_pubkey::Pubkey::find_program_address( &[ - COUNCIL_TOKEN_HOLDING_SEED, - realm.as_ref(), - council_mint.as_ref(), - ], - &SPL_GOVERNANCE_ID, - ) + COUNCIL_TOKEN_HOLDING_SEED, + realm.as_ref(), + council_mint.as_ref(), + ], + &SPL_GOVERNANCE_ID, + ) } - diff --git a/e2e/governance/src/generated/pdas/governance.rs b/e2e/governance/src/generated/pdas/governance.rs index f075a20..bf3bd2b 100644 --- a/e2e/governance/src/generated/pdas/governance.rs +++ b/e2e/governance/src/generated/pdas/governance.rs @@ -7,36 +7,25 @@ use crate::SPL_GOVERNANCE_ID; +pub const GOVERNANCE_SEED: &'static [u8] = b"account-governance"; - pub const GOVERNANCE_SEED: &'static [u8] = b"account-governance"; - pub fn create_governance_pda( - realm: solana_pubkey::Pubkey, - seed: solana_pubkey::Pubkey, - bump: u8, + realm: solana_pubkey::Pubkey, + seed: solana_pubkey::Pubkey, + bump: u8, ) -> Result { solana_pubkey::Pubkey::create_program_address( - &[ - GOVERNANCE_SEED, - realm.as_ref(), - seed.as_ref(), - &[bump], - ], - &SPL_GOVERNANCE_ID, - ) + &[GOVERNANCE_SEED, realm.as_ref(), seed.as_ref(), &[bump]], + &SPL_GOVERNANCE_ID, + ) } pub fn find_governance_pda( - realm: &solana_pubkey::Pubkey, - seed: &solana_pubkey::Pubkey, - ) -> (solana_pubkey::Pubkey, u8) { + realm: &solana_pubkey::Pubkey, + seed: &solana_pubkey::Pubkey, +) -> (solana_pubkey::Pubkey, u8) { solana_pubkey::Pubkey::find_program_address( - &[ - GOVERNANCE_SEED, - realm.as_ref(), - seed.as_ref(), - ], - &SPL_GOVERNANCE_ID, - ) + &[GOVERNANCE_SEED, realm.as_ref(), seed.as_ref()], + &SPL_GOVERNANCE_ID, + ) } - diff --git a/e2e/governance/src/generated/pdas/governing_token_holding.rs b/e2e/governance/src/generated/pdas/governing_token_holding.rs index 4a89c93..dfbe67f 100644 --- a/e2e/governance/src/generated/pdas/governing_token_holding.rs +++ b/e2e/governance/src/generated/pdas/governing_token_holding.rs @@ -7,36 +7,34 @@ use crate::SPL_GOVERNANCE_ID; +pub const GOVERNING_TOKEN_HOLDING_SEED: &'static [u8] = b"governance"; - pub const GOVERNING_TOKEN_HOLDING_SEED: &'static [u8] = b"governance"; - pub fn create_governing_token_holding_pda( - realm: solana_pubkey::Pubkey, - governing_token_mint: solana_pubkey::Pubkey, - bump: u8, + realm: solana_pubkey::Pubkey, + governing_token_mint: solana_pubkey::Pubkey, + bump: u8, ) -> Result { solana_pubkey::Pubkey::create_program_address( &[ - GOVERNING_TOKEN_HOLDING_SEED, - realm.as_ref(), - governing_token_mint.as_ref(), - &[bump], + GOVERNING_TOKEN_HOLDING_SEED, + realm.as_ref(), + governing_token_mint.as_ref(), + &[bump], ], - &SPL_GOVERNANCE_ID, - ) + &SPL_GOVERNANCE_ID, + ) } pub fn find_governing_token_holding_pda( - realm: &solana_pubkey::Pubkey, - governing_token_mint: &solana_pubkey::Pubkey, - ) -> (solana_pubkey::Pubkey, u8) { + realm: &solana_pubkey::Pubkey, + governing_token_mint: &solana_pubkey::Pubkey, +) -> (solana_pubkey::Pubkey, u8) { solana_pubkey::Pubkey::find_program_address( &[ - GOVERNING_TOKEN_HOLDING_SEED, - realm.as_ref(), - governing_token_mint.as_ref(), - ], - &SPL_GOVERNANCE_ID, - ) + GOVERNING_TOKEN_HOLDING_SEED, + realm.as_ref(), + governing_token_mint.as_ref(), + ], + &SPL_GOVERNANCE_ID, + ) } - diff --git a/e2e/governance/src/generated/pdas/mod.rs b/e2e/governance/src/generated/pdas/mod.rs index 8b13789..2fb9d5c 100644 --- a/e2e/governance/src/generated/pdas/mod.rs +++ b/e2e/governance/src/generated/pdas/mod.rs @@ -1 +1,29 @@ +pub mod community_token_holding; +pub mod council_token_holding; +pub mod governance; +pub mod governing_token_holding; +pub mod native_treasury; +pub mod proposal; +pub mod proposal_deposit; +pub mod proposal_transaction; +pub mod realm; +pub mod realm_config; +pub mod required_signatory; +pub mod signatory_record; +pub mod token_owner_record; +pub mod vote_record; +pub use self::community_token_holding::*; +pub use self::council_token_holding::*; +pub use self::governance::*; +pub use self::governing_token_holding::*; +pub use self::native_treasury::*; +pub use self::proposal::*; +pub use self::proposal_deposit::*; +pub use self::proposal_transaction::*; +pub use self::realm::*; +pub use self::realm_config::*; +pub use self::required_signatory::*; +pub use self::signatory_record::*; +pub use self::token_owner_record::*; +pub use self::vote_record::*; diff --git a/e2e/governance/src/generated/pdas/native_treasury.rs b/e2e/governance/src/generated/pdas/native_treasury.rs index 54e36f6..d9b7217 100644 --- a/e2e/governance/src/generated/pdas/native_treasury.rs +++ b/e2e/governance/src/generated/pdas/native_treasury.rs @@ -7,32 +7,21 @@ use crate::SPL_GOVERNANCE_ID; +pub const NATIVE_TREASURY_SEED: &'static [u8] = b"native-treasury"; - pub const NATIVE_TREASURY_SEED: &'static [u8] = b"native-treasury"; - pub fn create_native_treasury_pda( - governance: solana_pubkey::Pubkey, - bump: u8, + governance: solana_pubkey::Pubkey, + bump: u8, ) -> Result { solana_pubkey::Pubkey::create_program_address( - &[ - NATIVE_TREASURY_SEED, - governance.as_ref(), - &[bump], - ], - &SPL_GOVERNANCE_ID, - ) + &[NATIVE_TREASURY_SEED, governance.as_ref(), &[bump]], + &SPL_GOVERNANCE_ID, + ) } -pub fn find_native_treasury_pda( - governance: &solana_pubkey::Pubkey, - ) -> (solana_pubkey::Pubkey, u8) { +pub fn find_native_treasury_pda(governance: &solana_pubkey::Pubkey) -> (solana_pubkey::Pubkey, u8) { solana_pubkey::Pubkey::find_program_address( - &[ - NATIVE_TREASURY_SEED, - governance.as_ref(), - ], - &SPL_GOVERNANCE_ID, - ) + &[NATIVE_TREASURY_SEED, governance.as_ref()], + &SPL_GOVERNANCE_ID, + ) } - diff --git a/e2e/governance/src/generated/pdas/proposal.rs b/e2e/governance/src/generated/pdas/proposal.rs index 109bc99..2726eb4 100644 --- a/e2e/governance/src/generated/pdas/proposal.rs +++ b/e2e/governance/src/generated/pdas/proposal.rs @@ -7,40 +7,38 @@ use crate::SPL_GOVERNANCE_ID; +pub const PROPOSAL_SEED: &'static [u8] = b"governance"; - pub const PROPOSAL_SEED: &'static [u8] = b"governance"; - pub fn create_proposal_pda( - governance: solana_pubkey::Pubkey, - governing_token_mint: solana_pubkey::Pubkey, - proposal_seed: solana_pubkey::Pubkey, - bump: u8, + governance: solana_pubkey::Pubkey, + governing_token_mint: solana_pubkey::Pubkey, + proposal_seed: solana_pubkey::Pubkey, + bump: u8, ) -> Result { solana_pubkey::Pubkey::create_program_address( &[ - PROPOSAL_SEED, - governance.as_ref(), - governing_token_mint.as_ref(), - proposal_seed.as_ref(), - &[bump], + PROPOSAL_SEED, + governance.as_ref(), + governing_token_mint.as_ref(), + proposal_seed.as_ref(), + &[bump], ], - &SPL_GOVERNANCE_ID, - ) + &SPL_GOVERNANCE_ID, + ) } pub fn find_proposal_pda( - governance: &solana_pubkey::Pubkey, - governing_token_mint: &solana_pubkey::Pubkey, - proposal_seed: &solana_pubkey::Pubkey, - ) -> (solana_pubkey::Pubkey, u8) { + governance: &solana_pubkey::Pubkey, + governing_token_mint: &solana_pubkey::Pubkey, + proposal_seed: &solana_pubkey::Pubkey, +) -> (solana_pubkey::Pubkey, u8) { solana_pubkey::Pubkey::find_program_address( &[ - PROPOSAL_SEED, - governance.as_ref(), - governing_token_mint.as_ref(), - proposal_seed.as_ref(), - ], - &SPL_GOVERNANCE_ID, - ) + PROPOSAL_SEED, + governance.as_ref(), + governing_token_mint.as_ref(), + proposal_seed.as_ref(), + ], + &SPL_GOVERNANCE_ID, + ) } - diff --git a/e2e/governance/src/generated/pdas/proposal_deposit.rs b/e2e/governance/src/generated/pdas/proposal_deposit.rs index 207b043..83a1a1a 100644 --- a/e2e/governance/src/generated/pdas/proposal_deposit.rs +++ b/e2e/governance/src/generated/pdas/proposal_deposit.rs @@ -7,36 +7,34 @@ use crate::SPL_GOVERNANCE_ID; +pub const PROPOSAL_DEPOSIT_SEED: &'static [u8] = b"proposal-deposit"; - pub const PROPOSAL_DEPOSIT_SEED: &'static [u8] = b"proposal-deposit"; - pub fn create_proposal_deposit_pda( - proposal: solana_pubkey::Pubkey, - deposit_payer: solana_pubkey::Pubkey, - bump: u8, + proposal: solana_pubkey::Pubkey, + deposit_payer: solana_pubkey::Pubkey, + bump: u8, ) -> Result { solana_pubkey::Pubkey::create_program_address( &[ - PROPOSAL_DEPOSIT_SEED, - proposal.as_ref(), - deposit_payer.as_ref(), - &[bump], + PROPOSAL_DEPOSIT_SEED, + proposal.as_ref(), + deposit_payer.as_ref(), + &[bump], ], - &SPL_GOVERNANCE_ID, - ) + &SPL_GOVERNANCE_ID, + ) } pub fn find_proposal_deposit_pda( - proposal: &solana_pubkey::Pubkey, - deposit_payer: &solana_pubkey::Pubkey, - ) -> (solana_pubkey::Pubkey, u8) { + proposal: &solana_pubkey::Pubkey, + deposit_payer: &solana_pubkey::Pubkey, +) -> (solana_pubkey::Pubkey, u8) { solana_pubkey::Pubkey::find_program_address( &[ - PROPOSAL_DEPOSIT_SEED, - proposal.as_ref(), - deposit_payer.as_ref(), - ], - &SPL_GOVERNANCE_ID, - ) + PROPOSAL_DEPOSIT_SEED, + proposal.as_ref(), + deposit_payer.as_ref(), + ], + &SPL_GOVERNANCE_ID, + ) } - diff --git a/e2e/governance/src/generated/pdas/proposal_transaction.rs b/e2e/governance/src/generated/pdas/proposal_transaction.rs index a107021..7aee3c9 100644 --- a/e2e/governance/src/generated/pdas/proposal_transaction.rs +++ b/e2e/governance/src/generated/pdas/proposal_transaction.rs @@ -7,40 +7,38 @@ use crate::SPL_GOVERNANCE_ID; +pub const PROPOSAL_TRANSACTION_SEED: &'static [u8] = b"governance"; - pub const PROPOSAL_TRANSACTION_SEED: &'static [u8] = b"governance"; - pub fn create_proposal_transaction_pda( - proposal: solana_pubkey::Pubkey, - option_index: u8, - index: u16, - bump: u8, + proposal: solana_pubkey::Pubkey, + option_index: u8, + index: u16, + bump: u8, ) -> Result { solana_pubkey::Pubkey::create_program_address( &[ - PROPOSAL_TRANSACTION_SEED, - proposal.as_ref(), - option_index.to_string().as_ref(), - index.to_string().as_ref(), - &[bump], + PROPOSAL_TRANSACTION_SEED, + proposal.as_ref(), + option_index.to_string().as_ref(), + index.to_string().as_ref(), + &[bump], ], - &SPL_GOVERNANCE_ID, - ) + &SPL_GOVERNANCE_ID, + ) } pub fn find_proposal_transaction_pda( - proposal: &solana_pubkey::Pubkey, - option_index: u8, - index: u16, - ) -> (solana_pubkey::Pubkey, u8) { + proposal: &solana_pubkey::Pubkey, + option_index: u8, + index: u16, +) -> (solana_pubkey::Pubkey, u8) { solana_pubkey::Pubkey::find_program_address( &[ - PROPOSAL_TRANSACTION_SEED, - proposal.as_ref(), - option_index.to_string().as_ref(), - index.to_string().as_ref(), - ], - &SPL_GOVERNANCE_ID, - ) + PROPOSAL_TRANSACTION_SEED, + proposal.as_ref(), + option_index.to_string().as_ref(), + index.to_string().as_ref(), + ], + &SPL_GOVERNANCE_ID, + ) } - diff --git a/e2e/governance/src/generated/pdas/realm.rs b/e2e/governance/src/generated/pdas/realm.rs index 1d72486..de693bc 100644 --- a/e2e/governance/src/generated/pdas/realm.rs +++ b/e2e/governance/src/generated/pdas/realm.rs @@ -7,32 +7,21 @@ use crate::SPL_GOVERNANCE_ID; +pub const REALM_SEED: &'static [u8] = b"governance"; - pub const REALM_SEED: &'static [u8] = b"governance"; - pub fn create_realm_pda( - name: RemainderStr, - bump: u8, + name: RemainderStr, + bump: u8, ) -> Result { solana_pubkey::Pubkey::create_program_address( - &[ - REALM_SEED, - name.to_string().as_ref(), - &[bump], - ], - &SPL_GOVERNANCE_ID, - ) + &[REALM_SEED, name.to_string().as_ref(), &[bump]], + &SPL_GOVERNANCE_ID, + ) } -pub fn find_realm_pda( - name: RemainderStr, - ) -> (solana_pubkey::Pubkey, u8) { +pub fn find_realm_pda(name: RemainderStr) -> (solana_pubkey::Pubkey, u8) { solana_pubkey::Pubkey::find_program_address( - &[ - REALM_SEED, - name.to_string().as_ref(), - ], - &SPL_GOVERNANCE_ID, - ) + &[REALM_SEED, name.to_string().as_ref()], + &SPL_GOVERNANCE_ID, + ) } - diff --git a/e2e/governance/src/generated/pdas/realm_config.rs b/e2e/governance/src/generated/pdas/realm_config.rs index ee86683..ee7990c 100644 --- a/e2e/governance/src/generated/pdas/realm_config.rs +++ b/e2e/governance/src/generated/pdas/realm_config.rs @@ -7,32 +7,21 @@ use crate::SPL_GOVERNANCE_ID; +pub const REALM_CONFIG_SEED: &'static [u8] = b"realm-config"; - pub const REALM_CONFIG_SEED: &'static [u8] = b"realm-config"; - pub fn create_realm_config_pda( - realm: solana_pubkey::Pubkey, - bump: u8, + realm: solana_pubkey::Pubkey, + bump: u8, ) -> Result { solana_pubkey::Pubkey::create_program_address( - &[ - REALM_CONFIG_SEED, - realm.as_ref(), - &[bump], - ], - &SPL_GOVERNANCE_ID, - ) + &[REALM_CONFIG_SEED, realm.as_ref(), &[bump]], + &SPL_GOVERNANCE_ID, + ) } -pub fn find_realm_config_pda( - realm: &solana_pubkey::Pubkey, - ) -> (solana_pubkey::Pubkey, u8) { +pub fn find_realm_config_pda(realm: &solana_pubkey::Pubkey) -> (solana_pubkey::Pubkey, u8) { solana_pubkey::Pubkey::find_program_address( - &[ - REALM_CONFIG_SEED, - realm.as_ref(), - ], - &SPL_GOVERNANCE_ID, - ) + &[REALM_CONFIG_SEED, realm.as_ref()], + &SPL_GOVERNANCE_ID, + ) } - diff --git a/e2e/governance/src/generated/pdas/required_signatory.rs b/e2e/governance/src/generated/pdas/required_signatory.rs index f53afd5..2d906ad 100644 --- a/e2e/governance/src/generated/pdas/required_signatory.rs +++ b/e2e/governance/src/generated/pdas/required_signatory.rs @@ -7,36 +7,34 @@ use crate::SPL_GOVERNANCE_ID; +pub const REQUIRED_SIGNATORY_SEED: &'static [u8] = b"required-signatory"; - pub const REQUIRED_SIGNATORY_SEED: &'static [u8] = b"required-signatory"; - pub fn create_required_signatory_pda( - governance: solana_pubkey::Pubkey, - signatory: solana_pubkey::Pubkey, - bump: u8, + governance: solana_pubkey::Pubkey, + signatory: solana_pubkey::Pubkey, + bump: u8, ) -> Result { solana_pubkey::Pubkey::create_program_address( &[ - REQUIRED_SIGNATORY_SEED, - governance.as_ref(), - signatory.as_ref(), - &[bump], + REQUIRED_SIGNATORY_SEED, + governance.as_ref(), + signatory.as_ref(), + &[bump], ], - &SPL_GOVERNANCE_ID, - ) + &SPL_GOVERNANCE_ID, + ) } pub fn find_required_signatory_pda( - governance: &solana_pubkey::Pubkey, - signatory: &solana_pubkey::Pubkey, - ) -> (solana_pubkey::Pubkey, u8) { + governance: &solana_pubkey::Pubkey, + signatory: &solana_pubkey::Pubkey, +) -> (solana_pubkey::Pubkey, u8) { solana_pubkey::Pubkey::find_program_address( &[ - REQUIRED_SIGNATORY_SEED, - governance.as_ref(), - signatory.as_ref(), - ], - &SPL_GOVERNANCE_ID, - ) + REQUIRED_SIGNATORY_SEED, + governance.as_ref(), + signatory.as_ref(), + ], + &SPL_GOVERNANCE_ID, + ) } - diff --git a/e2e/governance/src/generated/pdas/signatory_record.rs b/e2e/governance/src/generated/pdas/signatory_record.rs index 295b3e3..1099693 100644 --- a/e2e/governance/src/generated/pdas/signatory_record.rs +++ b/e2e/governance/src/generated/pdas/signatory_record.rs @@ -7,36 +7,30 @@ use crate::SPL_GOVERNANCE_ID; +pub const SIGNATORY_RECORD_SEED: &'static [u8] = b"governance"; - pub const SIGNATORY_RECORD_SEED: &'static [u8] = b"governance"; - pub fn create_signatory_record_pda( - proposal: solana_pubkey::Pubkey, - signatory: solana_pubkey::Pubkey, - bump: u8, + proposal: solana_pubkey::Pubkey, + signatory: solana_pubkey::Pubkey, + bump: u8, ) -> Result { solana_pubkey::Pubkey::create_program_address( &[ - SIGNATORY_RECORD_SEED, - proposal.as_ref(), - signatory.as_ref(), - &[bump], + SIGNATORY_RECORD_SEED, + proposal.as_ref(), + signatory.as_ref(), + &[bump], ], - &SPL_GOVERNANCE_ID, - ) + &SPL_GOVERNANCE_ID, + ) } pub fn find_signatory_record_pda( - proposal: &solana_pubkey::Pubkey, - signatory: &solana_pubkey::Pubkey, - ) -> (solana_pubkey::Pubkey, u8) { + proposal: &solana_pubkey::Pubkey, + signatory: &solana_pubkey::Pubkey, +) -> (solana_pubkey::Pubkey, u8) { solana_pubkey::Pubkey::find_program_address( - &[ - SIGNATORY_RECORD_SEED, - proposal.as_ref(), - signatory.as_ref(), - ], - &SPL_GOVERNANCE_ID, - ) + &[SIGNATORY_RECORD_SEED, proposal.as_ref(), signatory.as_ref()], + &SPL_GOVERNANCE_ID, + ) } - diff --git a/e2e/governance/src/generated/pdas/token_owner_record.rs b/e2e/governance/src/generated/pdas/token_owner_record.rs index a7672e5..3786066 100644 --- a/e2e/governance/src/generated/pdas/token_owner_record.rs +++ b/e2e/governance/src/generated/pdas/token_owner_record.rs @@ -7,40 +7,38 @@ use crate::SPL_GOVERNANCE_ID; +pub const TOKEN_OWNER_RECORD_SEED: &'static [u8] = b"governance"; - pub const TOKEN_OWNER_RECORD_SEED: &'static [u8] = b"governance"; - pub fn create_token_owner_record_pda( - realm: solana_pubkey::Pubkey, - governing_token_mint: solana_pubkey::Pubkey, - governing_token_owner: solana_pubkey::Pubkey, - bump: u8, + realm: solana_pubkey::Pubkey, + governing_token_mint: solana_pubkey::Pubkey, + governing_token_owner: solana_pubkey::Pubkey, + bump: u8, ) -> Result { solana_pubkey::Pubkey::create_program_address( &[ - TOKEN_OWNER_RECORD_SEED, - realm.as_ref(), - governing_token_mint.as_ref(), - governing_token_owner.as_ref(), - &[bump], + TOKEN_OWNER_RECORD_SEED, + realm.as_ref(), + governing_token_mint.as_ref(), + governing_token_owner.as_ref(), + &[bump], ], - &SPL_GOVERNANCE_ID, - ) + &SPL_GOVERNANCE_ID, + ) } pub fn find_token_owner_record_pda( - realm: &solana_pubkey::Pubkey, - governing_token_mint: &solana_pubkey::Pubkey, - governing_token_owner: &solana_pubkey::Pubkey, - ) -> (solana_pubkey::Pubkey, u8) { + realm: &solana_pubkey::Pubkey, + governing_token_mint: &solana_pubkey::Pubkey, + governing_token_owner: &solana_pubkey::Pubkey, +) -> (solana_pubkey::Pubkey, u8) { solana_pubkey::Pubkey::find_program_address( &[ - TOKEN_OWNER_RECORD_SEED, - realm.as_ref(), - governing_token_mint.as_ref(), - governing_token_owner.as_ref(), - ], - &SPL_GOVERNANCE_ID, - ) + TOKEN_OWNER_RECORD_SEED, + realm.as_ref(), + governing_token_mint.as_ref(), + governing_token_owner.as_ref(), + ], + &SPL_GOVERNANCE_ID, + ) } - diff --git a/e2e/governance/src/generated/pdas/vote_record.rs b/e2e/governance/src/generated/pdas/vote_record.rs index 4443f88..7789e57 100644 --- a/e2e/governance/src/generated/pdas/vote_record.rs +++ b/e2e/governance/src/generated/pdas/vote_record.rs @@ -7,36 +7,34 @@ use crate::SPL_GOVERNANCE_ID; +pub const VOTE_RECORD_SEED: &'static [u8] = b"governance"; - pub const VOTE_RECORD_SEED: &'static [u8] = b"governance"; - pub fn create_vote_record_pda( - proposal: solana_pubkey::Pubkey, - token_owner_record: solana_pubkey::Pubkey, - bump: u8, + proposal: solana_pubkey::Pubkey, + token_owner_record: solana_pubkey::Pubkey, + bump: u8, ) -> Result { solana_pubkey::Pubkey::create_program_address( &[ - VOTE_RECORD_SEED, - proposal.as_ref(), - token_owner_record.as_ref(), - &[bump], + VOTE_RECORD_SEED, + proposal.as_ref(), + token_owner_record.as_ref(), + &[bump], ], - &SPL_GOVERNANCE_ID, - ) + &SPL_GOVERNANCE_ID, + ) } pub fn find_vote_record_pda( - proposal: &solana_pubkey::Pubkey, - token_owner_record: &solana_pubkey::Pubkey, - ) -> (solana_pubkey::Pubkey, u8) { + proposal: &solana_pubkey::Pubkey, + token_owner_record: &solana_pubkey::Pubkey, +) -> (solana_pubkey::Pubkey, u8) { solana_pubkey::Pubkey::find_program_address( &[ - VOTE_RECORD_SEED, - proposal.as_ref(), - token_owner_record.as_ref(), - ], - &SPL_GOVERNANCE_ID, - ) + VOTE_RECORD_SEED, + proposal.as_ref(), + token_owner_record.as_ref(), + ], + &SPL_GOVERNANCE_ID, + ) } - diff --git a/test/pdasPage.test.ts b/test/pdasPage.test.ts index 99cfd37..1448961 100644 --- a/test/pdasPage.test.ts +++ b/test/pdasPage.test.ts @@ -1,15 +1,16 @@ import { - constantPdaSeedNodeFromString, + bytesTypeNode, constantPdaSeedNode, + constantPdaSeedNodeFromString, + fixedSizeTypeNode, + getAllPdas, + numberTypeNode, + numberValueNode, pdaNode, programNode, publicKeyTypeNode, - variablePdaSeedNode, - numberTypeNode, - numberValueNode, - bytesTypeNode, - fixedSizeTypeNode, rootNode, + variablePdaSeedNode, } from '@codama/nodes'; import { getFromRenderMap } from '@codama/renderers-core'; import { visit } from '@codama/visitors-core'; @@ -22,7 +23,6 @@ test('it renders a standalone PDA with variable seeds', () => { // Given a program with a PDA that has variable seeds. const node = programNode({ name: 'myProgram', - publicKey: 'TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA', pdas: [ pdaNode({ name: 'myPda', @@ -32,6 +32,7 @@ test('it renders a standalone PDA with variable seeds', () => { ], }), ], + publicKey: 'TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA', }); // When we render it. @@ -53,7 +54,6 @@ test('it renders a PDA with only constant seeds', () => { // Given a program with a PDA that has only constant seeds. const node = programNode({ name: 'myProgram', - publicKey: 'TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA', pdas: [ pdaNode({ name: 'configPda', @@ -63,6 +63,7 @@ test('it renders a PDA with only constant seeds', () => { ], }), ], + publicKey: 'TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA', }); // When we render it. @@ -83,7 +84,6 @@ test('it renders a PDA with byte array seeds', () => { // Given a program with a PDA that has byte array seeds. const node = programNode({ name: 'myProgram', - publicKey: 'TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA', pdas: [ pdaNode({ name: 'hashPda', @@ -93,6 +93,7 @@ test('it renders a PDA with byte array seeds', () => { ], }), ], + publicKey: 'TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA', }); // When we render it. @@ -113,7 +114,6 @@ test('it renders a PDA module file', () => { // Given a root node with a program containing multiple PDAs. const program = programNode({ name: 'myProgram', - publicKey: 'TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA', pdas: [ pdaNode({ name: 'firstPda', @@ -124,6 +124,7 @@ test('it renders a PDA module file', () => { seeds: [constantPdaSeedNodeFromString('utf8', 'second')], }), ], + publicKey: 'TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA', }); const node = rootNode(program); @@ -143,16 +144,18 @@ test('it includes PDAs module in the root mod file', () => { // Given a root node with a program containing PDAs. const program = programNode({ name: 'myProgram', - publicKey: 'TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA', pdas: [ pdaNode({ name: 'myPda', seeds: [constantPdaSeedNodeFromString('utf8', 'test')], }), ], + publicKey: 'TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA', }); const node = rootNode(program); + console.log("PDAs", getAllPdas(node)) + // When we render it. const renderMap = visit(node, getRenderMapVisitor()); From 7ede9ec1c85d7e9f4671990eeece49f1c0a9f7fe Mon Sep 17 00:00:00 2001 From: Ian Macalinao Date: Thu, 9 Oct 2025 12:43:31 +0800 Subject: [PATCH 13/24] rustdocs for pda generators --- e2e/governance/src/generated/pdas/community_token_holding.rs | 4 ++-- e2e/governance/src/generated/pdas/council_token_holding.rs | 4 ++-- e2e/governance/src/generated/pdas/governance.rs | 4 ++-- e2e/governance/src/generated/pdas/governing_token_holding.rs | 4 ++-- e2e/governance/src/generated/pdas/native_treasury.rs | 4 ++-- e2e/governance/src/generated/pdas/proposal.rs | 4 ++-- e2e/governance/src/generated/pdas/proposal_deposit.rs | 4 ++-- e2e/governance/src/generated/pdas/proposal_transaction.rs | 4 ++-- e2e/governance/src/generated/pdas/realm.rs | 4 ++-- e2e/governance/src/generated/pdas/realm_config.rs | 4 ++-- e2e/governance/src/generated/pdas/required_signatory.rs | 4 ++-- e2e/governance/src/generated/pdas/signatory_record.rs | 4 ++-- e2e/governance/src/generated/pdas/token_owner_record.rs | 4 ++-- e2e/governance/src/generated/pdas/vote_record.rs | 4 ++-- public/templates/pdasPage.njk | 2 ++ 15 files changed, 30 insertions(+), 28 deletions(-) diff --git a/e2e/governance/src/generated/pdas/community_token_holding.rs b/e2e/governance/src/generated/pdas/community_token_holding.rs index ebc98bb..c014544 100644 --- a/e2e/governance/src/generated/pdas/community_token_holding.rs +++ b/e2e/governance/src/generated/pdas/community_token_holding.rs @@ -8,7 +8,7 @@ use crate::SPL_GOVERNANCE_ID; pub const COMMUNITY_TOKEN_HOLDING_SEED: &'static [u8] = b"governance"; - +/// Community token holding account of a realm pub fn create_community_token_holding_pda( realm: solana_pubkey::Pubkey, community_mint: solana_pubkey::Pubkey, @@ -24,7 +24,7 @@ pub fn create_community_token_holding_pda( &SPL_GOVERNANCE_ID, ) } - +/// Community token holding account of a realm pub fn find_community_token_holding_pda( realm: &solana_pubkey::Pubkey, community_mint: &solana_pubkey::Pubkey, diff --git a/e2e/governance/src/generated/pdas/council_token_holding.rs b/e2e/governance/src/generated/pdas/council_token_holding.rs index b5da294..6403a68 100644 --- a/e2e/governance/src/generated/pdas/council_token_holding.rs +++ b/e2e/governance/src/generated/pdas/council_token_holding.rs @@ -8,7 +8,7 @@ use crate::SPL_GOVERNANCE_ID; pub const COUNCIL_TOKEN_HOLDING_SEED: &'static [u8] = b"governance"; - +/// Council token holding account of a realm pub fn create_council_token_holding_pda( realm: solana_pubkey::Pubkey, council_mint: solana_pubkey::Pubkey, @@ -24,7 +24,7 @@ pub fn create_council_token_holding_pda( &SPL_GOVERNANCE_ID, ) } - +/// Council token holding account of a realm pub fn find_council_token_holding_pda( realm: &solana_pubkey::Pubkey, council_mint: &solana_pubkey::Pubkey, diff --git a/e2e/governance/src/generated/pdas/governance.rs b/e2e/governance/src/generated/pdas/governance.rs index bf3bd2b..fda84c7 100644 --- a/e2e/governance/src/generated/pdas/governance.rs +++ b/e2e/governance/src/generated/pdas/governance.rs @@ -8,7 +8,7 @@ use crate::SPL_GOVERNANCE_ID; pub const GOVERNANCE_SEED: &'static [u8] = b"account-governance"; - +/// Governance account within a realm pub fn create_governance_pda( realm: solana_pubkey::Pubkey, seed: solana_pubkey::Pubkey, @@ -19,7 +19,7 @@ pub fn create_governance_pda( &SPL_GOVERNANCE_ID, ) } - +/// Governance account within a realm pub fn find_governance_pda( realm: &solana_pubkey::Pubkey, seed: &solana_pubkey::Pubkey, diff --git a/e2e/governance/src/generated/pdas/governing_token_holding.rs b/e2e/governance/src/generated/pdas/governing_token_holding.rs index dfbe67f..301bd8c 100644 --- a/e2e/governance/src/generated/pdas/governing_token_holding.rs +++ b/e2e/governance/src/generated/pdas/governing_token_holding.rs @@ -8,7 +8,7 @@ use crate::SPL_GOVERNANCE_ID; pub const GOVERNING_TOKEN_HOLDING_SEED: &'static [u8] = b"governance"; - +/// Governing token holding account pub fn create_governing_token_holding_pda( realm: solana_pubkey::Pubkey, governing_token_mint: solana_pubkey::Pubkey, @@ -24,7 +24,7 @@ pub fn create_governing_token_holding_pda( &SPL_GOVERNANCE_ID, ) } - +/// Governing token holding account pub fn find_governing_token_holding_pda( realm: &solana_pubkey::Pubkey, governing_token_mint: &solana_pubkey::Pubkey, diff --git a/e2e/governance/src/generated/pdas/native_treasury.rs b/e2e/governance/src/generated/pdas/native_treasury.rs index d9b7217..1dc03e3 100644 --- a/e2e/governance/src/generated/pdas/native_treasury.rs +++ b/e2e/governance/src/generated/pdas/native_treasury.rs @@ -8,7 +8,7 @@ use crate::SPL_GOVERNANCE_ID; pub const NATIVE_TREASURY_SEED: &'static [u8] = b"native-treasury"; - +/// Governance's native SOL treasury account pub fn create_native_treasury_pda( governance: solana_pubkey::Pubkey, bump: u8, @@ -18,7 +18,7 @@ pub fn create_native_treasury_pda( &SPL_GOVERNANCE_ID, ) } - +/// Governance's native SOL treasury account pub fn find_native_treasury_pda(governance: &solana_pubkey::Pubkey) -> (solana_pubkey::Pubkey, u8) { solana_pubkey::Pubkey::find_program_address( &[NATIVE_TREASURY_SEED, governance.as_ref()], diff --git a/e2e/governance/src/generated/pdas/proposal.rs b/e2e/governance/src/generated/pdas/proposal.rs index 2726eb4..6c27861 100644 --- a/e2e/governance/src/generated/pdas/proposal.rs +++ b/e2e/governance/src/generated/pdas/proposal.rs @@ -8,7 +8,7 @@ use crate::SPL_GOVERNANCE_ID; pub const PROPOSAL_SEED: &'static [u8] = b"governance"; - +/// Governance proposal pub fn create_proposal_pda( governance: solana_pubkey::Pubkey, governing_token_mint: solana_pubkey::Pubkey, @@ -26,7 +26,7 @@ pub fn create_proposal_pda( &SPL_GOVERNANCE_ID, ) } - +/// Governance proposal pub fn find_proposal_pda( governance: &solana_pubkey::Pubkey, governing_token_mint: &solana_pubkey::Pubkey, diff --git a/e2e/governance/src/generated/pdas/proposal_deposit.rs b/e2e/governance/src/generated/pdas/proposal_deposit.rs index 83a1a1a..4953042 100644 --- a/e2e/governance/src/generated/pdas/proposal_deposit.rs +++ b/e2e/governance/src/generated/pdas/proposal_deposit.rs @@ -8,7 +8,7 @@ use crate::SPL_GOVERNANCE_ID; pub const PROPOSAL_DEPOSIT_SEED: &'static [u8] = b"proposal-deposit"; - +/// Proposal deposit made by a specific payer pub fn create_proposal_deposit_pda( proposal: solana_pubkey::Pubkey, deposit_payer: solana_pubkey::Pubkey, @@ -24,7 +24,7 @@ pub fn create_proposal_deposit_pda( &SPL_GOVERNANCE_ID, ) } - +/// Proposal deposit made by a specific payer pub fn find_proposal_deposit_pda( proposal: &solana_pubkey::Pubkey, deposit_payer: &solana_pubkey::Pubkey, diff --git a/e2e/governance/src/generated/pdas/proposal_transaction.rs b/e2e/governance/src/generated/pdas/proposal_transaction.rs index 7aee3c9..952345e 100644 --- a/e2e/governance/src/generated/pdas/proposal_transaction.rs +++ b/e2e/governance/src/generated/pdas/proposal_transaction.rs @@ -8,7 +8,7 @@ use crate::SPL_GOVERNANCE_ID; pub const PROPOSAL_TRANSACTION_SEED: &'static [u8] = b"governance"; - +/// Transaction within a proposal option pub fn create_proposal_transaction_pda( proposal: solana_pubkey::Pubkey, option_index: u8, @@ -26,7 +26,7 @@ pub fn create_proposal_transaction_pda( &SPL_GOVERNANCE_ID, ) } - +/// Transaction within a proposal option pub fn find_proposal_transaction_pda( proposal: &solana_pubkey::Pubkey, option_index: u8, diff --git a/e2e/governance/src/generated/pdas/realm.rs b/e2e/governance/src/generated/pdas/realm.rs index de693bc..84f5c58 100644 --- a/e2e/governance/src/generated/pdas/realm.rs +++ b/e2e/governance/src/generated/pdas/realm.rs @@ -8,7 +8,7 @@ use crate::SPL_GOVERNANCE_ID; pub const REALM_SEED: &'static [u8] = b"governance"; - +/// Realm account identified by its name pub fn create_realm_pda( name: RemainderStr, bump: u8, @@ -18,7 +18,7 @@ pub fn create_realm_pda( &SPL_GOVERNANCE_ID, ) } - +/// Realm account identified by its name pub fn find_realm_pda(name: RemainderStr) -> (solana_pubkey::Pubkey, u8) { solana_pubkey::Pubkey::find_program_address( &[REALM_SEED, name.to_string().as_ref()], diff --git a/e2e/governance/src/generated/pdas/realm_config.rs b/e2e/governance/src/generated/pdas/realm_config.rs index ee7990c..d285ea4 100644 --- a/e2e/governance/src/generated/pdas/realm_config.rs +++ b/e2e/governance/src/generated/pdas/realm_config.rs @@ -8,7 +8,7 @@ use crate::SPL_GOVERNANCE_ID; pub const REALM_CONFIG_SEED: &'static [u8] = b"realm-config"; - +/// Configuration of a realm pub fn create_realm_config_pda( realm: solana_pubkey::Pubkey, bump: u8, @@ -18,7 +18,7 @@ pub fn create_realm_config_pda( &SPL_GOVERNANCE_ID, ) } - +/// Configuration of a realm pub fn find_realm_config_pda(realm: &solana_pubkey::Pubkey) -> (solana_pubkey::Pubkey, u8) { solana_pubkey::Pubkey::find_program_address( &[REALM_CONFIG_SEED, realm.as_ref()], diff --git a/e2e/governance/src/generated/pdas/required_signatory.rs b/e2e/governance/src/generated/pdas/required_signatory.rs index 2d906ad..0d43371 100644 --- a/e2e/governance/src/generated/pdas/required_signatory.rs +++ b/e2e/governance/src/generated/pdas/required_signatory.rs @@ -8,7 +8,7 @@ use crate::SPL_GOVERNANCE_ID; pub const REQUIRED_SIGNATORY_SEED: &'static [u8] = b"required-signatory"; - +/// Required signatory on a governance pub fn create_required_signatory_pda( governance: solana_pubkey::Pubkey, signatory: solana_pubkey::Pubkey, @@ -24,7 +24,7 @@ pub fn create_required_signatory_pda( &SPL_GOVERNANCE_ID, ) } - +/// Required signatory on a governance pub fn find_required_signatory_pda( governance: &solana_pubkey::Pubkey, signatory: &solana_pubkey::Pubkey, diff --git a/e2e/governance/src/generated/pdas/signatory_record.rs b/e2e/governance/src/generated/pdas/signatory_record.rs index 1099693..b029efe 100644 --- a/e2e/governance/src/generated/pdas/signatory_record.rs +++ b/e2e/governance/src/generated/pdas/signatory_record.rs @@ -8,7 +8,7 @@ use crate::SPL_GOVERNANCE_ID; pub const SIGNATORY_RECORD_SEED: &'static [u8] = b"governance"; - +/// Signatory's record on a proposal pub fn create_signatory_record_pda( proposal: solana_pubkey::Pubkey, signatory: solana_pubkey::Pubkey, @@ -24,7 +24,7 @@ pub fn create_signatory_record_pda( &SPL_GOVERNANCE_ID, ) } - +/// Signatory's record on a proposal pub fn find_signatory_record_pda( proposal: &solana_pubkey::Pubkey, signatory: &solana_pubkey::Pubkey, diff --git a/e2e/governance/src/generated/pdas/token_owner_record.rs b/e2e/governance/src/generated/pdas/token_owner_record.rs index 3786066..8199ea6 100644 --- a/e2e/governance/src/generated/pdas/token_owner_record.rs +++ b/e2e/governance/src/generated/pdas/token_owner_record.rs @@ -8,7 +8,7 @@ use crate::SPL_GOVERNANCE_ID; pub const TOKEN_OWNER_RECORD_SEED: &'static [u8] = b"governance"; - +/// Token owner's record within a realm pub fn create_token_owner_record_pda( realm: solana_pubkey::Pubkey, governing_token_mint: solana_pubkey::Pubkey, @@ -26,7 +26,7 @@ pub fn create_token_owner_record_pda( &SPL_GOVERNANCE_ID, ) } - +/// Token owner's record within a realm pub fn find_token_owner_record_pda( realm: &solana_pubkey::Pubkey, governing_token_mint: &solana_pubkey::Pubkey, diff --git a/e2e/governance/src/generated/pdas/vote_record.rs b/e2e/governance/src/generated/pdas/vote_record.rs index 7789e57..366cc74 100644 --- a/e2e/governance/src/generated/pdas/vote_record.rs +++ b/e2e/governance/src/generated/pdas/vote_record.rs @@ -8,7 +8,7 @@ use crate::SPL_GOVERNANCE_ID; pub const VOTE_RECORD_SEED: &'static [u8] = b"governance"; - +/// Vote record on a proposal pub fn create_vote_record_pda( proposal: solana_pubkey::Pubkey, token_owner_record: solana_pubkey::Pubkey, @@ -24,7 +24,7 @@ pub fn create_vote_record_pda( &SPL_GOVERNANCE_ID, ) } - +/// Vote record on a proposal pub fn find_vote_record_pda( proposal: &solana_pubkey::Pubkey, token_owner_record: &solana_pubkey::Pubkey, diff --git a/public/templates/pdasPage.njk b/public/templates/pdasPage.njk index aaf1ba3..9d27784 100644 --- a/public/templates/pdasPage.njk +++ b/public/templates/pdasPage.njk @@ -16,6 +16,7 @@ pub const {{ pda.name | snakeCase | upper }}_SEED{% if constantSeeds.length > 1 {% endif %} {% endfor %} +{{- macros.docblock(pda.docs) -}} pub fn create_{{ pda.name | snakeCase }}_pda( {% if hasVariableSeeds %} {% for seed in seeds %} @@ -59,6 +60,7 @@ pub fn create_{{ pda.name | snakeCase }}_pda( ) } +{{- macros.docblock(pda.docs) -}} pub fn find_{{ pda.name | snakeCase }}_pda( {% if hasVariableSeeds %} {% for seed in seeds %} From 4356d5b9f030f56661b5ce1c2c9c2c5250cf35b5 Mon Sep 17 00:00:00 2001 From: ioxde <228087182+ioxde@users.noreply.github.com> Date: Wed, 18 Mar 2026 21:00:26 -0700 Subject: [PATCH 14/24] migrate pda generation to solana-address and remove default serde --- Cargo.lock | 594 +++++++++++++++++- Cargo.toml | 4 + e2e/governance/Cargo.toml | 7 +- .../src/generated/accounts/governance_v1.rs | 54 +- .../src/generated/accounts/governance_v2.rs | 54 +- .../accounts/legacy_token_owner_record.rs | 73 +-- .../generated/accounts/program_metadata.rs | 25 +- .../generated/accounts/proposal_deposit.rs | 55 +- .../accounts/proposal_instruction_v1.rs | 46 +- .../accounts/proposal_transaction_v2.rs | 46 +- .../src/generated/accounts/proposal_v1.rs | 70 +-- .../src/generated/accounts/proposal_v2.rs | 71 +-- .../accounts/realm_config_account.rs | 44 +- .../src/generated/accounts/realm_v1.rs | 48 +- .../src/generated/accounts/realm_v2.rs | 49 +- .../generated/accounts/required_signatory.rs | 54 +- .../generated/accounts/signatory_record_v1.rs | 54 +- .../generated/accounts/signatory_record_v2.rs | 54 +- .../accounts/token_owner_record_v1.rs | 72 +-- .../accounts/token_owner_record_v2.rs | 73 +-- .../src/generated/accounts/vote_record_v1.rs | 57 +- .../src/generated/accounts/vote_record_v2.rs | 57 +- .../instructions/add_required_signatory.rs | 40 +- .../generated/instructions/add_signatory.rs | 52 +- .../generated/instructions/cancel_proposal.rs | 31 +- .../src/generated/instructions/cast_vote.rs | 82 ++- .../instructions/complete_proposal.rs | 19 +- .../instructions/create_governance.rs | 58 +- .../instructions/create_mint_governance.rs | 72 ++- .../instructions/create_native_treasury.rs | 27 +- .../instructions/create_program_governance.rs | 76 ++- .../generated/instructions/create_proposal.rs | 82 ++- .../generated/instructions/create_realm.rs | 98 ++- .../instructions/create_token_governance.rs | 72 ++- .../instructions/create_token_owner_record.rs | 39 +- .../instructions/deposit_governing_tokens.rs | 66 +- .../instructions/execute_transaction.rs | 19 +- .../generated/instructions/finalize_vote.rs | 43 +- .../instructions/flag_transaction_error.rs | 25 +- .../instructions/insert_transaction.rs | 54 +- .../src/generated/instructions/legacy1.rs | 1 - .../instructions/refund_proposal_deposit.rs | 19 +- .../generated/instructions/relinquish_vote.rs | 49 +- .../instructions/remove_required_signatory.rs | 22 +- .../instructions/remove_transaction.rs | 34 +- .../instructions/revoke_governing_tokens.rs | 46 +- .../instructions/set_governance_config.rs | 8 +- .../instructions/set_governance_delegate.rs | 26 +- .../instructions/set_realm_authority.rs | 20 +- .../instructions/set_realm_config.rs | 70 +-- .../instructions/sign_off_proposal.rs | 31 +- .../instructions/update_program_metadata.rs | 21 +- .../instructions/withdraw_governing_tokens.rs | 45 +- .../generated/pdas/community_token_holding.rs | 18 +- .../generated/pdas/council_token_holding.rs | 18 +- .../src/generated/pdas/governance.rs | 17 +- .../generated/pdas/governing_token_holding.rs | 18 +- .../src/generated/pdas/native_treasury.rs | 12 +- e2e/governance/src/generated/pdas/proposal.rs | 22 +- .../src/generated/pdas/proposal_deposit.rs | 18 +- .../generated/pdas/proposal_transaction.rs | 14 +- e2e/governance/src/generated/pdas/realm.rs | 12 +- .../src/generated/pdas/realm_config.rs | 12 +- .../src/generated/pdas/required_signatory.rs | 18 +- .../src/generated/pdas/signatory_record.rs | 18 +- .../src/generated/pdas/token_owner_record.rs | 22 +- .../src/generated/pdas/vote_record.rs | 18 +- e2e/governance/src/generated/programs.rs | 4 +- e2e/governance/src/generated/shared.rs | 4 +- .../src/generated/types/account_meta_data.rs | 9 +- .../types/governance_account_type.rs | 1 - .../src/generated/types/governance_config.rs | 1 - .../types/governance_instruction_v1.rs | 1 - .../generated/types/governing_token_config.rs | 7 +- .../governing_token_config_account_args.rs | 7 +- .../types/governing_token_config_params.rs | 1 - .../generated/types/governing_token_type.rs | 1 - .../src/generated/types/instruction_data.rs | 9 +- .../types/instruction_execution_flags.rs | 1 - .../types/mint_max_voter_weight_source.rs | 1 - .../src/generated/types/multi_choice_type.rs | 1 - .../src/generated/types/native_treasury.rs | 1 - .../src/generated/types/option_vote_result.rs | 1 - .../src/generated/types/proposal_option.rs | 1 - .../src/generated/types/proposal_state.rs | 1 - .../src/generated/types/realm_config.rs | 5 +- .../generated/types/realm_config_params.rs | 1 - .../generated/types/realm_config_params_v1.rs | 1 - .../src/generated/types/reserved110.rs | 2 - .../src/generated/types/reserved119.rs | 2 - .../types/set_realm_authority_action.rs | 1 - .../types/transaction_execution_status.rs | 1 - e2e/governance/src/generated/types/vote.rs | 1 - .../src/generated/types/vote_choice.rs | 1 - .../src/generated/types/vote_kind.rs | 1 - .../src/generated/types/vote_threshold.rs | 1 - .../src/generated/types/vote_tipping.rs | 1 - .../src/generated/types/vote_type.rs | 1 - .../src/generated/types/vote_weight_v1.rs | 1 - public/templates/pdasPage.njk | 24 +- src/getRenderMapVisitor.ts | 1 + test/pdasPage.test.ts | 23 +- 102 files changed, 1847 insertions(+), 1518 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index e6d5885..128cf19 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -258,6 +258,15 @@ dependencies = [ "thiserror 1.0.69", ] +[[package]] +name = "android_system_properties" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" +dependencies = [ + "libc", +] + [[package]] name = "anyhow" version = "1.0.100" @@ -575,6 +584,29 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" +[[package]] +name = "cfg_eval" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "45565fc9416b9896014f5732ac776f810ee53a66730c17e4020c3ec064a8f88f" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "chrono" +version = "0.4.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c673075a2e0e5f4a1dde27ce9dee1ea4558c7ffe648f576438a20ca1d2acc4b0" +dependencies = [ + "iana-time-zone", + "num-traits", + "serde", + "windows-link", +] + [[package]] name = "codama-renderers-rust-e2e-anchor" version = "0.0.0" @@ -610,23 +642,22 @@ name = "codama-renderers-rust-e2e-governance" version = "0.0.0" dependencies = [ "anchor-lang", - "assert_matches", - "borsh 0.10.4", + "borsh 1.5.7", "kaigan", "num-derive", "num-traits", "serde", "serde-big-array", "serde_with", - "solana-account", - "solana-account-info", + "solana-account 3.0.0", + "solana-account-info 3.1.0", + "solana-address 2.2.0", "solana-client", - "solana-cpi", + "solana-cpi 3.1.0", "solana-decode-error", - "solana-instruction", - "solana-program-error", - "solana-pubkey", - "solana-sdk", + "solana-instruction 3.2.0", + "solana-program-error 3.0.0", + "spl-collections", "thiserror 1.0.69", ] @@ -848,6 +879,59 @@ dependencies = [ "syn 2.0.117", ] +[[package]] +name = "dashmap" +version = "5.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "978747c1d849a7d2ee5e8adc0159961c48fb7e5db2f06af6723b80123bb53856" +dependencies = [ + "cfg-if", + "hashbrown 0.14.5", + "lock_api", + "once_cell", + "parking_lot_core", +] + +[[package]] +name = "data-encoding" +version = "2.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a2330da5de22e8a3cb63252ce2abb30116bf5265e89c0e01bc17015ce30a476" + +[[package]] +name = "der" +version = "0.7.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7c1832837b905bbfb5101e07cc24c8deddf52f93225eee6ead5f4d63d53ddcb" +dependencies = [ + "const-oid", + "zeroize", +] + +[[package]] +name = "der-parser" +version = "8.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dbd676fbbab537128ef0278adb5576cf363cff6aa22a7b24effe97347cfab61e" +dependencies = [ + "asn1-rs", + "displaydoc", + "nom", + "num-bigint 0.4.6", + "num-traits", + "rusticata-macros", +] + +[[package]] +name = "deranged" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a41953f86f8a05768a6cda24def994fd2f424b04ec5c719cf89989779f199071" +dependencies = [ + "powerfmt", + "serde_core", +] + [[package]] name = "digest" version = "0.9.0" @@ -879,6 +963,60 @@ dependencies = [ "syn 2.0.117", ] +[[package]] +name = "dlopen2" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09b4f5f101177ff01b8ec4ecc81eead416a8aa42819a2869311b3420fa114ffa" +dependencies = [ + "dlopen2_derive", + "libc", + "once_cell", + "winapi", +] + +[[package]] +name = "dlopen2_derive" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6cbae11b3de8fce2a456e8ea3dada226b35fe791f0dc1d360c0941f0bb681f3" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "dyn-clone" +version = "1.0.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0881ea181b1df73ff77ffaaf9c7544ecc11e82fba9b5f27b262a3c73a332555" + +[[package]] +name = "ed25519" +version = "2.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "115531babc129696a58c64a4fef0a8bf9e9698629fb97e9e40767d235cfbcd53" +dependencies = [ + "pkcs8", + "signature", +] + +[[package]] +name = "ed25519-dalek" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70e796c081cee67dc755e1a36a0a172b897fab85fc3f6bc48307991f64e4eca9" +dependencies = [ + "curve25519-dalek", + "ed25519", + "rand_core 0.6.4", + "serde", + "sha2 0.10.9", + "subtle", + "zeroize", +] + [[package]] name = "either" version = "1.15.0" @@ -1164,6 +1302,44 @@ dependencies = [ "unicode-segmentation", ] +[[package]] +name = "hermit-abi" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc0fef456e4baa96da950455cd02c081ca953b141298e41db3fc7e36b1da849c" + +[[package]] +name = "hex" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" + +[[package]] +name = "histogram" +version = "0.6.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12cb882ccb290b8646e554b157ab0b71e64e8d5bef775cd66b6531e52d302669" + +[[package]] +name = "hmac" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" +dependencies = [ + "digest 0.10.7", +] + +[[package]] +name = "http" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "601cbb57e577e2f5ef5be8e7b83f0f63994f25aa94d673e54a92d5c516d101f1" +dependencies = [ + "bytes", + "fnv", + "itoa", +] + [[package]] name = "http" version = "1.4.0" @@ -1264,6 +1440,30 @@ dependencies = [ "tracing", ] +[[package]] +name = "iana-time-zone" +version = "0.1.65" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e31bc9ad994ba00e440a8aa5c9ef0ec67d5cb5e5cb0cc7f8b744a35b389cc470" +dependencies = [ + "android_system_properties", + "core-foundation-sys", + "iana-time-zone-haiku", + "js-sys", + "log", + "wasm-bindgen", + "windows-core", +] + +[[package]] +name = "iana-time-zone-haiku" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" +dependencies = [ + "cc", +] + [[package]] name = "icu_collections" version = "2.0.0" @@ -1377,6 +1577,17 @@ dependencies = [ "icu_properties", ] +[[package]] +name = "indexmap" +version = "1.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" +dependencies = [ + "autocfg", + "hashbrown 0.12.3", + "serde", +] + [[package]] name = "indexmap" version = "2.11.4" @@ -1385,6 +1596,8 @@ checksum = "4b0f83760fb341a774ed326568e19f5a863af4a952def8c39f9ab92fd95b88e5" dependencies = [ "equivalent", "hashbrown 0.16.0", + "serde", + "serde_core", ] [[package]] @@ -1468,6 +1681,15 @@ dependencies = [ "serde_json", ] +[[package]] +name = "kaigan" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4f25ded719a2354f6b1a51d0c0741c25bc7afe038617664eb37f6418439eb084" +dependencies = [ + "borsh 0.10.4", +] + [[package]] name = "keccak" version = "0.1.5" @@ -1941,6 +2163,26 @@ dependencies = [ "bitflags", ] +[[package]] +name = "ref-cast" +version = "1.0.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f354300ae66f76f1c85c5f84693f0ce81d747e2c3f21a45fef496d89c960bf7d" +dependencies = [ + "ref-cast-impl", +] + +[[package]] +name = "ref-cast-impl" +version = "1.0.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7186006dcb21920990093f30e3dea63b7d6e977bf1256be20c3563a5db070da" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + [[package]] name = "regex" version = "1.11.3" @@ -2107,6 +2349,48 @@ version = "1.0.20" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" +[[package]] +name = "same-file" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "schannel" +version = "0.1.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "891d81b926048e76efe18581bf793546b4c0eaf8448d72be8de2bbee5fd166e1" +dependencies = [ + "windows-sys 0.61.1", +] + +[[package]] +name = "schemars" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4cd191f9397d57d581cddd31014772520aa448f65ef991055d7f61582c65165f" +dependencies = [ + "dyn-clone", + "ref-cast", + "serde", + "serde_json", +] + +[[package]] +name = "schemars" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2b42f36aa1cd011945615b92222f6bf73c599a102a300334cd7f8dbeec726cc" +dependencies = [ + "dyn-clone", + "ref-cast", + "serde", + "serde_json", +] + [[package]] name = "scopeguard" version = "1.2.0" @@ -2202,6 +2486,49 @@ dependencies = [ "serde", ] +[[package]] +name = "serde_with" +version = "3.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c522100790450cf78eeac1507263d0a350d4d5b30df0c8e1fe051a10c22b376e" +dependencies = [ + "base64 0.22.1", + "chrono", + "hex", + "indexmap 1.9.3", + "indexmap 2.11.4", + "schemars 0.9.0", + "schemars 1.2.1", + "serde", + "serde_derive", + "serde_json", + "serde_with_macros", + "time", +] + +[[package]] +name = "serde_with_macros" +version = "3.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "327ada00f7d64abaac1e55a6911e90cf665aa051b9a561c7006c157f4633135e" +dependencies = [ + "darling", + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "sha1" +version = "0.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest 0.10.7", +] + [[package]] name = "sha2" version = "0.9.9" @@ -2461,6 +2788,73 @@ dependencies = [ "borsh 1.5.7", ] +[[package]] +name = "solana-client" +version = "3.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "99541c3b3571d6675a9bfc032c776712b3f4da0d5e7f4a5019e044885f716137" +dependencies = [ + "async-trait", + "bincode", + "dashmap", + "futures", + "futures-util", + "indexmap 2.11.4", + "indicatif", + "log", + "quinn", + "rayon", + "solana-account 3.0.0", + "solana-client-traits", + "solana-commitment-config", + "solana-connection-cache", + "solana-epoch-info", + "solana-hash 3.1.0", + "solana-instruction 3.2.0", + "solana-keypair", + "solana-measure", + "solana-message 3.1.0", + "solana-pubkey 3.0.0", + "solana-pubsub-client", + "solana-quic-client", + "solana-quic-definitions", + "solana-rpc-client", + "solana-rpc-client-api", + "solana-rpc-client-nonce-utils", + "solana-signature", + "solana-signer", + "solana-streamer", + "solana-time-utils", + "solana-tpu-client", + "solana-transaction", + "solana-transaction-error 3.1.0", + "solana-transaction-status-client-types", + "solana-udp-client", + "thiserror 2.0.18", + "tokio", +] + +[[package]] +name = "solana-client-traits" +version = "3.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08618ed587e128105510c54ae3e456b9a06d674d8640db75afe66dad65cb4e02" +dependencies = [ + "solana-account 3.0.0", + "solana-commitment-config", + "solana-epoch-info", + "solana-hash 3.1.0", + "solana-instruction 3.2.0", + "solana-keypair", + "solana-message 3.1.0", + "solana-pubkey 3.0.0", + "solana-signature", + "solana-signer", + "solana-system-interface 2.0.0", + "solana-transaction", + "solana-transaction-error 3.1.0", +] + [[package]] name = "solana-clock" version = "2.2.2" @@ -2497,6 +2891,29 @@ dependencies = [ "serde_derive", ] +[[package]] +name = "solana-connection-cache" +version = "3.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec08ad33264b1159feea22346deae240d3b38b103346ecf3bfc008a02509afe0" +dependencies = [ + "async-trait", + "bincode", + "crossbeam-channel", + "futures-util", + "indexmap 2.11.4", + "log", + "rand 0.8.5", + "rayon", + "solana-keypair", + "solana-measure", + "solana-metrics", + "solana-time-utils", + "solana-transaction-error 3.1.0", + "thiserror 2.0.18", + "tokio", +] + [[package]] name = "solana-cpi" version = "2.2.1" @@ -3575,6 +3992,55 @@ dependencies = [ "solana-sysvar-id 2.2.1", ] +[[package]] +name = "solana-streamer" +version = "3.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "acb28f9c11b3f549dc49694c3dddef34a1531fe2d19c7ead36b7254786379f87" +dependencies = [ + "arc-swap", + "async-channel", + "bytes", + "crossbeam-channel", + "dashmap", + "futures", + "futures-util", + "governor", + "histogram", + "indexmap 2.11.4", + "itertools", + "libc", + "log", + "nix", + "num_cpus", + "pem", + "percentage", + "quinn", + "quinn-proto", + "rand 0.8.5", + "rustls 0.23.32", + "smallvec", + "socket2", + "solana-keypair", + "solana-measure", + "solana-metrics", + "solana-net-utils", + "solana-packet", + "solana-perf", + "solana-pubkey 3.0.0", + "solana-quic-definitions", + "solana-signature", + "solana-signer", + "solana-time-utils", + "solana-tls-utils", + "solana-transaction-error 3.1.0", + "solana-transaction-metrics-tracker", + "thiserror 2.0.18", + "tokio", + "tokio-util", + "x509-parser", +] + [[package]] name = "solana-svm-feature-set" version = "3.0.14" @@ -3686,6 +4152,59 @@ dependencies = [ "solana-sdk-ids 3.1.0", ] +[[package]] +name = "solana-time-utils" +version = "3.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ced92c60aa76ec4780a9d93f3bd64dfa916e1b998eacc6f1c110f3f444f02c9" + +[[package]] +name = "solana-tls-utils" +version = "3.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "475766b71bafcaa6af326c54d35dc09ca4a334e5866b42d09b354291b7aa5819" +dependencies = [ + "rustls 0.23.32", + "solana-keypair", + "solana-pubkey 3.0.0", + "solana-signer", + "x509-parser", +] + +[[package]] +name = "solana-tpu-client" +version = "3.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "313159134696b2c482fa9a7188fd4daac638d69f5962fe842c3f4cfece1a27f3" +dependencies = [ + "async-trait", + "bincode", + "futures-util", + "indexmap 2.11.4", + "indicatif", + "log", + "rayon", + "solana-client-traits", + "solana-clock 3.0.1", + "solana-commitment-config", + "solana-connection-cache", + "solana-epoch-schedule 3.0.0", + "solana-measure", + "solana-message 3.1.0", + "solana-net-utils", + "solana-pubkey 3.0.0", + "solana-pubsub-client", + "solana-quic-definitions", + "solana-rpc-client", + "solana-rpc-client-api", + "solana-signature", + "solana-signer", + "solana-transaction", + "solana-transaction-error 3.1.0", + "thiserror 2.0.18", + "tokio", +] + [[package]] name = "solana-transaction" version = "3.1.0" @@ -4073,7 +4592,7 @@ version = "0.22.27" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "41fe8c660ae4257887cf66394862d21dbca4a6ddd26f04a3560410406a2f819a" dependencies = [ - "indexmap", + "indexmap 2.11.4", "serde", "serde_spanned", "toml_datetime 0.6.11", @@ -4087,7 +4606,7 @@ version = "0.23.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f3effe7c0e86fdff4f69cdd2ccc1b96f933e24811c5441d44904e8683e27184b" dependencies = [ - "indexmap", + "indexmap 2.11.4", "toml_datetime 0.7.2", "toml_parser", "winnow", @@ -4423,12 +4942,65 @@ dependencies = [ "syn 2.0.117", ] +[[package]] +name = "windows-core" +version = "0.62.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6844ee5416b285084d3d3fffd743b925a6c9385455f64f6d4fa3031c4c2749a9" +dependencies = [ + "windows-implement", + "windows-interface", + "windows-link", + "windows-result", + "windows-strings", +] + +[[package]] +name = "windows-implement" +version = "0.60.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "windows-interface" +version = "0.59.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + [[package]] name = "windows-link" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "45e46c0661abb7180e7b9c281db115305d49ca1709ab8242adf09666d2173c65" +[[package]] +name = "windows-result" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7084dcc306f89883455a206237404d3eaf961e5bd7e0f312f7c91f57eb44167f" +dependencies = [ + "windows-link", +] + +[[package]] +name = "windows-strings" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7218c655a553b0bed4426cf54b20d7ba363ef543b52d515b3e48d7fd55318dda" +dependencies = [ + "windows-link", +] + [[package]] name = "windows-sys" version = "0.52.0" diff --git a/Cargo.toml b/Cargo.toml index 676cc87..1352002 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -5,8 +5,12 @@ resolver = "2" [workspace.dependencies] anchor-lang = "~0.31" borsh = "^1.0" +kaigan = "^0.3" num-derive = "^0.4" num-traits = "^0.2" +serde = "^1.0" +serde-big-array = "^0.5" +serde_with = "^3.0" solana-account = "~3.0" solana-account-info = "~3.1" solana-address = "~2.2" diff --git a/e2e/governance/Cargo.toml b/e2e/governance/Cargo.toml index 5a04d0e..0d057f7 100644 --- a/e2e/governance/Cargo.toml +++ b/e2e/governance/Cargo.toml @@ -25,9 +25,6 @@ solana-cpi = { workspace = true } solana-decode-error = { workspace = true } solana-instruction = { workspace = true } solana-program-error = { workspace = true } -solana-pubkey = { workspace = true, features = ["curve25519", "borsh"] } +solana-address = { workspace = true, features = ["borsh", "copy", "curve25519", "decode"] } +spl-collections = { workspace = true } thiserror = { workspace = true } - -[dev-dependencies] -assert_matches = { workspace = true } -solana-sdk = { workspace = true } diff --git a/e2e/governance/src/generated/accounts/governance_v1.rs b/e2e/governance/src/generated/accounts/governance_v1.rs index c7fb13e..755fde5 100644 --- a/e2e/governance/src/generated/accounts/governance_v1.rs +++ b/e2e/governance/src/generated/accounts/governance_v1.rs @@ -9,22 +9,13 @@ use crate::generated::types::GovernanceAccountType; use crate::generated::types::GovernanceConfig; use borsh::BorshDeserialize; use borsh::BorshSerialize; -use solana_pubkey::Pubkey; +use solana_address::Address; #[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] -#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct GovernanceV1 { pub account_type: GovernanceAccountType, - #[cfg_attr( - feature = "serde", - serde(with = "serde_with::As::") - )] - pub realm: Pubkey, - #[cfg_attr( - feature = "serde", - serde(with = "serde_with::As::") - )] - pub governed_account: Pubkey, + pub realm: Address, + pub governed_account: Address, pub proposals_count: u32, pub config: GovernanceConfig, } @@ -35,16 +26,16 @@ impl GovernanceV1 { /// Values are positional and appear in the following order: /// /// 0. `GovernanceV1::PREFIX` - /// 1. realm (`Pubkey`) - /// 2. seed (`Pubkey`) + /// 1. realm (`Address`) + /// 2. seed (`Address`) pub const PREFIX: &'static [u8] = "account-governance".as_bytes(); pub fn create_pda( - realm: Pubkey, - seed: Pubkey, + realm: Address, + seed: Address, bump: u8, - ) -> Result { - solana_pubkey::Pubkey::create_program_address( + ) -> Result { + solana_address::Address::create_program_address( &[ "account-governance".as_bytes(), realm.as_ref(), @@ -55,8 +46,8 @@ impl GovernanceV1 { ) } - pub fn find_pda(realm: &Pubkey, seed: &Pubkey) -> (solana_pubkey::Pubkey, u8) { - solana_pubkey::Pubkey::find_program_address( + pub fn find_pda(realm: &Address, seed: &Address) -> (solana_address::Address, u8) { + solana_address::Address::find_program_address( &[ "account-governance".as_bytes(), realm.as_ref(), @@ -85,7 +76,7 @@ impl<'a> TryFrom<&solana_account_info::AccountInfo<'a>> for GovernanceV1 { #[cfg(feature = "fetch")] pub fn fetch_governance_v1( rpc: &solana_client::rpc_client::RpcClient, - address: &solana_pubkey::Pubkey, + address: &solana_address::Address, ) -> Result, std::io::Error> { let accounts = fetch_all_governance_v1(rpc, &[*address])?; Ok(accounts[0].clone()) @@ -94,18 +85,17 @@ pub fn fetch_governance_v1( #[cfg(feature = "fetch")] pub fn fetch_all_governance_v1( rpc: &solana_client::rpc_client::RpcClient, - addresses: &[solana_pubkey::Pubkey], + addresses: &[solana_address::Address], ) -> Result>, std::io::Error> { let accounts = rpc .get_multiple_accounts(addresses) - .map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, e.to_string()))?; + .map_err(|e| std::io::Error::other(e.to_string()))?; let mut decoded_accounts: Vec> = Vec::new(); for i in 0..addresses.len() { let address = addresses[i]; - let account = accounts[i].as_ref().ok_or(std::io::Error::new( - std::io::ErrorKind::Other, - format!("Account not found: {}", address), - ))?; + let account = accounts[i].as_ref().ok_or(std::io::Error::other(format!( + "Account not found: {address}" + )))?; let data = GovernanceV1::from_bytes(&account.data)?; decoded_accounts.push(crate::shared::DecodedAccount { address, @@ -119,7 +109,7 @@ pub fn fetch_all_governance_v1( #[cfg(feature = "fetch")] pub fn fetch_maybe_governance_v1( rpc: &solana_client::rpc_client::RpcClient, - address: &solana_pubkey::Pubkey, + address: &solana_address::Address, ) -> Result, std::io::Error> { let accounts = fetch_all_maybe_governance_v1(rpc, &[*address])?; Ok(accounts[0].clone()) @@ -128,11 +118,11 @@ pub fn fetch_maybe_governance_v1( #[cfg(feature = "fetch")] pub fn fetch_all_maybe_governance_v1( rpc: &solana_client::rpc_client::RpcClient, - addresses: &[solana_pubkey::Pubkey], + addresses: &[solana_address::Address], ) -> Result>, std::io::Error> { let accounts = rpc .get_multiple_accounts(addresses) - .map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, e.to_string()))?; + .map_err(|e| std::io::Error::other(e.to_string()))?; let mut decoded_accounts: Vec> = Vec::new(); for i in 0..addresses.len() { let address = addresses[i]; @@ -164,8 +154,8 @@ impl anchor_lang::AccountSerialize for GovernanceV1 {} #[cfg(feature = "anchor")] impl anchor_lang::Owner for GovernanceV1 { - fn owner() -> Pubkey { - crate::SPL_GOVERNANCE_ID + fn owner() -> anchor_lang::solana_program::pubkey::Pubkey { + anchor_lang::solana_program::pubkey::Pubkey::from(crate::SPL_GOVERNANCE_ID.to_bytes()) } } diff --git a/e2e/governance/src/generated/accounts/governance_v2.rs b/e2e/governance/src/generated/accounts/governance_v2.rs index 85e117f..d85b261 100644 --- a/e2e/governance/src/generated/accounts/governance_v2.rs +++ b/e2e/governance/src/generated/accounts/governance_v2.rs @@ -10,22 +10,13 @@ use crate::generated::types::GovernanceConfig; use crate::generated::types::Reserved119; use borsh::BorshDeserialize; use borsh::BorshSerialize; -use solana_pubkey::Pubkey; +use solana_address::Address; #[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] -#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct GovernanceV2 { pub account_type: GovernanceAccountType, - #[cfg_attr( - feature = "serde", - serde(with = "serde_with::As::") - )] - pub realm: Pubkey, - #[cfg_attr( - feature = "serde", - serde(with = "serde_with::As::") - )] - pub governed_account: Pubkey, + pub realm: Address, + pub governed_account: Address, pub reserved1: u32, pub config: GovernanceConfig, pub reserved_v2: Reserved119, @@ -39,16 +30,16 @@ impl GovernanceV2 { /// Values are positional and appear in the following order: /// /// 0. `GovernanceV2::PREFIX` - /// 1. realm (`Pubkey`) - /// 2. seed (`Pubkey`) + /// 1. realm (`Address`) + /// 2. seed (`Address`) pub const PREFIX: &'static [u8] = "account-governance".as_bytes(); pub fn create_pda( - realm: Pubkey, - seed: Pubkey, + realm: Address, + seed: Address, bump: u8, - ) -> Result { - solana_pubkey::Pubkey::create_program_address( + ) -> Result { + solana_address::Address::create_program_address( &[ "account-governance".as_bytes(), realm.as_ref(), @@ -59,8 +50,8 @@ impl GovernanceV2 { ) } - pub fn find_pda(realm: &Pubkey, seed: &Pubkey) -> (solana_pubkey::Pubkey, u8) { - solana_pubkey::Pubkey::find_program_address( + pub fn find_pda(realm: &Address, seed: &Address) -> (solana_address::Address, u8) { + solana_address::Address::find_program_address( &[ "account-governance".as_bytes(), realm.as_ref(), @@ -89,7 +80,7 @@ impl<'a> TryFrom<&solana_account_info::AccountInfo<'a>> for GovernanceV2 { #[cfg(feature = "fetch")] pub fn fetch_governance_v2( rpc: &solana_client::rpc_client::RpcClient, - address: &solana_pubkey::Pubkey, + address: &solana_address::Address, ) -> Result, std::io::Error> { let accounts = fetch_all_governance_v2(rpc, &[*address])?; Ok(accounts[0].clone()) @@ -98,18 +89,17 @@ pub fn fetch_governance_v2( #[cfg(feature = "fetch")] pub fn fetch_all_governance_v2( rpc: &solana_client::rpc_client::RpcClient, - addresses: &[solana_pubkey::Pubkey], + addresses: &[solana_address::Address], ) -> Result>, std::io::Error> { let accounts = rpc .get_multiple_accounts(addresses) - .map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, e.to_string()))?; + .map_err(|e| std::io::Error::other(e.to_string()))?; let mut decoded_accounts: Vec> = Vec::new(); for i in 0..addresses.len() { let address = addresses[i]; - let account = accounts[i].as_ref().ok_or(std::io::Error::new( - std::io::ErrorKind::Other, - format!("Account not found: {}", address), - ))?; + let account = accounts[i].as_ref().ok_or(std::io::Error::other(format!( + "Account not found: {address}" + )))?; let data = GovernanceV2::from_bytes(&account.data)?; decoded_accounts.push(crate::shared::DecodedAccount { address, @@ -123,7 +113,7 @@ pub fn fetch_all_governance_v2( #[cfg(feature = "fetch")] pub fn fetch_maybe_governance_v2( rpc: &solana_client::rpc_client::RpcClient, - address: &solana_pubkey::Pubkey, + address: &solana_address::Address, ) -> Result, std::io::Error> { let accounts = fetch_all_maybe_governance_v2(rpc, &[*address])?; Ok(accounts[0].clone()) @@ -132,11 +122,11 @@ pub fn fetch_maybe_governance_v2( #[cfg(feature = "fetch")] pub fn fetch_all_maybe_governance_v2( rpc: &solana_client::rpc_client::RpcClient, - addresses: &[solana_pubkey::Pubkey], + addresses: &[solana_address::Address], ) -> Result>, std::io::Error> { let accounts = rpc .get_multiple_accounts(addresses) - .map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, e.to_string()))?; + .map_err(|e| std::io::Error::other(e.to_string()))?; let mut decoded_accounts: Vec> = Vec::new(); for i in 0..addresses.len() { let address = addresses[i]; @@ -168,8 +158,8 @@ impl anchor_lang::AccountSerialize for GovernanceV2 {} #[cfg(feature = "anchor")] impl anchor_lang::Owner for GovernanceV2 { - fn owner() -> Pubkey { - crate::SPL_GOVERNANCE_ID + fn owner() -> anchor_lang::solana_program::pubkey::Pubkey { + anchor_lang::solana_program::pubkey::Pubkey::from(crate::SPL_GOVERNANCE_ID.to_bytes()) } } diff --git a/e2e/governance/src/generated/accounts/legacy_token_owner_record.rs b/e2e/governance/src/generated/accounts/legacy_token_owner_record.rs index 0547d43..7d67b53 100644 --- a/e2e/governance/src/generated/accounts/legacy_token_owner_record.rs +++ b/e2e/governance/src/generated/accounts/legacy_token_owner_record.rs @@ -8,34 +8,20 @@ use crate::generated::types::GovernanceAccountType; use borsh::BorshDeserialize; use borsh::BorshSerialize; -use solana_pubkey::Pubkey; +use solana_address::Address; #[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] -#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct LegacyTokenOwnerRecord { pub account_type: GovernanceAccountType, - #[cfg_attr( - feature = "serde", - serde(with = "serde_with::As::") - )] - pub realm: Pubkey, - #[cfg_attr( - feature = "serde", - serde(with = "serde_with::As::") - )] - pub governing_token_mint: Pubkey, - #[cfg_attr( - feature = "serde", - serde(with = "serde_with::As::") - )] - pub governing_token_owner: Pubkey, + pub realm: Address, + pub governing_token_mint: Address, + pub governing_token_owner: Address, pub governing_token_deposit_amount: u64, pub unrelinquished_votes_count: u32, pub total_votes_count: u32, pub outstanding_proposal_count: u8, pub reserved: [u8; 7], - pub governance_delegate: Option, - #[cfg_attr(feature = "serde", serde(with = "serde_big_array::BigArray"))] + pub governance_delegate: Option
, pub reserved_v2: [u8; 128], } @@ -45,18 +31,18 @@ impl LegacyTokenOwnerRecord { /// Values are positional and appear in the following order: /// /// 0. `LegacyTokenOwnerRecord::PREFIX` - /// 1. realm (`Pubkey`) - /// 2. governing_token_mint (`Pubkey`) - /// 3. governing_token_owner (`Pubkey`) + /// 1. realm (`Address`) + /// 2. governing_token_mint (`Address`) + /// 3. governing_token_owner (`Address`) pub const PREFIX: &'static [u8] = "governance".as_bytes(); pub fn create_pda( - realm: Pubkey, - governing_token_mint: Pubkey, - governing_token_owner: Pubkey, + realm: Address, + governing_token_mint: Address, + governing_token_owner: Address, bump: u8, - ) -> Result { - solana_pubkey::Pubkey::create_program_address( + ) -> Result { + solana_address::Address::create_program_address( &[ "governance".as_bytes(), realm.as_ref(), @@ -69,11 +55,11 @@ impl LegacyTokenOwnerRecord { } pub fn find_pda( - realm: &Pubkey, - governing_token_mint: &Pubkey, - governing_token_owner: &Pubkey, - ) -> (solana_pubkey::Pubkey, u8) { - solana_pubkey::Pubkey::find_program_address( + realm: &Address, + governing_token_mint: &Address, + governing_token_owner: &Address, + ) -> (solana_address::Address, u8) { + solana_address::Address::find_program_address( &[ "governance".as_bytes(), realm.as_ref(), @@ -103,7 +89,7 @@ impl<'a> TryFrom<&solana_account_info::AccountInfo<'a>> for LegacyTokenOwnerReco #[cfg(feature = "fetch")] pub fn fetch_legacy_token_owner_record( rpc: &solana_client::rpc_client::RpcClient, - address: &solana_pubkey::Pubkey, + address: &solana_address::Address, ) -> Result, std::io::Error> { let accounts = fetch_all_legacy_token_owner_record(rpc, &[*address])?; Ok(accounts[0].clone()) @@ -112,19 +98,18 @@ pub fn fetch_legacy_token_owner_record( #[cfg(feature = "fetch")] pub fn fetch_all_legacy_token_owner_record( rpc: &solana_client::rpc_client::RpcClient, - addresses: &[solana_pubkey::Pubkey], + addresses: &[solana_address::Address], ) -> Result>, std::io::Error> { let accounts = rpc .get_multiple_accounts(addresses) - .map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, e.to_string()))?; + .map_err(|e| std::io::Error::other(e.to_string()))?; let mut decoded_accounts: Vec> = Vec::new(); for i in 0..addresses.len() { let address = addresses[i]; - let account = accounts[i].as_ref().ok_or(std::io::Error::new( - std::io::ErrorKind::Other, - format!("Account not found: {}", address), - ))?; + let account = accounts[i].as_ref().ok_or(std::io::Error::other(format!( + "Account not found: {address}" + )))?; let data = LegacyTokenOwnerRecord::from_bytes(&account.data)?; decoded_accounts.push(crate::shared::DecodedAccount { address, @@ -138,7 +123,7 @@ pub fn fetch_all_legacy_token_owner_record( #[cfg(feature = "fetch")] pub fn fetch_maybe_legacy_token_owner_record( rpc: &solana_client::rpc_client::RpcClient, - address: &solana_pubkey::Pubkey, + address: &solana_address::Address, ) -> Result, std::io::Error> { let accounts = fetch_all_maybe_legacy_token_owner_record(rpc, &[*address])?; Ok(accounts[0].clone()) @@ -147,11 +132,11 @@ pub fn fetch_maybe_legacy_token_owner_record( #[cfg(feature = "fetch")] pub fn fetch_all_maybe_legacy_token_owner_record( rpc: &solana_client::rpc_client::RpcClient, - addresses: &[solana_pubkey::Pubkey], + addresses: &[solana_address::Address], ) -> Result>, std::io::Error> { let accounts = rpc .get_multiple_accounts(addresses) - .map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, e.to_string()))?; + .map_err(|e| std::io::Error::other(e.to_string()))?; let mut decoded_accounts: Vec> = Vec::new(); for i in 0..addresses.len() { let address = addresses[i]; @@ -183,8 +168,8 @@ impl anchor_lang::AccountSerialize for LegacyTokenOwnerRecord {} #[cfg(feature = "anchor")] impl anchor_lang::Owner for LegacyTokenOwnerRecord { - fn owner() -> Pubkey { - crate::SPL_GOVERNANCE_ID + fn owner() -> anchor_lang::solana_program::pubkey::Pubkey { + anchor_lang::solana_program::pubkey::Pubkey::from(crate::SPL_GOVERNANCE_ID.to_bytes()) } } diff --git a/e2e/governance/src/generated/accounts/program_metadata.rs b/e2e/governance/src/generated/accounts/program_metadata.rs index 5e2b867..fa58103 100644 --- a/e2e/governance/src/generated/accounts/program_metadata.rs +++ b/e2e/governance/src/generated/accounts/program_metadata.rs @@ -11,12 +11,10 @@ use borsh::BorshDeserialize; use borsh::BorshSerialize; #[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] -#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct ProgramMetadata { pub account_type: GovernanceAccountType, pub updated_at: Slot, pub version: String, - #[cfg_attr(feature = "serde", serde(with = "serde_big_array::BigArray"))] pub reserved: [u8; 64], } @@ -40,7 +38,7 @@ impl<'a> TryFrom<&solana_account_info::AccountInfo<'a>> for ProgramMetadata { #[cfg(feature = "fetch")] pub fn fetch_program_metadata( rpc: &solana_client::rpc_client::RpcClient, - address: &solana_pubkey::Pubkey, + address: &solana_address::Address, ) -> Result, std::io::Error> { let accounts = fetch_all_program_metadata(rpc, &[*address])?; Ok(accounts[0].clone()) @@ -49,18 +47,17 @@ pub fn fetch_program_metadata( #[cfg(feature = "fetch")] pub fn fetch_all_program_metadata( rpc: &solana_client::rpc_client::RpcClient, - addresses: &[solana_pubkey::Pubkey], + addresses: &[solana_address::Address], ) -> Result>, std::io::Error> { let accounts = rpc .get_multiple_accounts(addresses) - .map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, e.to_string()))?; + .map_err(|e| std::io::Error::other(e.to_string()))?; let mut decoded_accounts: Vec> = Vec::new(); for i in 0..addresses.len() { let address = addresses[i]; - let account = accounts[i].as_ref().ok_or(std::io::Error::new( - std::io::ErrorKind::Other, - format!("Account not found: {}", address), - ))?; + let account = accounts[i].as_ref().ok_or(std::io::Error::other(format!( + "Account not found: {address}" + )))?; let data = ProgramMetadata::from_bytes(&account.data)?; decoded_accounts.push(crate::shared::DecodedAccount { address, @@ -74,7 +71,7 @@ pub fn fetch_all_program_metadata( #[cfg(feature = "fetch")] pub fn fetch_maybe_program_metadata( rpc: &solana_client::rpc_client::RpcClient, - address: &solana_pubkey::Pubkey, + address: &solana_address::Address, ) -> Result, std::io::Error> { let accounts = fetch_all_maybe_program_metadata(rpc, &[*address])?; Ok(accounts[0].clone()) @@ -83,11 +80,11 @@ pub fn fetch_maybe_program_metadata( #[cfg(feature = "fetch")] pub fn fetch_all_maybe_program_metadata( rpc: &solana_client::rpc_client::RpcClient, - addresses: &[solana_pubkey::Pubkey], + addresses: &[solana_address::Address], ) -> Result>, std::io::Error> { let accounts = rpc .get_multiple_accounts(addresses) - .map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, e.to_string()))?; + .map_err(|e| std::io::Error::other(e.to_string()))?; let mut decoded_accounts: Vec> = Vec::new(); for i in 0..addresses.len() { let address = addresses[i]; @@ -119,8 +116,8 @@ impl anchor_lang::AccountSerialize for ProgramMetadata {} #[cfg(feature = "anchor")] impl anchor_lang::Owner for ProgramMetadata { - fn owner() -> Pubkey { - crate::SPL_GOVERNANCE_ID + fn owner() -> anchor_lang::solana_program::pubkey::Pubkey { + anchor_lang::solana_program::pubkey::Pubkey::from(crate::SPL_GOVERNANCE_ID.to_bytes()) } } diff --git a/e2e/governance/src/generated/accounts/proposal_deposit.rs b/e2e/governance/src/generated/accounts/proposal_deposit.rs index 695552b..e608fba 100644 --- a/e2e/governance/src/generated/accounts/proposal_deposit.rs +++ b/e2e/governance/src/generated/accounts/proposal_deposit.rs @@ -8,23 +8,13 @@ use crate::generated::types::GovernanceAccountType; use borsh::BorshDeserialize; use borsh::BorshSerialize; -use solana_pubkey::Pubkey; +use solana_address::Address; #[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] -#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct ProposalDeposit { pub account_type: GovernanceAccountType, - #[cfg_attr( - feature = "serde", - serde(with = "serde_with::As::") - )] - pub proposal: Pubkey, - #[cfg_attr( - feature = "serde", - serde(with = "serde_with::As::") - )] - pub deposit_payer: Pubkey, - #[cfg_attr(feature = "serde", serde(with = "serde_big_array::BigArray"))] + pub proposal: Address, + pub deposit_payer: Address, pub reserved: [u8; 64], } @@ -34,16 +24,16 @@ impl ProposalDeposit { /// Values are positional and appear in the following order: /// /// 0. `ProposalDeposit::PREFIX` - /// 1. proposal (`Pubkey`) - /// 2. deposit_payer (`Pubkey`) + /// 1. proposal (`Address`) + /// 2. deposit_payer (`Address`) pub const PREFIX: &'static [u8] = "proposal-deposit".as_bytes(); pub fn create_pda( - proposal: Pubkey, - deposit_payer: Pubkey, + proposal: Address, + deposit_payer: Address, bump: u8, - ) -> Result { - solana_pubkey::Pubkey::create_program_address( + ) -> Result { + solana_address::Address::create_program_address( &[ "proposal-deposit".as_bytes(), proposal.as_ref(), @@ -54,8 +44,8 @@ impl ProposalDeposit { ) } - pub fn find_pda(proposal: &Pubkey, deposit_payer: &Pubkey) -> (solana_pubkey::Pubkey, u8) { - solana_pubkey::Pubkey::find_program_address( + pub fn find_pda(proposal: &Address, deposit_payer: &Address) -> (solana_address::Address, u8) { + solana_address::Address::find_program_address( &[ "proposal-deposit".as_bytes(), proposal.as_ref(), @@ -84,7 +74,7 @@ impl<'a> TryFrom<&solana_account_info::AccountInfo<'a>> for ProposalDeposit { #[cfg(feature = "fetch")] pub fn fetch_proposal_deposit( rpc: &solana_client::rpc_client::RpcClient, - address: &solana_pubkey::Pubkey, + address: &solana_address::Address, ) -> Result, std::io::Error> { let accounts = fetch_all_proposal_deposit(rpc, &[*address])?; Ok(accounts[0].clone()) @@ -93,18 +83,17 @@ pub fn fetch_proposal_deposit( #[cfg(feature = "fetch")] pub fn fetch_all_proposal_deposit( rpc: &solana_client::rpc_client::RpcClient, - addresses: &[solana_pubkey::Pubkey], + addresses: &[solana_address::Address], ) -> Result>, std::io::Error> { let accounts = rpc .get_multiple_accounts(addresses) - .map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, e.to_string()))?; + .map_err(|e| std::io::Error::other(e.to_string()))?; let mut decoded_accounts: Vec> = Vec::new(); for i in 0..addresses.len() { let address = addresses[i]; - let account = accounts[i].as_ref().ok_or(std::io::Error::new( - std::io::ErrorKind::Other, - format!("Account not found: {}", address), - ))?; + let account = accounts[i].as_ref().ok_or(std::io::Error::other(format!( + "Account not found: {address}" + )))?; let data = ProposalDeposit::from_bytes(&account.data)?; decoded_accounts.push(crate::shared::DecodedAccount { address, @@ -118,7 +107,7 @@ pub fn fetch_all_proposal_deposit( #[cfg(feature = "fetch")] pub fn fetch_maybe_proposal_deposit( rpc: &solana_client::rpc_client::RpcClient, - address: &solana_pubkey::Pubkey, + address: &solana_address::Address, ) -> Result, std::io::Error> { let accounts = fetch_all_maybe_proposal_deposit(rpc, &[*address])?; Ok(accounts[0].clone()) @@ -127,11 +116,11 @@ pub fn fetch_maybe_proposal_deposit( #[cfg(feature = "fetch")] pub fn fetch_all_maybe_proposal_deposit( rpc: &solana_client::rpc_client::RpcClient, - addresses: &[solana_pubkey::Pubkey], + addresses: &[solana_address::Address], ) -> Result>, std::io::Error> { let accounts = rpc .get_multiple_accounts(addresses) - .map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, e.to_string()))?; + .map_err(|e| std::io::Error::other(e.to_string()))?; let mut decoded_accounts: Vec> = Vec::new(); for i in 0..addresses.len() { let address = addresses[i]; @@ -163,8 +152,8 @@ impl anchor_lang::AccountSerialize for ProposalDeposit {} #[cfg(feature = "anchor")] impl anchor_lang::Owner for ProposalDeposit { - fn owner() -> Pubkey { - crate::SPL_GOVERNANCE_ID + fn owner() -> anchor_lang::solana_program::pubkey::Pubkey { + anchor_lang::solana_program::pubkey::Pubkey::from(crate::SPL_GOVERNANCE_ID.to_bytes()) } } diff --git a/e2e/governance/src/generated/accounts/proposal_instruction_v1.rs b/e2e/governance/src/generated/accounts/proposal_instruction_v1.rs index 28df3ab..a1ccf2e 100644 --- a/e2e/governance/src/generated/accounts/proposal_instruction_v1.rs +++ b/e2e/governance/src/generated/accounts/proposal_instruction_v1.rs @@ -11,17 +11,12 @@ use crate::generated::types::TransactionExecutionStatus; use crate::generated::types::UnixTimestamp; use borsh::BorshDeserialize; use borsh::BorshSerialize; -use solana_pubkey::Pubkey; +use solana_address::Address; #[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] -#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct ProposalInstructionV1 { pub account_type: GovernanceAccountType, - #[cfg_attr( - feature = "serde", - serde(with = "serde_with::As::") - )] - pub proposal: Pubkey, + pub proposal: Address, pub instruction_index: u16, pub hold_up_time: u32, pub instruction: InstructionData, @@ -35,18 +30,18 @@ impl ProposalInstructionV1 { /// Values are positional and appear in the following order: /// /// 0. `ProposalInstructionV1::PREFIX` - /// 1. proposal (`Pubkey`) + /// 1. proposal (`Address`) /// 2. option_index (`u8`) /// 3. index (`u16`) pub const PREFIX: &'static [u8] = "governance".as_bytes(); pub fn create_pda( - proposal: Pubkey, + proposal: Address, option_index: u8, index: u16, bump: u8, - ) -> Result { - solana_pubkey::Pubkey::create_program_address( + ) -> Result { + solana_address::Address::create_program_address( &[ "governance".as_bytes(), proposal.as_ref(), @@ -59,11 +54,11 @@ impl ProposalInstructionV1 { } pub fn find_pda( - proposal: &Pubkey, + proposal: &Address, option_index: u8, index: u16, - ) -> (solana_pubkey::Pubkey, u8) { - solana_pubkey::Pubkey::find_program_address( + ) -> (solana_address::Address, u8) { + solana_address::Address::find_program_address( &[ "governance".as_bytes(), proposal.as_ref(), @@ -93,7 +88,7 @@ impl<'a> TryFrom<&solana_account_info::AccountInfo<'a>> for ProposalInstructionV #[cfg(feature = "fetch")] pub fn fetch_proposal_instruction_v1( rpc: &solana_client::rpc_client::RpcClient, - address: &solana_pubkey::Pubkey, + address: &solana_address::Address, ) -> Result, std::io::Error> { let accounts = fetch_all_proposal_instruction_v1(rpc, &[*address])?; Ok(accounts[0].clone()) @@ -102,19 +97,18 @@ pub fn fetch_proposal_instruction_v1( #[cfg(feature = "fetch")] pub fn fetch_all_proposal_instruction_v1( rpc: &solana_client::rpc_client::RpcClient, - addresses: &[solana_pubkey::Pubkey], + addresses: &[solana_address::Address], ) -> Result>, std::io::Error> { let accounts = rpc .get_multiple_accounts(addresses) - .map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, e.to_string()))?; + .map_err(|e| std::io::Error::other(e.to_string()))?; let mut decoded_accounts: Vec> = Vec::new(); for i in 0..addresses.len() { let address = addresses[i]; - let account = accounts[i].as_ref().ok_or(std::io::Error::new( - std::io::ErrorKind::Other, - format!("Account not found: {}", address), - ))?; + let account = accounts[i].as_ref().ok_or(std::io::Error::other(format!( + "Account not found: {address}" + )))?; let data = ProposalInstructionV1::from_bytes(&account.data)?; decoded_accounts.push(crate::shared::DecodedAccount { address, @@ -128,7 +122,7 @@ pub fn fetch_all_proposal_instruction_v1( #[cfg(feature = "fetch")] pub fn fetch_maybe_proposal_instruction_v1( rpc: &solana_client::rpc_client::RpcClient, - address: &solana_pubkey::Pubkey, + address: &solana_address::Address, ) -> Result, std::io::Error> { let accounts = fetch_all_maybe_proposal_instruction_v1(rpc, &[*address])?; Ok(accounts[0].clone()) @@ -137,11 +131,11 @@ pub fn fetch_maybe_proposal_instruction_v1( #[cfg(feature = "fetch")] pub fn fetch_all_maybe_proposal_instruction_v1( rpc: &solana_client::rpc_client::RpcClient, - addresses: &[solana_pubkey::Pubkey], + addresses: &[solana_address::Address], ) -> Result>, std::io::Error> { let accounts = rpc .get_multiple_accounts(addresses) - .map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, e.to_string()))?; + .map_err(|e| std::io::Error::other(e.to_string()))?; let mut decoded_accounts: Vec> = Vec::new(); for i in 0..addresses.len() { let address = addresses[i]; @@ -173,8 +167,8 @@ impl anchor_lang::AccountSerialize for ProposalInstructionV1 {} #[cfg(feature = "anchor")] impl anchor_lang::Owner for ProposalInstructionV1 { - fn owner() -> Pubkey { - crate::SPL_GOVERNANCE_ID + fn owner() -> anchor_lang::solana_program::pubkey::Pubkey { + anchor_lang::solana_program::pubkey::Pubkey::from(crate::SPL_GOVERNANCE_ID.to_bytes()) } } diff --git a/e2e/governance/src/generated/accounts/proposal_transaction_v2.rs b/e2e/governance/src/generated/accounts/proposal_transaction_v2.rs index 9fa1d2e..16fe28a 100644 --- a/e2e/governance/src/generated/accounts/proposal_transaction_v2.rs +++ b/e2e/governance/src/generated/accounts/proposal_transaction_v2.rs @@ -11,17 +11,12 @@ use crate::generated::types::TransactionExecutionStatus; use crate::generated::types::UnixTimestamp; use borsh::BorshDeserialize; use borsh::BorshSerialize; -use solana_pubkey::Pubkey; +use solana_address::Address; #[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] -#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct ProposalTransactionV2 { pub account_type: GovernanceAccountType, - #[cfg_attr( - feature = "serde", - serde(with = "serde_with::As::") - )] - pub proposal: Pubkey, + pub proposal: Address, pub option_index: u8, pub transaction_index: u16, pub hold_up_time: u32, @@ -37,18 +32,18 @@ impl ProposalTransactionV2 { /// Values are positional and appear in the following order: /// /// 0. `ProposalTransactionV2::PREFIX` - /// 1. proposal (`Pubkey`) + /// 1. proposal (`Address`) /// 2. option_index (`u8`) /// 3. index (`u16`) pub const PREFIX: &'static [u8] = "governance".as_bytes(); pub fn create_pda( - proposal: Pubkey, + proposal: Address, option_index: u8, index: u16, bump: u8, - ) -> Result { - solana_pubkey::Pubkey::create_program_address( + ) -> Result { + solana_address::Address::create_program_address( &[ "governance".as_bytes(), proposal.as_ref(), @@ -61,11 +56,11 @@ impl ProposalTransactionV2 { } pub fn find_pda( - proposal: &Pubkey, + proposal: &Address, option_index: u8, index: u16, - ) -> (solana_pubkey::Pubkey, u8) { - solana_pubkey::Pubkey::find_program_address( + ) -> (solana_address::Address, u8) { + solana_address::Address::find_program_address( &[ "governance".as_bytes(), proposal.as_ref(), @@ -95,7 +90,7 @@ impl<'a> TryFrom<&solana_account_info::AccountInfo<'a>> for ProposalTransactionV #[cfg(feature = "fetch")] pub fn fetch_proposal_transaction_v2( rpc: &solana_client::rpc_client::RpcClient, - address: &solana_pubkey::Pubkey, + address: &solana_address::Address, ) -> Result, std::io::Error> { let accounts = fetch_all_proposal_transaction_v2(rpc, &[*address])?; Ok(accounts[0].clone()) @@ -104,19 +99,18 @@ pub fn fetch_proposal_transaction_v2( #[cfg(feature = "fetch")] pub fn fetch_all_proposal_transaction_v2( rpc: &solana_client::rpc_client::RpcClient, - addresses: &[solana_pubkey::Pubkey], + addresses: &[solana_address::Address], ) -> Result>, std::io::Error> { let accounts = rpc .get_multiple_accounts(addresses) - .map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, e.to_string()))?; + .map_err(|e| std::io::Error::other(e.to_string()))?; let mut decoded_accounts: Vec> = Vec::new(); for i in 0..addresses.len() { let address = addresses[i]; - let account = accounts[i].as_ref().ok_or(std::io::Error::new( - std::io::ErrorKind::Other, - format!("Account not found: {}", address), - ))?; + let account = accounts[i].as_ref().ok_or(std::io::Error::other(format!( + "Account not found: {address}" + )))?; let data = ProposalTransactionV2::from_bytes(&account.data)?; decoded_accounts.push(crate::shared::DecodedAccount { address, @@ -130,7 +124,7 @@ pub fn fetch_all_proposal_transaction_v2( #[cfg(feature = "fetch")] pub fn fetch_maybe_proposal_transaction_v2( rpc: &solana_client::rpc_client::RpcClient, - address: &solana_pubkey::Pubkey, + address: &solana_address::Address, ) -> Result, std::io::Error> { let accounts = fetch_all_maybe_proposal_transaction_v2(rpc, &[*address])?; Ok(accounts[0].clone()) @@ -139,11 +133,11 @@ pub fn fetch_maybe_proposal_transaction_v2( #[cfg(feature = "fetch")] pub fn fetch_all_maybe_proposal_transaction_v2( rpc: &solana_client::rpc_client::RpcClient, - addresses: &[solana_pubkey::Pubkey], + addresses: &[solana_address::Address], ) -> Result>, std::io::Error> { let accounts = rpc .get_multiple_accounts(addresses) - .map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, e.to_string()))?; + .map_err(|e| std::io::Error::other(e.to_string()))?; let mut decoded_accounts: Vec> = Vec::new(); for i in 0..addresses.len() { let address = addresses[i]; @@ -175,8 +169,8 @@ impl anchor_lang::AccountSerialize for ProposalTransactionV2 {} #[cfg(feature = "anchor")] impl anchor_lang::Owner for ProposalTransactionV2 { - fn owner() -> Pubkey { - crate::SPL_GOVERNANCE_ID + fn owner() -> anchor_lang::solana_program::pubkey::Pubkey { + anchor_lang::solana_program::pubkey::Pubkey::from(crate::SPL_GOVERNANCE_ID.to_bytes()) } } diff --git a/e2e/governance/src/generated/accounts/proposal_v1.rs b/e2e/governance/src/generated/accounts/proposal_v1.rs index 7c68cb4..0173a81 100644 --- a/e2e/governance/src/generated/accounts/proposal_v1.rs +++ b/e2e/governance/src/generated/accounts/proposal_v1.rs @@ -13,28 +13,15 @@ use crate::generated::types::UnixTimestamp; use crate::generated::types::VoteThreshold; use borsh::BorshDeserialize; use borsh::BorshSerialize; -use solana_pubkey::Pubkey; +use solana_address::Address; #[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] -#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct ProposalV1 { pub account_type: GovernanceAccountType, - #[cfg_attr( - feature = "serde", - serde(with = "serde_with::As::") - )] - pub governance: Pubkey, - #[cfg_attr( - feature = "serde", - serde(with = "serde_with::As::") - )] - pub governing_token_mint: Pubkey, + pub governance: Address, + pub governing_token_mint: Address, pub state: ProposalState, - #[cfg_attr( - feature = "serde", - serde(with = "serde_with::As::") - )] - pub token_owner_record: Pubkey, + pub token_owner_record: Address, pub signatories_count: u8, pub signatories_signed_off_count: u8, pub yes_votes_count: u64, @@ -62,18 +49,18 @@ impl ProposalV1 { /// Values are positional and appear in the following order: /// /// 0. `ProposalV1::PREFIX` - /// 1. governance (`Pubkey`) - /// 2. governing_token_mint (`Pubkey`) - /// 3. proposal_seed (`Pubkey`) + /// 1. governance (`Address`) + /// 2. governing_token_mint (`Address`) + /// 3. proposal_seed (`Address`) pub const PREFIX: &'static [u8] = "governance".as_bytes(); pub fn create_pda( - governance: Pubkey, - governing_token_mint: Pubkey, - proposal_seed: Pubkey, + governance: Address, + governing_token_mint: Address, + proposal_seed: Address, bump: u8, - ) -> Result { - solana_pubkey::Pubkey::create_program_address( + ) -> Result { + solana_address::Address::create_program_address( &[ "governance".as_bytes(), governance.as_ref(), @@ -86,11 +73,11 @@ impl ProposalV1 { } pub fn find_pda( - governance: &Pubkey, - governing_token_mint: &Pubkey, - proposal_seed: &Pubkey, - ) -> (solana_pubkey::Pubkey, u8) { - solana_pubkey::Pubkey::find_program_address( + governance: &Address, + governing_token_mint: &Address, + proposal_seed: &Address, + ) -> (solana_address::Address, u8) { + solana_address::Address::find_program_address( &[ "governance".as_bytes(), governance.as_ref(), @@ -120,7 +107,7 @@ impl<'a> TryFrom<&solana_account_info::AccountInfo<'a>> for ProposalV1 { #[cfg(feature = "fetch")] pub fn fetch_proposal_v1( rpc: &solana_client::rpc_client::RpcClient, - address: &solana_pubkey::Pubkey, + address: &solana_address::Address, ) -> Result, std::io::Error> { let accounts = fetch_all_proposal_v1(rpc, &[*address])?; Ok(accounts[0].clone()) @@ -129,18 +116,17 @@ pub fn fetch_proposal_v1( #[cfg(feature = "fetch")] pub fn fetch_all_proposal_v1( rpc: &solana_client::rpc_client::RpcClient, - addresses: &[solana_pubkey::Pubkey], + addresses: &[solana_address::Address], ) -> Result>, std::io::Error> { let accounts = rpc .get_multiple_accounts(addresses) - .map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, e.to_string()))?; + .map_err(|e| std::io::Error::other(e.to_string()))?; let mut decoded_accounts: Vec> = Vec::new(); for i in 0..addresses.len() { let address = addresses[i]; - let account = accounts[i].as_ref().ok_or(std::io::Error::new( - std::io::ErrorKind::Other, - format!("Account not found: {}", address), - ))?; + let account = accounts[i].as_ref().ok_or(std::io::Error::other(format!( + "Account not found: {address}" + )))?; let data = ProposalV1::from_bytes(&account.data)?; decoded_accounts.push(crate::shared::DecodedAccount { address, @@ -154,7 +140,7 @@ pub fn fetch_all_proposal_v1( #[cfg(feature = "fetch")] pub fn fetch_maybe_proposal_v1( rpc: &solana_client::rpc_client::RpcClient, - address: &solana_pubkey::Pubkey, + address: &solana_address::Address, ) -> Result, std::io::Error> { let accounts = fetch_all_maybe_proposal_v1(rpc, &[*address])?; Ok(accounts[0].clone()) @@ -163,11 +149,11 @@ pub fn fetch_maybe_proposal_v1( #[cfg(feature = "fetch")] pub fn fetch_all_maybe_proposal_v1( rpc: &solana_client::rpc_client::RpcClient, - addresses: &[solana_pubkey::Pubkey], + addresses: &[solana_address::Address], ) -> Result>, std::io::Error> { let accounts = rpc .get_multiple_accounts(addresses) - .map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, e.to_string()))?; + .map_err(|e| std::io::Error::other(e.to_string()))?; let mut decoded_accounts: Vec> = Vec::new(); for i in 0..addresses.len() { let address = addresses[i]; @@ -199,8 +185,8 @@ impl anchor_lang::AccountSerialize for ProposalV1 {} #[cfg(feature = "anchor")] impl anchor_lang::Owner for ProposalV1 { - fn owner() -> Pubkey { - crate::SPL_GOVERNANCE_ID + fn owner() -> anchor_lang::solana_program::pubkey::Pubkey { + anchor_lang::solana_program::pubkey::Pubkey::from(crate::SPL_GOVERNANCE_ID.to_bytes()) } } diff --git a/e2e/governance/src/generated/accounts/proposal_v2.rs b/e2e/governance/src/generated/accounts/proposal_v2.rs index 772d940..376ee88 100644 --- a/e2e/governance/src/generated/accounts/proposal_v2.rs +++ b/e2e/governance/src/generated/accounts/proposal_v2.rs @@ -15,28 +15,15 @@ use crate::generated::types::VoteThreshold; use crate::generated::types::VoteType; use borsh::BorshDeserialize; use borsh::BorshSerialize; -use solana_pubkey::Pubkey; +use solana_address::Address; #[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] -#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct ProposalV2 { pub account_type: GovernanceAccountType, - #[cfg_attr( - feature = "serde", - serde(with = "serde_with::As::") - )] - pub governance: Pubkey, - #[cfg_attr( - feature = "serde", - serde(with = "serde_with::As::") - )] - pub governing_token_mint: Pubkey, + pub governance: Address, + pub governing_token_mint: Address, pub state: ProposalState, - #[cfg_attr( - feature = "serde", - serde(with = "serde_with::As::") - )] - pub token_owner_record: Pubkey, + pub token_owner_record: Address, pub signatories_count: u8, pub signatories_signed_off_count: u8, pub vote_type: VoteType, @@ -56,7 +43,6 @@ pub struct ProposalV2 { pub max_vote_weight: Option, pub max_voting_time: Option, pub vote_threshold: Option, - #[cfg_attr(feature = "serde", serde(with = "serde_big_array::BigArray"))] pub reserved: [u8; 64], pub name: String, pub description_link: String, @@ -69,18 +55,18 @@ impl ProposalV2 { /// Values are positional and appear in the following order: /// /// 0. `ProposalV2::PREFIX` - /// 1. governance (`Pubkey`) - /// 2. governing_token_mint (`Pubkey`) - /// 3. proposal_seed (`Pubkey`) + /// 1. governance (`Address`) + /// 2. governing_token_mint (`Address`) + /// 3. proposal_seed (`Address`) pub const PREFIX: &'static [u8] = "governance".as_bytes(); pub fn create_pda( - governance: Pubkey, - governing_token_mint: Pubkey, - proposal_seed: Pubkey, + governance: Address, + governing_token_mint: Address, + proposal_seed: Address, bump: u8, - ) -> Result { - solana_pubkey::Pubkey::create_program_address( + ) -> Result { + solana_address::Address::create_program_address( &[ "governance".as_bytes(), governance.as_ref(), @@ -93,11 +79,11 @@ impl ProposalV2 { } pub fn find_pda( - governance: &Pubkey, - governing_token_mint: &Pubkey, - proposal_seed: &Pubkey, - ) -> (solana_pubkey::Pubkey, u8) { - solana_pubkey::Pubkey::find_program_address( + governance: &Address, + governing_token_mint: &Address, + proposal_seed: &Address, + ) -> (solana_address::Address, u8) { + solana_address::Address::find_program_address( &[ "governance".as_bytes(), governance.as_ref(), @@ -127,7 +113,7 @@ impl<'a> TryFrom<&solana_account_info::AccountInfo<'a>> for ProposalV2 { #[cfg(feature = "fetch")] pub fn fetch_proposal_v2( rpc: &solana_client::rpc_client::RpcClient, - address: &solana_pubkey::Pubkey, + address: &solana_address::Address, ) -> Result, std::io::Error> { let accounts = fetch_all_proposal_v2(rpc, &[*address])?; Ok(accounts[0].clone()) @@ -136,18 +122,17 @@ pub fn fetch_proposal_v2( #[cfg(feature = "fetch")] pub fn fetch_all_proposal_v2( rpc: &solana_client::rpc_client::RpcClient, - addresses: &[solana_pubkey::Pubkey], + addresses: &[solana_address::Address], ) -> Result>, std::io::Error> { let accounts = rpc .get_multiple_accounts(addresses) - .map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, e.to_string()))?; + .map_err(|e| std::io::Error::other(e.to_string()))?; let mut decoded_accounts: Vec> = Vec::new(); for i in 0..addresses.len() { let address = addresses[i]; - let account = accounts[i].as_ref().ok_or(std::io::Error::new( - std::io::ErrorKind::Other, - format!("Account not found: {}", address), - ))?; + let account = accounts[i].as_ref().ok_or(std::io::Error::other(format!( + "Account not found: {address}" + )))?; let data = ProposalV2::from_bytes(&account.data)?; decoded_accounts.push(crate::shared::DecodedAccount { address, @@ -161,7 +146,7 @@ pub fn fetch_all_proposal_v2( #[cfg(feature = "fetch")] pub fn fetch_maybe_proposal_v2( rpc: &solana_client::rpc_client::RpcClient, - address: &solana_pubkey::Pubkey, + address: &solana_address::Address, ) -> Result, std::io::Error> { let accounts = fetch_all_maybe_proposal_v2(rpc, &[*address])?; Ok(accounts[0].clone()) @@ -170,11 +155,11 @@ pub fn fetch_maybe_proposal_v2( #[cfg(feature = "fetch")] pub fn fetch_all_maybe_proposal_v2( rpc: &solana_client::rpc_client::RpcClient, - addresses: &[solana_pubkey::Pubkey], + addresses: &[solana_address::Address], ) -> Result>, std::io::Error> { let accounts = rpc .get_multiple_accounts(addresses) - .map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, e.to_string()))?; + .map_err(|e| std::io::Error::other(e.to_string()))?; let mut decoded_accounts: Vec> = Vec::new(); for i in 0..addresses.len() { let address = addresses[i]; @@ -206,8 +191,8 @@ impl anchor_lang::AccountSerialize for ProposalV2 {} #[cfg(feature = "anchor")] impl anchor_lang::Owner for ProposalV2 { - fn owner() -> Pubkey { - crate::SPL_GOVERNANCE_ID + fn owner() -> anchor_lang::solana_program::pubkey::Pubkey { + anchor_lang::solana_program::pubkey::Pubkey::from(crate::SPL_GOVERNANCE_ID.to_bytes()) } } diff --git a/e2e/governance/src/generated/accounts/realm_config_account.rs b/e2e/governance/src/generated/accounts/realm_config_account.rs index 2892b1b..d5e0fb2 100644 --- a/e2e/governance/src/generated/accounts/realm_config_account.rs +++ b/e2e/governance/src/generated/accounts/realm_config_account.rs @@ -10,17 +10,12 @@ use crate::generated::types::GoverningTokenConfig; use crate::generated::types::Reserved110; use borsh::BorshDeserialize; use borsh::BorshSerialize; -use solana_pubkey::Pubkey; +use solana_address::Address; #[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] -#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct RealmConfigAccount { pub account_type: GovernanceAccountType, - #[cfg_attr( - feature = "serde", - serde(with = "serde_with::As::") - )] - pub realm: Pubkey, + pub realm: Address, pub community_token_config: GoverningTokenConfig, pub council_token_config: GoverningTokenConfig, pub reserved: Reserved110, @@ -32,21 +27,21 @@ impl RealmConfigAccount { /// Values are positional and appear in the following order: /// /// 0. `RealmConfigAccount::PREFIX` - /// 1. realm (`Pubkey`) + /// 1. realm (`Address`) pub const PREFIX: &'static [u8] = "realm-config".as_bytes(); pub fn create_pda( - realm: Pubkey, + realm: Address, bump: u8, - ) -> Result { - solana_pubkey::Pubkey::create_program_address( + ) -> Result { + solana_address::Address::create_program_address( &["realm-config".as_bytes(), realm.as_ref(), &[bump]], &crate::SPL_GOVERNANCE_ID, ) } - pub fn find_pda(realm: &Pubkey) -> (solana_pubkey::Pubkey, u8) { - solana_pubkey::Pubkey::find_program_address( + pub fn find_pda(realm: &Address) -> (solana_address::Address, u8) { + solana_address::Address::find_program_address( &["realm-config".as_bytes(), realm.as_ref()], &crate::SPL_GOVERNANCE_ID, ) @@ -71,7 +66,7 @@ impl<'a> TryFrom<&solana_account_info::AccountInfo<'a>> for RealmConfigAccount { #[cfg(feature = "fetch")] pub fn fetch_realm_config_account( rpc: &solana_client::rpc_client::RpcClient, - address: &solana_pubkey::Pubkey, + address: &solana_address::Address, ) -> Result, std::io::Error> { let accounts = fetch_all_realm_config_account(rpc, &[*address])?; Ok(accounts[0].clone()) @@ -80,18 +75,17 @@ pub fn fetch_realm_config_account( #[cfg(feature = "fetch")] pub fn fetch_all_realm_config_account( rpc: &solana_client::rpc_client::RpcClient, - addresses: &[solana_pubkey::Pubkey], + addresses: &[solana_address::Address], ) -> Result>, std::io::Error> { let accounts = rpc .get_multiple_accounts(addresses) - .map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, e.to_string()))?; + .map_err(|e| std::io::Error::other(e.to_string()))?; let mut decoded_accounts: Vec> = Vec::new(); for i in 0..addresses.len() { let address = addresses[i]; - let account = accounts[i].as_ref().ok_or(std::io::Error::new( - std::io::ErrorKind::Other, - format!("Account not found: {}", address), - ))?; + let account = accounts[i].as_ref().ok_or(std::io::Error::other(format!( + "Account not found: {address}" + )))?; let data = RealmConfigAccount::from_bytes(&account.data)?; decoded_accounts.push(crate::shared::DecodedAccount { address, @@ -105,7 +99,7 @@ pub fn fetch_all_realm_config_account( #[cfg(feature = "fetch")] pub fn fetch_maybe_realm_config_account( rpc: &solana_client::rpc_client::RpcClient, - address: &solana_pubkey::Pubkey, + address: &solana_address::Address, ) -> Result, std::io::Error> { let accounts = fetch_all_maybe_realm_config_account(rpc, &[*address])?; Ok(accounts[0].clone()) @@ -114,11 +108,11 @@ pub fn fetch_maybe_realm_config_account( #[cfg(feature = "fetch")] pub fn fetch_all_maybe_realm_config_account( rpc: &solana_client::rpc_client::RpcClient, - addresses: &[solana_pubkey::Pubkey], + addresses: &[solana_address::Address], ) -> Result>, std::io::Error> { let accounts = rpc .get_multiple_accounts(addresses) - .map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, e.to_string()))?; + .map_err(|e| std::io::Error::other(e.to_string()))?; let mut decoded_accounts: Vec> = Vec::new(); for i in 0..addresses.len() { let address = addresses[i]; @@ -150,8 +144,8 @@ impl anchor_lang::AccountSerialize for RealmConfigAccount {} #[cfg(feature = "anchor")] impl anchor_lang::Owner for RealmConfigAccount { - fn owner() -> Pubkey { - crate::SPL_GOVERNANCE_ID + fn owner() -> anchor_lang::solana_program::pubkey::Pubkey { + anchor_lang::solana_program::pubkey::Pubkey::from(crate::SPL_GOVERNANCE_ID.to_bytes()) } } diff --git a/e2e/governance/src/generated/accounts/realm_v1.rs b/e2e/governance/src/generated/accounts/realm_v1.rs index d9d5dad..68774cf 100644 --- a/e2e/governance/src/generated/accounts/realm_v1.rs +++ b/e2e/governance/src/generated/accounts/realm_v1.rs @@ -9,22 +9,17 @@ use crate::generated::types::GovernanceAccountType; use crate::generated::types::RealmConfig; use borsh::BorshDeserialize; use borsh::BorshSerialize; -use kaigan::types::RemainderStr; -use solana_pubkey::Pubkey; +use solana_address::Address; +use spl_collections::TrailingStr; #[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] -#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct RealmV1 { pub account_type: GovernanceAccountType, - #[cfg_attr( - feature = "serde", - serde(with = "serde_with::As::") - )] - pub community_mint: Pubkey, + pub community_mint: Address, pub config: RealmConfig, pub reserved: [u8; 6], pub voting_proposal_count: u16, - pub authority: Option, + pub authority: Option
, pub name: String, } @@ -34,21 +29,21 @@ impl RealmV1 { /// Values are positional and appear in the following order: /// /// 0. `RealmV1::PREFIX` - /// 1. name (`RemainderStr`) + /// 1. name (`TrailingStr`) pub const PREFIX: &'static [u8] = "governance".as_bytes(); pub fn create_pda( - name: RemainderStr, + name: TrailingStr, bump: u8, - ) -> Result { - solana_pubkey::Pubkey::create_program_address( + ) -> Result { + solana_address::Address::create_program_address( &["governance".as_bytes(), name.to_string().as_ref(), &[bump]], &crate::SPL_GOVERNANCE_ID, ) } - pub fn find_pda(name: RemainderStr) -> (solana_pubkey::Pubkey, u8) { - solana_pubkey::Pubkey::find_program_address( + pub fn find_pda(name: TrailingStr) -> (solana_address::Address, u8) { + solana_address::Address::find_program_address( &["governance".as_bytes(), name.to_string().as_ref()], &crate::SPL_GOVERNANCE_ID, ) @@ -73,7 +68,7 @@ impl<'a> TryFrom<&solana_account_info::AccountInfo<'a>> for RealmV1 { #[cfg(feature = "fetch")] pub fn fetch_realm_v1( rpc: &solana_client::rpc_client::RpcClient, - address: &solana_pubkey::Pubkey, + address: &solana_address::Address, ) -> Result, std::io::Error> { let accounts = fetch_all_realm_v1(rpc, &[*address])?; Ok(accounts[0].clone()) @@ -82,18 +77,17 @@ pub fn fetch_realm_v1( #[cfg(feature = "fetch")] pub fn fetch_all_realm_v1( rpc: &solana_client::rpc_client::RpcClient, - addresses: &[solana_pubkey::Pubkey], + addresses: &[solana_address::Address], ) -> Result>, std::io::Error> { let accounts = rpc .get_multiple_accounts(addresses) - .map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, e.to_string()))?; + .map_err(|e| std::io::Error::other(e.to_string()))?; let mut decoded_accounts: Vec> = Vec::new(); for i in 0..addresses.len() { let address = addresses[i]; - let account = accounts[i].as_ref().ok_or(std::io::Error::new( - std::io::ErrorKind::Other, - format!("Account not found: {}", address), - ))?; + let account = accounts[i].as_ref().ok_or(std::io::Error::other(format!( + "Account not found: {address}" + )))?; let data = RealmV1::from_bytes(&account.data)?; decoded_accounts.push(crate::shared::DecodedAccount { address, @@ -107,7 +101,7 @@ pub fn fetch_all_realm_v1( #[cfg(feature = "fetch")] pub fn fetch_maybe_realm_v1( rpc: &solana_client::rpc_client::RpcClient, - address: &solana_pubkey::Pubkey, + address: &solana_address::Address, ) -> Result, std::io::Error> { let accounts = fetch_all_maybe_realm_v1(rpc, &[*address])?; Ok(accounts[0].clone()) @@ -116,11 +110,11 @@ pub fn fetch_maybe_realm_v1( #[cfg(feature = "fetch")] pub fn fetch_all_maybe_realm_v1( rpc: &solana_client::rpc_client::RpcClient, - addresses: &[solana_pubkey::Pubkey], + addresses: &[solana_address::Address], ) -> Result>, std::io::Error> { let accounts = rpc .get_multiple_accounts(addresses) - .map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, e.to_string()))?; + .map_err(|e| std::io::Error::other(e.to_string()))?; let mut decoded_accounts: Vec> = Vec::new(); for i in 0..addresses.len() { let address = addresses[i]; @@ -152,8 +146,8 @@ impl anchor_lang::AccountSerialize for RealmV1 {} #[cfg(feature = "anchor")] impl anchor_lang::Owner for RealmV1 { - fn owner() -> Pubkey { - crate::SPL_GOVERNANCE_ID + fn owner() -> anchor_lang::solana_program::pubkey::Pubkey { + anchor_lang::solana_program::pubkey::Pubkey::from(crate::SPL_GOVERNANCE_ID.to_bytes()) } } diff --git a/e2e/governance/src/generated/accounts/realm_v2.rs b/e2e/governance/src/generated/accounts/realm_v2.rs index 04551d8..cda3432 100644 --- a/e2e/governance/src/generated/accounts/realm_v2.rs +++ b/e2e/governance/src/generated/accounts/realm_v2.rs @@ -9,24 +9,18 @@ use crate::generated::types::GovernanceAccountType; use crate::generated::types::RealmConfig; use borsh::BorshDeserialize; use borsh::BorshSerialize; -use kaigan::types::RemainderStr; -use solana_pubkey::Pubkey; +use solana_address::Address; +use spl_collections::TrailingStr; #[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] -#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct RealmV2 { pub account_type: GovernanceAccountType, - #[cfg_attr( - feature = "serde", - serde(with = "serde_with::As::") - )] - pub community_mint: Pubkey, + pub community_mint: Address, pub config: RealmConfig, pub reserved: [u8; 6], pub legacy1: u16, - pub authority: Option, + pub authority: Option
, pub name: String, - #[cfg_attr(feature = "serde", serde(with = "serde_big_array::BigArray"))] pub reserved_v2: [u8; 128], } @@ -36,21 +30,21 @@ impl RealmV2 { /// Values are positional and appear in the following order: /// /// 0. `RealmV2::PREFIX` - /// 1. name (`RemainderStr`) + /// 1. name (`TrailingStr`) pub const PREFIX: &'static [u8] = "governance".as_bytes(); pub fn create_pda( - name: RemainderStr, + name: TrailingStr, bump: u8, - ) -> Result { - solana_pubkey::Pubkey::create_program_address( + ) -> Result { + solana_address::Address::create_program_address( &["governance".as_bytes(), name.to_string().as_ref(), &[bump]], &crate::SPL_GOVERNANCE_ID, ) } - pub fn find_pda(name: RemainderStr) -> (solana_pubkey::Pubkey, u8) { - solana_pubkey::Pubkey::find_program_address( + pub fn find_pda(name: TrailingStr) -> (solana_address::Address, u8) { + solana_address::Address::find_program_address( &["governance".as_bytes(), name.to_string().as_ref()], &crate::SPL_GOVERNANCE_ID, ) @@ -75,7 +69,7 @@ impl<'a> TryFrom<&solana_account_info::AccountInfo<'a>> for RealmV2 { #[cfg(feature = "fetch")] pub fn fetch_realm_v2( rpc: &solana_client::rpc_client::RpcClient, - address: &solana_pubkey::Pubkey, + address: &solana_address::Address, ) -> Result, std::io::Error> { let accounts = fetch_all_realm_v2(rpc, &[*address])?; Ok(accounts[0].clone()) @@ -84,18 +78,17 @@ pub fn fetch_realm_v2( #[cfg(feature = "fetch")] pub fn fetch_all_realm_v2( rpc: &solana_client::rpc_client::RpcClient, - addresses: &[solana_pubkey::Pubkey], + addresses: &[solana_address::Address], ) -> Result>, std::io::Error> { let accounts = rpc .get_multiple_accounts(addresses) - .map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, e.to_string()))?; + .map_err(|e| std::io::Error::other(e.to_string()))?; let mut decoded_accounts: Vec> = Vec::new(); for i in 0..addresses.len() { let address = addresses[i]; - let account = accounts[i].as_ref().ok_or(std::io::Error::new( - std::io::ErrorKind::Other, - format!("Account not found: {}", address), - ))?; + let account = accounts[i].as_ref().ok_or(std::io::Error::other(format!( + "Account not found: {address}" + )))?; let data = RealmV2::from_bytes(&account.data)?; decoded_accounts.push(crate::shared::DecodedAccount { address, @@ -109,7 +102,7 @@ pub fn fetch_all_realm_v2( #[cfg(feature = "fetch")] pub fn fetch_maybe_realm_v2( rpc: &solana_client::rpc_client::RpcClient, - address: &solana_pubkey::Pubkey, + address: &solana_address::Address, ) -> Result, std::io::Error> { let accounts = fetch_all_maybe_realm_v2(rpc, &[*address])?; Ok(accounts[0].clone()) @@ -118,11 +111,11 @@ pub fn fetch_maybe_realm_v2( #[cfg(feature = "fetch")] pub fn fetch_all_maybe_realm_v2( rpc: &solana_client::rpc_client::RpcClient, - addresses: &[solana_pubkey::Pubkey], + addresses: &[solana_address::Address], ) -> Result>, std::io::Error> { let accounts = rpc .get_multiple_accounts(addresses) - .map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, e.to_string()))?; + .map_err(|e| std::io::Error::other(e.to_string()))?; let mut decoded_accounts: Vec> = Vec::new(); for i in 0..addresses.len() { let address = addresses[i]; @@ -154,8 +147,8 @@ impl anchor_lang::AccountSerialize for RealmV2 {} #[cfg(feature = "anchor")] impl anchor_lang::Owner for RealmV2 { - fn owner() -> Pubkey { - crate::SPL_GOVERNANCE_ID + fn owner() -> anchor_lang::solana_program::pubkey::Pubkey { + anchor_lang::solana_program::pubkey::Pubkey::from(crate::SPL_GOVERNANCE_ID.to_bytes()) } } diff --git a/e2e/governance/src/generated/accounts/required_signatory.rs b/e2e/governance/src/generated/accounts/required_signatory.rs index 3fbfc3e..223f6b6 100644 --- a/e2e/governance/src/generated/accounts/required_signatory.rs +++ b/e2e/governance/src/generated/accounts/required_signatory.rs @@ -8,23 +8,14 @@ use crate::generated::types::GovernanceAccountType; use borsh::BorshDeserialize; use borsh::BorshSerialize; -use solana_pubkey::Pubkey; +use solana_address::Address; #[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] -#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct RequiredSignatory { pub account_type: GovernanceAccountType, pub account_version: u8, - #[cfg_attr( - feature = "serde", - serde(with = "serde_with::As::") - )] - pub governance: Pubkey, - #[cfg_attr( - feature = "serde", - serde(with = "serde_with::As::") - )] - pub signatory: Pubkey, + pub governance: Address, + pub signatory: Address, } impl RequiredSignatory { @@ -33,16 +24,16 @@ impl RequiredSignatory { /// Values are positional and appear in the following order: /// /// 0. `RequiredSignatory::PREFIX` - /// 1. governance (`Pubkey`) - /// 2. signatory (`Pubkey`) + /// 1. governance (`Address`) + /// 2. signatory (`Address`) pub const PREFIX: &'static [u8] = "required-signatory".as_bytes(); pub fn create_pda( - governance: Pubkey, - signatory: Pubkey, + governance: Address, + signatory: Address, bump: u8, - ) -> Result { - solana_pubkey::Pubkey::create_program_address( + ) -> Result { + solana_address::Address::create_program_address( &[ "required-signatory".as_bytes(), governance.as_ref(), @@ -53,8 +44,8 @@ impl RequiredSignatory { ) } - pub fn find_pda(governance: &Pubkey, signatory: &Pubkey) -> (solana_pubkey::Pubkey, u8) { - solana_pubkey::Pubkey::find_program_address( + pub fn find_pda(governance: &Address, signatory: &Address) -> (solana_address::Address, u8) { + solana_address::Address::find_program_address( &[ "required-signatory".as_bytes(), governance.as_ref(), @@ -83,7 +74,7 @@ impl<'a> TryFrom<&solana_account_info::AccountInfo<'a>> for RequiredSignatory { #[cfg(feature = "fetch")] pub fn fetch_required_signatory( rpc: &solana_client::rpc_client::RpcClient, - address: &solana_pubkey::Pubkey, + address: &solana_address::Address, ) -> Result, std::io::Error> { let accounts = fetch_all_required_signatory(rpc, &[*address])?; Ok(accounts[0].clone()) @@ -92,18 +83,17 @@ pub fn fetch_required_signatory( #[cfg(feature = "fetch")] pub fn fetch_all_required_signatory( rpc: &solana_client::rpc_client::RpcClient, - addresses: &[solana_pubkey::Pubkey], + addresses: &[solana_address::Address], ) -> Result>, std::io::Error> { let accounts = rpc .get_multiple_accounts(addresses) - .map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, e.to_string()))?; + .map_err(|e| std::io::Error::other(e.to_string()))?; let mut decoded_accounts: Vec> = Vec::new(); for i in 0..addresses.len() { let address = addresses[i]; - let account = accounts[i].as_ref().ok_or(std::io::Error::new( - std::io::ErrorKind::Other, - format!("Account not found: {}", address), - ))?; + let account = accounts[i].as_ref().ok_or(std::io::Error::other(format!( + "Account not found: {address}" + )))?; let data = RequiredSignatory::from_bytes(&account.data)?; decoded_accounts.push(crate::shared::DecodedAccount { address, @@ -117,7 +107,7 @@ pub fn fetch_all_required_signatory( #[cfg(feature = "fetch")] pub fn fetch_maybe_required_signatory( rpc: &solana_client::rpc_client::RpcClient, - address: &solana_pubkey::Pubkey, + address: &solana_address::Address, ) -> Result, std::io::Error> { let accounts = fetch_all_maybe_required_signatory(rpc, &[*address])?; Ok(accounts[0].clone()) @@ -126,11 +116,11 @@ pub fn fetch_maybe_required_signatory( #[cfg(feature = "fetch")] pub fn fetch_all_maybe_required_signatory( rpc: &solana_client::rpc_client::RpcClient, - addresses: &[solana_pubkey::Pubkey], + addresses: &[solana_address::Address], ) -> Result>, std::io::Error> { let accounts = rpc .get_multiple_accounts(addresses) - .map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, e.to_string()))?; + .map_err(|e| std::io::Error::other(e.to_string()))?; let mut decoded_accounts: Vec> = Vec::new(); for i in 0..addresses.len() { let address = addresses[i]; @@ -162,8 +152,8 @@ impl anchor_lang::AccountSerialize for RequiredSignatory {} #[cfg(feature = "anchor")] impl anchor_lang::Owner for RequiredSignatory { - fn owner() -> Pubkey { - crate::SPL_GOVERNANCE_ID + fn owner() -> anchor_lang::solana_program::pubkey::Pubkey { + anchor_lang::solana_program::pubkey::Pubkey::from(crate::SPL_GOVERNANCE_ID.to_bytes()) } } diff --git a/e2e/governance/src/generated/accounts/signatory_record_v1.rs b/e2e/governance/src/generated/accounts/signatory_record_v1.rs index 76fbe79..285afc2 100644 --- a/e2e/governance/src/generated/accounts/signatory_record_v1.rs +++ b/e2e/governance/src/generated/accounts/signatory_record_v1.rs @@ -8,22 +8,13 @@ use crate::generated::types::GovernanceAccountType; use borsh::BorshDeserialize; use borsh::BorshSerialize; -use solana_pubkey::Pubkey; +use solana_address::Address; #[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] -#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct SignatoryRecordV1 { pub account_type: GovernanceAccountType, - #[cfg_attr( - feature = "serde", - serde(with = "serde_with::As::") - )] - pub proposal: Pubkey, - #[cfg_attr( - feature = "serde", - serde(with = "serde_with::As::") - )] - pub signatory: Pubkey, + pub proposal: Address, + pub signatory: Address, pub signed_off: bool, } @@ -33,16 +24,16 @@ impl SignatoryRecordV1 { /// Values are positional and appear in the following order: /// /// 0. `SignatoryRecordV1::PREFIX` - /// 1. proposal (`Pubkey`) - /// 2. signatory (`Pubkey`) + /// 1. proposal (`Address`) + /// 2. signatory (`Address`) pub const PREFIX: &'static [u8] = "governance".as_bytes(); pub fn create_pda( - proposal: Pubkey, - signatory: Pubkey, + proposal: Address, + signatory: Address, bump: u8, - ) -> Result { - solana_pubkey::Pubkey::create_program_address( + ) -> Result { + solana_address::Address::create_program_address( &[ "governance".as_bytes(), proposal.as_ref(), @@ -53,8 +44,8 @@ impl SignatoryRecordV1 { ) } - pub fn find_pda(proposal: &Pubkey, signatory: &Pubkey) -> (solana_pubkey::Pubkey, u8) { - solana_pubkey::Pubkey::find_program_address( + pub fn find_pda(proposal: &Address, signatory: &Address) -> (solana_address::Address, u8) { + solana_address::Address::find_program_address( &[ "governance".as_bytes(), proposal.as_ref(), @@ -83,7 +74,7 @@ impl<'a> TryFrom<&solana_account_info::AccountInfo<'a>> for SignatoryRecordV1 { #[cfg(feature = "fetch")] pub fn fetch_signatory_record_v1( rpc: &solana_client::rpc_client::RpcClient, - address: &solana_pubkey::Pubkey, + address: &solana_address::Address, ) -> Result, std::io::Error> { let accounts = fetch_all_signatory_record_v1(rpc, &[*address])?; Ok(accounts[0].clone()) @@ -92,18 +83,17 @@ pub fn fetch_signatory_record_v1( #[cfg(feature = "fetch")] pub fn fetch_all_signatory_record_v1( rpc: &solana_client::rpc_client::RpcClient, - addresses: &[solana_pubkey::Pubkey], + addresses: &[solana_address::Address], ) -> Result>, std::io::Error> { let accounts = rpc .get_multiple_accounts(addresses) - .map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, e.to_string()))?; + .map_err(|e| std::io::Error::other(e.to_string()))?; let mut decoded_accounts: Vec> = Vec::new(); for i in 0..addresses.len() { let address = addresses[i]; - let account = accounts[i].as_ref().ok_or(std::io::Error::new( - std::io::ErrorKind::Other, - format!("Account not found: {}", address), - ))?; + let account = accounts[i].as_ref().ok_or(std::io::Error::other(format!( + "Account not found: {address}" + )))?; let data = SignatoryRecordV1::from_bytes(&account.data)?; decoded_accounts.push(crate::shared::DecodedAccount { address, @@ -117,7 +107,7 @@ pub fn fetch_all_signatory_record_v1( #[cfg(feature = "fetch")] pub fn fetch_maybe_signatory_record_v1( rpc: &solana_client::rpc_client::RpcClient, - address: &solana_pubkey::Pubkey, + address: &solana_address::Address, ) -> Result, std::io::Error> { let accounts = fetch_all_maybe_signatory_record_v1(rpc, &[*address])?; Ok(accounts[0].clone()) @@ -126,11 +116,11 @@ pub fn fetch_maybe_signatory_record_v1( #[cfg(feature = "fetch")] pub fn fetch_all_maybe_signatory_record_v1( rpc: &solana_client::rpc_client::RpcClient, - addresses: &[solana_pubkey::Pubkey], + addresses: &[solana_address::Address], ) -> Result>, std::io::Error> { let accounts = rpc .get_multiple_accounts(addresses) - .map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, e.to_string()))?; + .map_err(|e| std::io::Error::other(e.to_string()))?; let mut decoded_accounts: Vec> = Vec::new(); for i in 0..addresses.len() { let address = addresses[i]; @@ -162,8 +152,8 @@ impl anchor_lang::AccountSerialize for SignatoryRecordV1 {} #[cfg(feature = "anchor")] impl anchor_lang::Owner for SignatoryRecordV1 { - fn owner() -> Pubkey { - crate::SPL_GOVERNANCE_ID + fn owner() -> anchor_lang::solana_program::pubkey::Pubkey { + anchor_lang::solana_program::pubkey::Pubkey::from(crate::SPL_GOVERNANCE_ID.to_bytes()) } } diff --git a/e2e/governance/src/generated/accounts/signatory_record_v2.rs b/e2e/governance/src/generated/accounts/signatory_record_v2.rs index 40f57ea..e0fe51c 100644 --- a/e2e/governance/src/generated/accounts/signatory_record_v2.rs +++ b/e2e/governance/src/generated/accounts/signatory_record_v2.rs @@ -8,22 +8,13 @@ use crate::generated::types::GovernanceAccountType; use borsh::BorshDeserialize; use borsh::BorshSerialize; -use solana_pubkey::Pubkey; +use solana_address::Address; #[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] -#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct SignatoryRecordV2 { pub account_type: GovernanceAccountType, - #[cfg_attr( - feature = "serde", - serde(with = "serde_with::As::") - )] - pub proposal: Pubkey, - #[cfg_attr( - feature = "serde", - serde(with = "serde_with::As::") - )] - pub signatory: Pubkey, + pub proposal: Address, + pub signatory: Address, pub signed_off: bool, pub reserved_v2: [u8; 8], } @@ -34,16 +25,16 @@ impl SignatoryRecordV2 { /// Values are positional and appear in the following order: /// /// 0. `SignatoryRecordV2::PREFIX` - /// 1. proposal (`Pubkey`) - /// 2. signatory (`Pubkey`) + /// 1. proposal (`Address`) + /// 2. signatory (`Address`) pub const PREFIX: &'static [u8] = "governance".as_bytes(); pub fn create_pda( - proposal: Pubkey, - signatory: Pubkey, + proposal: Address, + signatory: Address, bump: u8, - ) -> Result { - solana_pubkey::Pubkey::create_program_address( + ) -> Result { + solana_address::Address::create_program_address( &[ "governance".as_bytes(), proposal.as_ref(), @@ -54,8 +45,8 @@ impl SignatoryRecordV2 { ) } - pub fn find_pda(proposal: &Pubkey, signatory: &Pubkey) -> (solana_pubkey::Pubkey, u8) { - solana_pubkey::Pubkey::find_program_address( + pub fn find_pda(proposal: &Address, signatory: &Address) -> (solana_address::Address, u8) { + solana_address::Address::find_program_address( &[ "governance".as_bytes(), proposal.as_ref(), @@ -84,7 +75,7 @@ impl<'a> TryFrom<&solana_account_info::AccountInfo<'a>> for SignatoryRecordV2 { #[cfg(feature = "fetch")] pub fn fetch_signatory_record_v2( rpc: &solana_client::rpc_client::RpcClient, - address: &solana_pubkey::Pubkey, + address: &solana_address::Address, ) -> Result, std::io::Error> { let accounts = fetch_all_signatory_record_v2(rpc, &[*address])?; Ok(accounts[0].clone()) @@ -93,18 +84,17 @@ pub fn fetch_signatory_record_v2( #[cfg(feature = "fetch")] pub fn fetch_all_signatory_record_v2( rpc: &solana_client::rpc_client::RpcClient, - addresses: &[solana_pubkey::Pubkey], + addresses: &[solana_address::Address], ) -> Result>, std::io::Error> { let accounts = rpc .get_multiple_accounts(addresses) - .map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, e.to_string()))?; + .map_err(|e| std::io::Error::other(e.to_string()))?; let mut decoded_accounts: Vec> = Vec::new(); for i in 0..addresses.len() { let address = addresses[i]; - let account = accounts[i].as_ref().ok_or(std::io::Error::new( - std::io::ErrorKind::Other, - format!("Account not found: {}", address), - ))?; + let account = accounts[i].as_ref().ok_or(std::io::Error::other(format!( + "Account not found: {address}" + )))?; let data = SignatoryRecordV2::from_bytes(&account.data)?; decoded_accounts.push(crate::shared::DecodedAccount { address, @@ -118,7 +108,7 @@ pub fn fetch_all_signatory_record_v2( #[cfg(feature = "fetch")] pub fn fetch_maybe_signatory_record_v2( rpc: &solana_client::rpc_client::RpcClient, - address: &solana_pubkey::Pubkey, + address: &solana_address::Address, ) -> Result, std::io::Error> { let accounts = fetch_all_maybe_signatory_record_v2(rpc, &[*address])?; Ok(accounts[0].clone()) @@ -127,11 +117,11 @@ pub fn fetch_maybe_signatory_record_v2( #[cfg(feature = "fetch")] pub fn fetch_all_maybe_signatory_record_v2( rpc: &solana_client::rpc_client::RpcClient, - addresses: &[solana_pubkey::Pubkey], + addresses: &[solana_address::Address], ) -> Result>, std::io::Error> { let accounts = rpc .get_multiple_accounts(addresses) - .map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, e.to_string()))?; + .map_err(|e| std::io::Error::other(e.to_string()))?; let mut decoded_accounts: Vec> = Vec::new(); for i in 0..addresses.len() { let address = addresses[i]; @@ -163,8 +153,8 @@ impl anchor_lang::AccountSerialize for SignatoryRecordV2 {} #[cfg(feature = "anchor")] impl anchor_lang::Owner for SignatoryRecordV2 { - fn owner() -> Pubkey { - crate::SPL_GOVERNANCE_ID + fn owner() -> anchor_lang::solana_program::pubkey::Pubkey { + anchor_lang::solana_program::pubkey::Pubkey::from(crate::SPL_GOVERNANCE_ID.to_bytes()) } } diff --git a/e2e/governance/src/generated/accounts/token_owner_record_v1.rs b/e2e/governance/src/generated/accounts/token_owner_record_v1.rs index fd4abc8..17144f9 100644 --- a/e2e/governance/src/generated/accounts/token_owner_record_v1.rs +++ b/e2e/governance/src/generated/accounts/token_owner_record_v1.rs @@ -8,33 +8,20 @@ use crate::generated::types::GovernanceAccountType; use borsh::BorshDeserialize; use borsh::BorshSerialize; -use solana_pubkey::Pubkey; +use solana_address::Address; #[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] -#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct TokenOwnerRecordV1 { pub account_type: GovernanceAccountType, - #[cfg_attr( - feature = "serde", - serde(with = "serde_with::As::") - )] - pub realm: Pubkey, - #[cfg_attr( - feature = "serde", - serde(with = "serde_with::As::") - )] - pub governing_token_mint: Pubkey, - #[cfg_attr( - feature = "serde", - serde(with = "serde_with::As::") - )] - pub governing_token_owner: Pubkey, + pub realm: Address, + pub governing_token_mint: Address, + pub governing_token_owner: Address, pub governing_token_deposit_amount: u64, pub unrelinquished_votes_count: u64, pub outstanding_proposal_count: u8, pub version: u8, pub reserved: [u8; 6], - pub governance_delegate: Option, + pub governance_delegate: Option
, } impl TokenOwnerRecordV1 { @@ -43,18 +30,18 @@ impl TokenOwnerRecordV1 { /// Values are positional and appear in the following order: /// /// 0. `TokenOwnerRecordV1::PREFIX` - /// 1. realm (`Pubkey`) - /// 2. governing_token_mint (`Pubkey`) - /// 3. governing_token_owner (`Pubkey`) + /// 1. realm (`Address`) + /// 2. governing_token_mint (`Address`) + /// 3. governing_token_owner (`Address`) pub const PREFIX: &'static [u8] = "governance".as_bytes(); pub fn create_pda( - realm: Pubkey, - governing_token_mint: Pubkey, - governing_token_owner: Pubkey, + realm: Address, + governing_token_mint: Address, + governing_token_owner: Address, bump: u8, - ) -> Result { - solana_pubkey::Pubkey::create_program_address( + ) -> Result { + solana_address::Address::create_program_address( &[ "governance".as_bytes(), realm.as_ref(), @@ -67,11 +54,11 @@ impl TokenOwnerRecordV1 { } pub fn find_pda( - realm: &Pubkey, - governing_token_mint: &Pubkey, - governing_token_owner: &Pubkey, - ) -> (solana_pubkey::Pubkey, u8) { - solana_pubkey::Pubkey::find_program_address( + realm: &Address, + governing_token_mint: &Address, + governing_token_owner: &Address, + ) -> (solana_address::Address, u8) { + solana_address::Address::find_program_address( &[ "governance".as_bytes(), realm.as_ref(), @@ -101,7 +88,7 @@ impl<'a> TryFrom<&solana_account_info::AccountInfo<'a>> for TokenOwnerRecordV1 { #[cfg(feature = "fetch")] pub fn fetch_token_owner_record_v1( rpc: &solana_client::rpc_client::RpcClient, - address: &solana_pubkey::Pubkey, + address: &solana_address::Address, ) -> Result, std::io::Error> { let accounts = fetch_all_token_owner_record_v1(rpc, &[*address])?; Ok(accounts[0].clone()) @@ -110,18 +97,17 @@ pub fn fetch_token_owner_record_v1( #[cfg(feature = "fetch")] pub fn fetch_all_token_owner_record_v1( rpc: &solana_client::rpc_client::RpcClient, - addresses: &[solana_pubkey::Pubkey], + addresses: &[solana_address::Address], ) -> Result>, std::io::Error> { let accounts = rpc .get_multiple_accounts(addresses) - .map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, e.to_string()))?; + .map_err(|e| std::io::Error::other(e.to_string()))?; let mut decoded_accounts: Vec> = Vec::new(); for i in 0..addresses.len() { let address = addresses[i]; - let account = accounts[i].as_ref().ok_or(std::io::Error::new( - std::io::ErrorKind::Other, - format!("Account not found: {}", address), - ))?; + let account = accounts[i].as_ref().ok_or(std::io::Error::other(format!( + "Account not found: {address}" + )))?; let data = TokenOwnerRecordV1::from_bytes(&account.data)?; decoded_accounts.push(crate::shared::DecodedAccount { address, @@ -135,7 +121,7 @@ pub fn fetch_all_token_owner_record_v1( #[cfg(feature = "fetch")] pub fn fetch_maybe_token_owner_record_v1( rpc: &solana_client::rpc_client::RpcClient, - address: &solana_pubkey::Pubkey, + address: &solana_address::Address, ) -> Result, std::io::Error> { let accounts = fetch_all_maybe_token_owner_record_v1(rpc, &[*address])?; Ok(accounts[0].clone()) @@ -144,11 +130,11 @@ pub fn fetch_maybe_token_owner_record_v1( #[cfg(feature = "fetch")] pub fn fetch_all_maybe_token_owner_record_v1( rpc: &solana_client::rpc_client::RpcClient, - addresses: &[solana_pubkey::Pubkey], + addresses: &[solana_address::Address], ) -> Result>, std::io::Error> { let accounts = rpc .get_multiple_accounts(addresses) - .map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, e.to_string()))?; + .map_err(|e| std::io::Error::other(e.to_string()))?; let mut decoded_accounts: Vec> = Vec::new(); for i in 0..addresses.len() { let address = addresses[i]; @@ -180,8 +166,8 @@ impl anchor_lang::AccountSerialize for TokenOwnerRecordV1 {} #[cfg(feature = "anchor")] impl anchor_lang::Owner for TokenOwnerRecordV1 { - fn owner() -> Pubkey { - crate::SPL_GOVERNANCE_ID + fn owner() -> anchor_lang::solana_program::pubkey::Pubkey { + anchor_lang::solana_program::pubkey::Pubkey::from(crate::SPL_GOVERNANCE_ID.to_bytes()) } } diff --git a/e2e/governance/src/generated/accounts/token_owner_record_v2.rs b/e2e/governance/src/generated/accounts/token_owner_record_v2.rs index 319bc3c..7af6964 100644 --- a/e2e/governance/src/generated/accounts/token_owner_record_v2.rs +++ b/e2e/governance/src/generated/accounts/token_owner_record_v2.rs @@ -8,34 +8,20 @@ use crate::generated::types::GovernanceAccountType; use borsh::BorshDeserialize; use borsh::BorshSerialize; -use solana_pubkey::Pubkey; +use solana_address::Address; #[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] -#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct TokenOwnerRecordV2 { pub account_type: GovernanceAccountType, - #[cfg_attr( - feature = "serde", - serde(with = "serde_with::As::") - )] - pub realm: Pubkey, - #[cfg_attr( - feature = "serde", - serde(with = "serde_with::As::") - )] - pub governing_token_mint: Pubkey, - #[cfg_attr( - feature = "serde", - serde(with = "serde_with::As::") - )] - pub governing_token_owner: Pubkey, + pub realm: Address, + pub governing_token_mint: Address, + pub governing_token_owner: Address, pub governing_token_deposit_amount: u64, pub unrelinquished_votes_count: u64, pub outstanding_proposal_count: u8, pub version: u8, pub reserved: [u8; 6], - pub governance_delegate: Option, - #[cfg_attr(feature = "serde", serde(with = "serde_big_array::BigArray"))] + pub governance_delegate: Option
, pub reserved_v2: [u8; 128], } @@ -45,18 +31,18 @@ impl TokenOwnerRecordV2 { /// Values are positional and appear in the following order: /// /// 0. `TokenOwnerRecordV2::PREFIX` - /// 1. realm (`Pubkey`) - /// 2. governing_token_mint (`Pubkey`) - /// 3. governing_token_owner (`Pubkey`) + /// 1. realm (`Address`) + /// 2. governing_token_mint (`Address`) + /// 3. governing_token_owner (`Address`) pub const PREFIX: &'static [u8] = "governance".as_bytes(); pub fn create_pda( - realm: Pubkey, - governing_token_mint: Pubkey, - governing_token_owner: Pubkey, + realm: Address, + governing_token_mint: Address, + governing_token_owner: Address, bump: u8, - ) -> Result { - solana_pubkey::Pubkey::create_program_address( + ) -> Result { + solana_address::Address::create_program_address( &[ "governance".as_bytes(), realm.as_ref(), @@ -69,11 +55,11 @@ impl TokenOwnerRecordV2 { } pub fn find_pda( - realm: &Pubkey, - governing_token_mint: &Pubkey, - governing_token_owner: &Pubkey, - ) -> (solana_pubkey::Pubkey, u8) { - solana_pubkey::Pubkey::find_program_address( + realm: &Address, + governing_token_mint: &Address, + governing_token_owner: &Address, + ) -> (solana_address::Address, u8) { + solana_address::Address::find_program_address( &[ "governance".as_bytes(), realm.as_ref(), @@ -103,7 +89,7 @@ impl<'a> TryFrom<&solana_account_info::AccountInfo<'a>> for TokenOwnerRecordV2 { #[cfg(feature = "fetch")] pub fn fetch_token_owner_record_v2( rpc: &solana_client::rpc_client::RpcClient, - address: &solana_pubkey::Pubkey, + address: &solana_address::Address, ) -> Result, std::io::Error> { let accounts = fetch_all_token_owner_record_v2(rpc, &[*address])?; Ok(accounts[0].clone()) @@ -112,18 +98,17 @@ pub fn fetch_token_owner_record_v2( #[cfg(feature = "fetch")] pub fn fetch_all_token_owner_record_v2( rpc: &solana_client::rpc_client::RpcClient, - addresses: &[solana_pubkey::Pubkey], + addresses: &[solana_address::Address], ) -> Result>, std::io::Error> { let accounts = rpc .get_multiple_accounts(addresses) - .map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, e.to_string()))?; + .map_err(|e| std::io::Error::other(e.to_string()))?; let mut decoded_accounts: Vec> = Vec::new(); for i in 0..addresses.len() { let address = addresses[i]; - let account = accounts[i].as_ref().ok_or(std::io::Error::new( - std::io::ErrorKind::Other, - format!("Account not found: {}", address), - ))?; + let account = accounts[i].as_ref().ok_or(std::io::Error::other(format!( + "Account not found: {address}" + )))?; let data = TokenOwnerRecordV2::from_bytes(&account.data)?; decoded_accounts.push(crate::shared::DecodedAccount { address, @@ -137,7 +122,7 @@ pub fn fetch_all_token_owner_record_v2( #[cfg(feature = "fetch")] pub fn fetch_maybe_token_owner_record_v2( rpc: &solana_client::rpc_client::RpcClient, - address: &solana_pubkey::Pubkey, + address: &solana_address::Address, ) -> Result, std::io::Error> { let accounts = fetch_all_maybe_token_owner_record_v2(rpc, &[*address])?; Ok(accounts[0].clone()) @@ -146,11 +131,11 @@ pub fn fetch_maybe_token_owner_record_v2( #[cfg(feature = "fetch")] pub fn fetch_all_maybe_token_owner_record_v2( rpc: &solana_client::rpc_client::RpcClient, - addresses: &[solana_pubkey::Pubkey], + addresses: &[solana_address::Address], ) -> Result>, std::io::Error> { let accounts = rpc .get_multiple_accounts(addresses) - .map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, e.to_string()))?; + .map_err(|e| std::io::Error::other(e.to_string()))?; let mut decoded_accounts: Vec> = Vec::new(); for i in 0..addresses.len() { let address = addresses[i]; @@ -182,8 +167,8 @@ impl anchor_lang::AccountSerialize for TokenOwnerRecordV2 {} #[cfg(feature = "anchor")] impl anchor_lang::Owner for TokenOwnerRecordV2 { - fn owner() -> Pubkey { - crate::SPL_GOVERNANCE_ID + fn owner() -> anchor_lang::solana_program::pubkey::Pubkey { + anchor_lang::solana_program::pubkey::Pubkey::from(crate::SPL_GOVERNANCE_ID.to_bytes()) } } diff --git a/e2e/governance/src/generated/accounts/vote_record_v1.rs b/e2e/governance/src/generated/accounts/vote_record_v1.rs index 477d07b..58f796e 100644 --- a/e2e/governance/src/generated/accounts/vote_record_v1.rs +++ b/e2e/governance/src/generated/accounts/vote_record_v1.rs @@ -9,22 +9,13 @@ use crate::generated::types::GovernanceAccountType; use crate::generated::types::VoteWeightV1; use borsh::BorshDeserialize; use borsh::BorshSerialize; -use solana_pubkey::Pubkey; +use solana_address::Address; #[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] -#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct VoteRecordV1 { pub account_type: GovernanceAccountType, - #[cfg_attr( - feature = "serde", - serde(with = "serde_with::As::") - )] - pub proposal: Pubkey, - #[cfg_attr( - feature = "serde", - serde(with = "serde_with::As::") - )] - pub governing_token_owner: Pubkey, + pub proposal: Address, + pub governing_token_owner: Address, pub is_relinquished: bool, pub vote_weight: VoteWeightV1, } @@ -35,16 +26,16 @@ impl VoteRecordV1 { /// Values are positional and appear in the following order: /// /// 0. `VoteRecordV1::PREFIX` - /// 1. proposal (`Pubkey`) - /// 2. token_owner_record (`Pubkey`) + /// 1. proposal (`Address`) + /// 2. token_owner_record (`Address`) pub const PREFIX: &'static [u8] = "governance".as_bytes(); pub fn create_pda( - proposal: Pubkey, - token_owner_record: Pubkey, + proposal: Address, + token_owner_record: Address, bump: u8, - ) -> Result { - solana_pubkey::Pubkey::create_program_address( + ) -> Result { + solana_address::Address::create_program_address( &[ "governance".as_bytes(), proposal.as_ref(), @@ -55,8 +46,11 @@ impl VoteRecordV1 { ) } - pub fn find_pda(proposal: &Pubkey, token_owner_record: &Pubkey) -> (solana_pubkey::Pubkey, u8) { - solana_pubkey::Pubkey::find_program_address( + pub fn find_pda( + proposal: &Address, + token_owner_record: &Address, + ) -> (solana_address::Address, u8) { + solana_address::Address::find_program_address( &[ "governance".as_bytes(), proposal.as_ref(), @@ -85,7 +79,7 @@ impl<'a> TryFrom<&solana_account_info::AccountInfo<'a>> for VoteRecordV1 { #[cfg(feature = "fetch")] pub fn fetch_vote_record_v1( rpc: &solana_client::rpc_client::RpcClient, - address: &solana_pubkey::Pubkey, + address: &solana_address::Address, ) -> Result, std::io::Error> { let accounts = fetch_all_vote_record_v1(rpc, &[*address])?; Ok(accounts[0].clone()) @@ -94,18 +88,17 @@ pub fn fetch_vote_record_v1( #[cfg(feature = "fetch")] pub fn fetch_all_vote_record_v1( rpc: &solana_client::rpc_client::RpcClient, - addresses: &[solana_pubkey::Pubkey], + addresses: &[solana_address::Address], ) -> Result>, std::io::Error> { let accounts = rpc .get_multiple_accounts(addresses) - .map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, e.to_string()))?; + .map_err(|e| std::io::Error::other(e.to_string()))?; let mut decoded_accounts: Vec> = Vec::new(); for i in 0..addresses.len() { let address = addresses[i]; - let account = accounts[i].as_ref().ok_or(std::io::Error::new( - std::io::ErrorKind::Other, - format!("Account not found: {}", address), - ))?; + let account = accounts[i].as_ref().ok_or(std::io::Error::other(format!( + "Account not found: {address}" + )))?; let data = VoteRecordV1::from_bytes(&account.data)?; decoded_accounts.push(crate::shared::DecodedAccount { address, @@ -119,7 +112,7 @@ pub fn fetch_all_vote_record_v1( #[cfg(feature = "fetch")] pub fn fetch_maybe_vote_record_v1( rpc: &solana_client::rpc_client::RpcClient, - address: &solana_pubkey::Pubkey, + address: &solana_address::Address, ) -> Result, std::io::Error> { let accounts = fetch_all_maybe_vote_record_v1(rpc, &[*address])?; Ok(accounts[0].clone()) @@ -128,11 +121,11 @@ pub fn fetch_maybe_vote_record_v1( #[cfg(feature = "fetch")] pub fn fetch_all_maybe_vote_record_v1( rpc: &solana_client::rpc_client::RpcClient, - addresses: &[solana_pubkey::Pubkey], + addresses: &[solana_address::Address], ) -> Result>, std::io::Error> { let accounts = rpc .get_multiple_accounts(addresses) - .map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, e.to_string()))?; + .map_err(|e| std::io::Error::other(e.to_string()))?; let mut decoded_accounts: Vec> = Vec::new(); for i in 0..addresses.len() { let address = addresses[i]; @@ -164,8 +157,8 @@ impl anchor_lang::AccountSerialize for VoteRecordV1 {} #[cfg(feature = "anchor")] impl anchor_lang::Owner for VoteRecordV1 { - fn owner() -> Pubkey { - crate::SPL_GOVERNANCE_ID + fn owner() -> anchor_lang::solana_program::pubkey::Pubkey { + anchor_lang::solana_program::pubkey::Pubkey::from(crate::SPL_GOVERNANCE_ID.to_bytes()) } } diff --git a/e2e/governance/src/generated/accounts/vote_record_v2.rs b/e2e/governance/src/generated/accounts/vote_record_v2.rs index de784cb..329a09d 100644 --- a/e2e/governance/src/generated/accounts/vote_record_v2.rs +++ b/e2e/governance/src/generated/accounts/vote_record_v2.rs @@ -9,22 +9,13 @@ use crate::generated::types::GovernanceAccountType; use crate::generated::types::Vote; use borsh::BorshDeserialize; use borsh::BorshSerialize; -use solana_pubkey::Pubkey; +use solana_address::Address; #[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] -#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct VoteRecordV2 { pub account_type: GovernanceAccountType, - #[cfg_attr( - feature = "serde", - serde(with = "serde_with::As::") - )] - pub proposal: Pubkey, - #[cfg_attr( - feature = "serde", - serde(with = "serde_with::As::") - )] - pub governing_token_owner: Pubkey, + pub proposal: Address, + pub governing_token_owner: Address, pub is_relinquished: bool, pub voter_weight: u64, pub vote: Vote, @@ -37,16 +28,16 @@ impl VoteRecordV2 { /// Values are positional and appear in the following order: /// /// 0. `VoteRecordV2::PREFIX` - /// 1. proposal (`Pubkey`) - /// 2. token_owner_record (`Pubkey`) + /// 1. proposal (`Address`) + /// 2. token_owner_record (`Address`) pub const PREFIX: &'static [u8] = "governance".as_bytes(); pub fn create_pda( - proposal: Pubkey, - token_owner_record: Pubkey, + proposal: Address, + token_owner_record: Address, bump: u8, - ) -> Result { - solana_pubkey::Pubkey::create_program_address( + ) -> Result { + solana_address::Address::create_program_address( &[ "governance".as_bytes(), proposal.as_ref(), @@ -57,8 +48,11 @@ impl VoteRecordV2 { ) } - pub fn find_pda(proposal: &Pubkey, token_owner_record: &Pubkey) -> (solana_pubkey::Pubkey, u8) { - solana_pubkey::Pubkey::find_program_address( + pub fn find_pda( + proposal: &Address, + token_owner_record: &Address, + ) -> (solana_address::Address, u8) { + solana_address::Address::find_program_address( &[ "governance".as_bytes(), proposal.as_ref(), @@ -87,7 +81,7 @@ impl<'a> TryFrom<&solana_account_info::AccountInfo<'a>> for VoteRecordV2 { #[cfg(feature = "fetch")] pub fn fetch_vote_record_v2( rpc: &solana_client::rpc_client::RpcClient, - address: &solana_pubkey::Pubkey, + address: &solana_address::Address, ) -> Result, std::io::Error> { let accounts = fetch_all_vote_record_v2(rpc, &[*address])?; Ok(accounts[0].clone()) @@ -96,18 +90,17 @@ pub fn fetch_vote_record_v2( #[cfg(feature = "fetch")] pub fn fetch_all_vote_record_v2( rpc: &solana_client::rpc_client::RpcClient, - addresses: &[solana_pubkey::Pubkey], + addresses: &[solana_address::Address], ) -> Result>, std::io::Error> { let accounts = rpc .get_multiple_accounts(addresses) - .map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, e.to_string()))?; + .map_err(|e| std::io::Error::other(e.to_string()))?; let mut decoded_accounts: Vec> = Vec::new(); for i in 0..addresses.len() { let address = addresses[i]; - let account = accounts[i].as_ref().ok_or(std::io::Error::new( - std::io::ErrorKind::Other, - format!("Account not found: {}", address), - ))?; + let account = accounts[i].as_ref().ok_or(std::io::Error::other(format!( + "Account not found: {address}" + )))?; let data = VoteRecordV2::from_bytes(&account.data)?; decoded_accounts.push(crate::shared::DecodedAccount { address, @@ -121,7 +114,7 @@ pub fn fetch_all_vote_record_v2( #[cfg(feature = "fetch")] pub fn fetch_maybe_vote_record_v2( rpc: &solana_client::rpc_client::RpcClient, - address: &solana_pubkey::Pubkey, + address: &solana_address::Address, ) -> Result, std::io::Error> { let accounts = fetch_all_maybe_vote_record_v2(rpc, &[*address])?; Ok(accounts[0].clone()) @@ -130,11 +123,11 @@ pub fn fetch_maybe_vote_record_v2( #[cfg(feature = "fetch")] pub fn fetch_all_maybe_vote_record_v2( rpc: &solana_client::rpc_client::RpcClient, - addresses: &[solana_pubkey::Pubkey], + addresses: &[solana_address::Address], ) -> Result>, std::io::Error> { let accounts = rpc .get_multiple_accounts(addresses) - .map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, e.to_string()))?; + .map_err(|e| std::io::Error::other(e.to_string()))?; let mut decoded_accounts: Vec> = Vec::new(); for i in 0..addresses.len() { let address = addresses[i]; @@ -166,8 +159,8 @@ impl anchor_lang::AccountSerialize for VoteRecordV2 {} #[cfg(feature = "anchor")] impl anchor_lang::Owner for VoteRecordV2 { - fn owner() -> Pubkey { - crate::SPL_GOVERNANCE_ID + fn owner() -> anchor_lang::solana_program::pubkey::Pubkey { + anchor_lang::solana_program::pubkey::Pubkey::from(crate::SPL_GOVERNANCE_ID.to_bytes()) } } diff --git a/e2e/governance/src/generated/instructions/add_required_signatory.rs b/e2e/governance/src/generated/instructions/add_required_signatory.rs index 0e78413..90c1920 100644 --- a/e2e/governance/src/generated/instructions/add_required_signatory.rs +++ b/e2e/governance/src/generated/instructions/add_required_signatory.rs @@ -7,7 +7,7 @@ use borsh::BorshDeserialize; use borsh::BorshSerialize; -use solana_pubkey::Pubkey; +use solana_address::Address; pub const ADD_REQUIRED_SIGNATORY_DISCRIMINATOR: u8 = 29; @@ -15,13 +15,13 @@ pub const ADD_REQUIRED_SIGNATORY_DISCRIMINATOR: u8 = 29; #[derive(Debug)] pub struct AddRequiredSignatory { /// The Governance account the config is for - pub governance_account: solana_pubkey::Pubkey, + pub governance_account: solana_address::Address, - pub required_signatory_account: solana_pubkey::Pubkey, + pub required_signatory_account: solana_address::Address, - pub payer: solana_pubkey::Pubkey, + pub payer: solana_address::Address, - pub system_program: solana_pubkey::Pubkey, + pub system_program: solana_address::Address, } impl AddRequiredSignatory { @@ -70,7 +70,6 @@ impl AddRequiredSignatory { } #[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] -#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct AddRequiredSignatoryInstructionData { discriminator: u8, } @@ -92,9 +91,8 @@ impl Default for AddRequiredSignatoryInstructionData { } #[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] -#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct AddRequiredSignatoryInstructionArgs { - pub signatory: Pubkey, + pub signatory: Address, } impl AddRequiredSignatoryInstructionArgs { @@ -113,11 +111,11 @@ impl AddRequiredSignatoryInstructionArgs { /// 3. `[optional]` system_program (default to `11111111111111111111111111111111`) #[derive(Clone, Debug, Default)] pub struct AddRequiredSignatoryBuilder { - governance_account: Option, - required_signatory_account: Option, - payer: Option, - system_program: Option, - signatory: Option, + governance_account: Option, + required_signatory_account: Option, + payer: Option, + system_program: Option, + signatory: Option
, __remaining_accounts: Vec, } @@ -127,31 +125,31 @@ impl AddRequiredSignatoryBuilder { } /// The Governance account the config is for #[inline(always)] - pub fn governance_account(&mut self, governance_account: solana_pubkey::Pubkey) -> &mut Self { + pub fn governance_account(&mut self, governance_account: solana_address::Address) -> &mut Self { self.governance_account = Some(governance_account); self } #[inline(always)] pub fn required_signatory_account( &mut self, - required_signatory_account: solana_pubkey::Pubkey, + required_signatory_account: solana_address::Address, ) -> &mut Self { self.required_signatory_account = Some(required_signatory_account); self } #[inline(always)] - pub fn payer(&mut self, payer: solana_pubkey::Pubkey) -> &mut Self { + pub fn payer(&mut self, payer: solana_address::Address) -> &mut Self { self.payer = Some(payer); self } /// `[optional account, default to '11111111111111111111111111111111']` #[inline(always)] - pub fn system_program(&mut self, system_program: solana_pubkey::Pubkey) -> &mut Self { + pub fn system_program(&mut self, system_program: solana_address::Address) -> &mut Self { self.system_program = Some(system_program); self } #[inline(always)] - pub fn signatory(&mut self, signatory: Pubkey) -> &mut Self { + pub fn signatory(&mut self, signatory: Address) -> &mut Self { self.signatory = Some(signatory); self } @@ -182,7 +180,7 @@ impl AddRequiredSignatoryBuilder { payer: self.payer.expect("payer is not set"), system_program: self .system_program - .unwrap_or(solana_pubkey::pubkey!("11111111111111111111111111111111")), + .unwrap_or(solana_address::address!("11111111111111111111111111111111")), }; let args = AddRequiredSignatoryInstructionArgs { signatory: self.signatory.clone().expect("signatory is not set"), @@ -368,7 +366,7 @@ impl<'a, 'b> AddRequiredSignatoryCpiBuilder<'a, 'b> { self } #[inline(always)] - pub fn signatory(&mut self, signatory: Pubkey) -> &mut Self { + pub fn signatory(&mut self, signatory: Address) -> &mut Self { self.instruction.signatory = Some(signatory); self } @@ -448,7 +446,7 @@ struct AddRequiredSignatoryCpiBuilderInstruction<'a, 'b> { required_signatory_account: Option<&'b solana_account_info::AccountInfo<'a>>, payer: Option<&'b solana_account_info::AccountInfo<'a>>, system_program: Option<&'b solana_account_info::AccountInfo<'a>>, - signatory: Option, + signatory: Option
, /// Additional instruction accounts `(AccountInfo, is_writable, is_signer)`. __remaining_accounts: Vec<(&'b solana_account_info::AccountInfo<'a>, bool, bool)>, } diff --git a/e2e/governance/src/generated/instructions/add_signatory.rs b/e2e/governance/src/generated/instructions/add_signatory.rs index b6616ef..d55d00a 100644 --- a/e2e/governance/src/generated/instructions/add_signatory.rs +++ b/e2e/governance/src/generated/instructions/add_signatory.rs @@ -7,7 +7,7 @@ use borsh::BorshDeserialize; use borsh::BorshSerialize; -use solana_pubkey::Pubkey; +use solana_address::Address; pub const ADD_SIGNATORY_DISCRIMINATOR: u8 = 7; @@ -15,17 +15,17 @@ pub const ADD_SIGNATORY_DISCRIMINATOR: u8 = 7; #[derive(Debug)] pub struct AddSignatory { /// Proposal Account associated with the governance - pub proposal_account: solana_pubkey::Pubkey, + pub proposal_account: solana_address::Address, /// TokenOwnerRecord account of the Proposal owner - pub token_owner_record: solana_pubkey::Pubkey, + pub token_owner_record: solana_address::Address, /// Governance Authority (Token Owner or Governance Delegate) - pub governance_authority: solana_pubkey::Pubkey, + pub governance_authority: solana_address::Address, /// Signatory Record Account - pub signatory_record_account: solana_pubkey::Pubkey, + pub signatory_record_account: solana_address::Address, - pub payer: solana_pubkey::Pubkey, + pub payer: solana_address::Address, - pub system_program: solana_pubkey::Pubkey, + pub system_program: solana_address::Address, } impl AddSignatory { @@ -80,7 +80,6 @@ impl AddSignatory { } #[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] -#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct AddSignatoryInstructionData { discriminator: u8, } @@ -102,9 +101,8 @@ impl Default for AddSignatoryInstructionData { } #[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] -#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct AddSignatoryInstructionArgs { - pub signatory: Pubkey, + pub signatory: Address, } impl AddSignatoryInstructionArgs { @@ -125,13 +123,13 @@ impl AddSignatoryInstructionArgs { /// 5. `[optional]` system_program (default to `11111111111111111111111111111111`) #[derive(Clone, Debug, Default)] pub struct AddSignatoryBuilder { - proposal_account: Option, - token_owner_record: Option, - governance_authority: Option, - signatory_record_account: Option, - payer: Option, - system_program: Option, - signatory: Option, + proposal_account: Option, + token_owner_record: Option, + governance_authority: Option, + signatory_record_account: Option, + payer: Option, + system_program: Option, + signatory: Option
, __remaining_accounts: Vec, } @@ -141,13 +139,13 @@ impl AddSignatoryBuilder { } /// Proposal Account associated with the governance #[inline(always)] - pub fn proposal_account(&mut self, proposal_account: solana_pubkey::Pubkey) -> &mut Self { + pub fn proposal_account(&mut self, proposal_account: solana_address::Address) -> &mut Self { self.proposal_account = Some(proposal_account); self } /// TokenOwnerRecord account of the Proposal owner #[inline(always)] - pub fn token_owner_record(&mut self, token_owner_record: solana_pubkey::Pubkey) -> &mut Self { + pub fn token_owner_record(&mut self, token_owner_record: solana_address::Address) -> &mut Self { self.token_owner_record = Some(token_owner_record); self } @@ -155,7 +153,7 @@ impl AddSignatoryBuilder { #[inline(always)] pub fn governance_authority( &mut self, - governance_authority: solana_pubkey::Pubkey, + governance_authority: solana_address::Address, ) -> &mut Self { self.governance_authority = Some(governance_authority); self @@ -164,24 +162,24 @@ impl AddSignatoryBuilder { #[inline(always)] pub fn signatory_record_account( &mut self, - signatory_record_account: solana_pubkey::Pubkey, + signatory_record_account: solana_address::Address, ) -> &mut Self { self.signatory_record_account = Some(signatory_record_account); self } #[inline(always)] - pub fn payer(&mut self, payer: solana_pubkey::Pubkey) -> &mut Self { + pub fn payer(&mut self, payer: solana_address::Address) -> &mut Self { self.payer = Some(payer); self } /// `[optional account, default to '11111111111111111111111111111111']` #[inline(always)] - pub fn system_program(&mut self, system_program: solana_pubkey::Pubkey) -> &mut Self { + pub fn system_program(&mut self, system_program: solana_address::Address) -> &mut Self { self.system_program = Some(system_program); self } #[inline(always)] - pub fn signatory(&mut self, signatory: Pubkey) -> &mut Self { + pub fn signatory(&mut self, signatory: Address) -> &mut Self { self.signatory = Some(signatory); self } @@ -216,7 +214,7 @@ impl AddSignatoryBuilder { payer: self.payer.expect("payer is not set"), system_program: self .system_program - .unwrap_or(solana_pubkey::pubkey!("11111111111111111111111111111111")), + .unwrap_or(solana_address::address!("11111111111111111111111111111111")), }; let args = AddSignatoryInstructionArgs { signatory: self.signatory.clone().expect("signatory is not set"), @@ -443,7 +441,7 @@ impl<'a, 'b> AddSignatoryCpiBuilder<'a, 'b> { self } #[inline(always)] - pub fn signatory(&mut self, signatory: Pubkey) -> &mut Self { + pub fn signatory(&mut self, signatory: Address) -> &mut Self { self.instruction.signatory = Some(signatory); self } @@ -535,7 +533,7 @@ struct AddSignatoryCpiBuilderInstruction<'a, 'b> { signatory_record_account: Option<&'b solana_account_info::AccountInfo<'a>>, payer: Option<&'b solana_account_info::AccountInfo<'a>>, system_program: Option<&'b solana_account_info::AccountInfo<'a>>, - signatory: Option, + signatory: Option
, /// Additional instruction accounts `(AccountInfo, is_writable, is_signer)`. __remaining_accounts: Vec<(&'b solana_account_info::AccountInfo<'a>, bool, bool)>, } diff --git a/e2e/governance/src/generated/instructions/cancel_proposal.rs b/e2e/governance/src/generated/instructions/cancel_proposal.rs index ad46ea8..7d8976d 100644 --- a/e2e/governance/src/generated/instructions/cancel_proposal.rs +++ b/e2e/governance/src/generated/instructions/cancel_proposal.rs @@ -13,15 +13,15 @@ pub const CANCEL_PROPOSAL_DISCRIMINATOR: u8 = 11; /// Accounts. #[derive(Debug)] pub struct CancelProposal { - pub realm_account: solana_pubkey::Pubkey, + pub realm_account: solana_address::Address, - pub governance_account: solana_pubkey::Pubkey, + pub governance_account: solana_address::Address, - pub proposal_account: solana_pubkey::Pubkey, + pub proposal_account: solana_address::Address, /// TokenOwnerRecord account of the Proposal owner - pub token_owner_record: solana_pubkey::Pubkey, + pub token_owner_record: solana_address::Address, /// Governance authority (Token Owner or Governance Delegate) - pub governance_authority: solana_pubkey::Pubkey, + pub governance_authority: solana_address::Address, } impl CancelProposal { @@ -67,7 +67,6 @@ impl CancelProposal { } #[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] -#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct CancelProposalInstructionData { discriminator: u8, } @@ -99,11 +98,11 @@ impl Default for CancelProposalInstructionData { /// 4. `[signer]` governance_authority #[derive(Clone, Debug, Default)] pub struct CancelProposalBuilder { - realm_account: Option, - governance_account: Option, - proposal_account: Option, - token_owner_record: Option, - governance_authority: Option, + realm_account: Option, + governance_account: Option, + proposal_account: Option, + token_owner_record: Option, + governance_authority: Option, __remaining_accounts: Vec, } @@ -112,23 +111,23 @@ impl CancelProposalBuilder { Self::default() } #[inline(always)] - pub fn realm_account(&mut self, realm_account: solana_pubkey::Pubkey) -> &mut Self { + pub fn realm_account(&mut self, realm_account: solana_address::Address) -> &mut Self { self.realm_account = Some(realm_account); self } #[inline(always)] - pub fn governance_account(&mut self, governance_account: solana_pubkey::Pubkey) -> &mut Self { + pub fn governance_account(&mut self, governance_account: solana_address::Address) -> &mut Self { self.governance_account = Some(governance_account); self } #[inline(always)] - pub fn proposal_account(&mut self, proposal_account: solana_pubkey::Pubkey) -> &mut Self { + pub fn proposal_account(&mut self, proposal_account: solana_address::Address) -> &mut Self { self.proposal_account = Some(proposal_account); self } /// TokenOwnerRecord account of the Proposal owner #[inline(always)] - pub fn token_owner_record(&mut self, token_owner_record: solana_pubkey::Pubkey) -> &mut Self { + pub fn token_owner_record(&mut self, token_owner_record: solana_address::Address) -> &mut Self { self.token_owner_record = Some(token_owner_record); self } @@ -136,7 +135,7 @@ impl CancelProposalBuilder { #[inline(always)] pub fn governance_authority( &mut self, - governance_authority: solana_pubkey::Pubkey, + governance_authority: solana_address::Address, ) -> &mut Self { self.governance_authority = Some(governance_authority); self diff --git a/e2e/governance/src/generated/instructions/cast_vote.rs b/e2e/governance/src/generated/instructions/cast_vote.rs index 79388f7..8fd76a9 100644 --- a/e2e/governance/src/generated/instructions/cast_vote.rs +++ b/e2e/governance/src/generated/instructions/cast_vote.rs @@ -14,35 +14,35 @@ pub const CAST_VOTE_DISCRIMINATOR: u8 = 13; /// Accounts. #[derive(Debug)] pub struct CastVote { - pub realm_account: solana_pubkey::Pubkey, + pub realm_account: solana_address::Address, - pub governance_account: solana_pubkey::Pubkey, + pub governance_account: solana_address::Address, - pub proposal_account: solana_pubkey::Pubkey, + pub proposal_account: solana_address::Address, /// TokenOwnerRecord of the Proposal owner - pub proposal_token_owner_record: solana_pubkey::Pubkey, + pub proposal_token_owner_record: solana_address::Address, /// TokenOwnerRecord of the voter. PDA seeds: ['governance',realm, vote_governing_token_mint, governing_token_owner] - pub voter_token_owner_record: solana_pubkey::Pubkey, + pub voter_token_owner_record: solana_address::Address, /// Governance Authority (Token Owner or Governance Delegate) - pub governance_authority: solana_pubkey::Pubkey, + pub governance_authority: solana_address::Address, /// Proposal VoteRecord account. PDA seeds: ['governance',proposal,token_owner_record] - pub proposal_vote_record: solana_pubkey::Pubkey, + pub proposal_vote_record: solana_address::Address, /// The Governing Token Mint which is used to cast the vote (vote_governing_token_mint). /// The voting token mint is the governing_token_mint of the Proposal for Approve, Deny and Abstain votes. /// For Veto vote the voting token mint is the mint of the opposite voting population. /// Council mint to veto Community proposals and Community mint to veto Council proposals /// Note: In the current version only Council veto is supported - pub governing_token_mint: solana_pubkey::Pubkey, + pub governing_token_mint: solana_address::Address, - pub payer: solana_pubkey::Pubkey, + pub payer: solana_address::Address, - pub system_program: solana_pubkey::Pubkey, + pub system_program: solana_address::Address, /// RealmConfig account. PDA seeds: ['realm-config', realm] - pub realm_config_account: solana_pubkey::Pubkey, + pub realm_config_account: solana_address::Address, /// Optional Voter Weight Record - pub voter_weight_record: Option, + pub voter_weight_record: Option, /// Optional Max Voter Weight Record - pub max_voter_weight_record: Option, + pub max_voter_weight_record: Option, } impl CastVote { @@ -136,7 +136,6 @@ impl CastVote { } #[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] -#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct CastVoteInstructionData { discriminator: u8, } @@ -158,7 +157,6 @@ impl Default for CastVoteInstructionData { } #[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] -#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct CastVoteInstructionArgs { pub vote: Vote, } @@ -188,19 +186,19 @@ impl CastVoteInstructionArgs { /// 12. `[optional]` max_voter_weight_record #[derive(Clone, Debug, Default)] pub struct CastVoteBuilder { - realm_account: Option, - governance_account: Option, - proposal_account: Option, - proposal_token_owner_record: Option, - voter_token_owner_record: Option, - governance_authority: Option, - proposal_vote_record: Option, - governing_token_mint: Option, - payer: Option, - system_program: Option, - realm_config_account: Option, - voter_weight_record: Option, - max_voter_weight_record: Option, + realm_account: Option, + governance_account: Option, + proposal_account: Option, + proposal_token_owner_record: Option, + voter_token_owner_record: Option, + governance_authority: Option, + proposal_vote_record: Option, + governing_token_mint: Option, + payer: Option, + system_program: Option, + realm_config_account: Option, + voter_weight_record: Option, + max_voter_weight_record: Option, vote: Option, __remaining_accounts: Vec, } @@ -210,17 +208,17 @@ impl CastVoteBuilder { Self::default() } #[inline(always)] - pub fn realm_account(&mut self, realm_account: solana_pubkey::Pubkey) -> &mut Self { + pub fn realm_account(&mut self, realm_account: solana_address::Address) -> &mut Self { self.realm_account = Some(realm_account); self } #[inline(always)] - pub fn governance_account(&mut self, governance_account: solana_pubkey::Pubkey) -> &mut Self { + pub fn governance_account(&mut self, governance_account: solana_address::Address) -> &mut Self { self.governance_account = Some(governance_account); self } #[inline(always)] - pub fn proposal_account(&mut self, proposal_account: solana_pubkey::Pubkey) -> &mut Self { + pub fn proposal_account(&mut self, proposal_account: solana_address::Address) -> &mut Self { self.proposal_account = Some(proposal_account); self } @@ -228,7 +226,7 @@ impl CastVoteBuilder { #[inline(always)] pub fn proposal_token_owner_record( &mut self, - proposal_token_owner_record: solana_pubkey::Pubkey, + proposal_token_owner_record: solana_address::Address, ) -> &mut Self { self.proposal_token_owner_record = Some(proposal_token_owner_record); self @@ -237,7 +235,7 @@ impl CastVoteBuilder { #[inline(always)] pub fn voter_token_owner_record( &mut self, - voter_token_owner_record: solana_pubkey::Pubkey, + voter_token_owner_record: solana_address::Address, ) -> &mut Self { self.voter_token_owner_record = Some(voter_token_owner_record); self @@ -246,7 +244,7 @@ impl CastVoteBuilder { #[inline(always)] pub fn governance_authority( &mut self, - governance_authority: solana_pubkey::Pubkey, + governance_authority: solana_address::Address, ) -> &mut Self { self.governance_authority = Some(governance_authority); self @@ -255,7 +253,7 @@ impl CastVoteBuilder { #[inline(always)] pub fn proposal_vote_record( &mut self, - proposal_vote_record: solana_pubkey::Pubkey, + proposal_vote_record: solana_address::Address, ) -> &mut Self { self.proposal_vote_record = Some(proposal_vote_record); self @@ -268,19 +266,19 @@ impl CastVoteBuilder { #[inline(always)] pub fn governing_token_mint( &mut self, - governing_token_mint: solana_pubkey::Pubkey, + governing_token_mint: solana_address::Address, ) -> &mut Self { self.governing_token_mint = Some(governing_token_mint); self } #[inline(always)] - pub fn payer(&mut self, payer: solana_pubkey::Pubkey) -> &mut Self { + pub fn payer(&mut self, payer: solana_address::Address) -> &mut Self { self.payer = Some(payer); self } /// `[optional account, default to '11111111111111111111111111111111']` #[inline(always)] - pub fn system_program(&mut self, system_program: solana_pubkey::Pubkey) -> &mut Self { + pub fn system_program(&mut self, system_program: solana_address::Address) -> &mut Self { self.system_program = Some(system_program); self } @@ -288,7 +286,7 @@ impl CastVoteBuilder { #[inline(always)] pub fn realm_config_account( &mut self, - realm_config_account: solana_pubkey::Pubkey, + realm_config_account: solana_address::Address, ) -> &mut Self { self.realm_config_account = Some(realm_config_account); self @@ -298,7 +296,7 @@ impl CastVoteBuilder { #[inline(always)] pub fn voter_weight_record( &mut self, - voter_weight_record: Option, + voter_weight_record: Option, ) -> &mut Self { self.voter_weight_record = voter_weight_record; self @@ -308,7 +306,7 @@ impl CastVoteBuilder { #[inline(always)] pub fn max_voter_weight_record( &mut self, - max_voter_weight_record: Option, + max_voter_weight_record: Option, ) -> &mut Self { self.max_voter_weight_record = max_voter_weight_record; self @@ -359,7 +357,7 @@ impl CastVoteBuilder { payer: self.payer.expect("payer is not set"), system_program: self .system_program - .unwrap_or(solana_pubkey::pubkey!("11111111111111111111111111111111")), + .unwrap_or(solana_address::address!("11111111111111111111111111111111")), realm_config_account: self .realm_config_account .expect("realm_config_account is not set"), diff --git a/e2e/governance/src/generated/instructions/complete_proposal.rs b/e2e/governance/src/generated/instructions/complete_proposal.rs index 2410dc2..952555d 100644 --- a/e2e/governance/src/generated/instructions/complete_proposal.rs +++ b/e2e/governance/src/generated/instructions/complete_proposal.rs @@ -13,11 +13,11 @@ pub const COMPLETE_PROPOSAL_DISCRIMINATOR: u8 = 28; /// Accounts. #[derive(Debug)] pub struct CompleteProposal { - pub proposal_account: solana_pubkey::Pubkey, + pub proposal_account: solana_address::Address, /// TokenOwnerRecord account of the Proposal owner - pub token_owner_record: solana_pubkey::Pubkey, + pub token_owner_record: solana_address::Address, /// Token Owner or Delegate - pub complete_proposal_authority: solana_pubkey::Pubkey, + pub complete_proposal_authority: solana_address::Address, } impl CompleteProposal { @@ -55,7 +55,6 @@ impl CompleteProposal { } #[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] -#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct CompleteProposalInstructionData { discriminator: u8, } @@ -85,9 +84,9 @@ impl Default for CompleteProposalInstructionData { /// 2. `[signer]` complete_proposal_authority #[derive(Clone, Debug, Default)] pub struct CompleteProposalBuilder { - proposal_account: Option, - token_owner_record: Option, - complete_proposal_authority: Option, + proposal_account: Option, + token_owner_record: Option, + complete_proposal_authority: Option, __remaining_accounts: Vec, } @@ -96,13 +95,13 @@ impl CompleteProposalBuilder { Self::default() } #[inline(always)] - pub fn proposal_account(&mut self, proposal_account: solana_pubkey::Pubkey) -> &mut Self { + pub fn proposal_account(&mut self, proposal_account: solana_address::Address) -> &mut Self { self.proposal_account = Some(proposal_account); self } /// TokenOwnerRecord account of the Proposal owner #[inline(always)] - pub fn token_owner_record(&mut self, token_owner_record: solana_pubkey::Pubkey) -> &mut Self { + pub fn token_owner_record(&mut self, token_owner_record: solana_address::Address) -> &mut Self { self.token_owner_record = Some(token_owner_record); self } @@ -110,7 +109,7 @@ impl CompleteProposalBuilder { #[inline(always)] pub fn complete_proposal_authority( &mut self, - complete_proposal_authority: solana_pubkey::Pubkey, + complete_proposal_authority: solana_address::Address, ) -> &mut Self { self.complete_proposal_authority = Some(complete_proposal_authority); self diff --git a/e2e/governance/src/generated/instructions/create_governance.rs b/e2e/governance/src/generated/instructions/create_governance.rs index b9c2767..a419648 100644 --- a/e2e/governance/src/generated/instructions/create_governance.rs +++ b/e2e/governance/src/generated/instructions/create_governance.rs @@ -15,24 +15,24 @@ pub const CREATE_GOVERNANCE_DISCRIMINATOR: u8 = 4; #[derive(Debug)] pub struct CreateGovernance { /// Realm account the created governance belongs to - pub realm_account: solana_pubkey::Pubkey, + pub realm_account: solana_address::Address, /// seeds=['account-governance', realm, governed_account] - pub governance_account: solana_pubkey::Pubkey, + pub governance_account: solana_address::Address, /// Account governed by this Governance (governing_account). /// Note: the account doesn't have to exist and can be used only as a unique identified for the Governance account - pub governed_account: solana_pubkey::Pubkey, + pub governed_account: solana_address::Address, /// Used only if not signed by RealmAuthority - pub governing_token_owner_record: solana_pubkey::Pubkey, + pub governing_token_owner_record: solana_address::Address, - pub payer: solana_pubkey::Pubkey, + pub payer: solana_address::Address, - pub system_program: solana_pubkey::Pubkey, + pub system_program: solana_address::Address, - pub governance_authority: solana_pubkey::Pubkey, + pub governance_authority: solana_address::Address, /// seeds=['realm-config', realm] - pub realm_config_account: solana_pubkey::Pubkey, + pub realm_config_account: solana_address::Address, /// Optional Voter Weight Record - pub voter_weight_record: Option, + pub voter_weight_record: Option, } impl CreateGovernance { @@ -106,7 +106,6 @@ impl CreateGovernance { } #[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] -#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct CreateGovernanceInstructionData { discriminator: u8, } @@ -128,7 +127,6 @@ impl Default for CreateGovernanceInstructionData { } #[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] -#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct CreateGovernanceInstructionArgs { pub config: GovernanceConfig, } @@ -154,15 +152,15 @@ impl CreateGovernanceInstructionArgs { /// 8. `[optional]` voter_weight_record #[derive(Clone, Debug, Default)] pub struct CreateGovernanceBuilder { - realm_account: Option, - governance_account: Option, - governed_account: Option, - governing_token_owner_record: Option, - payer: Option, - system_program: Option, - governance_authority: Option, - realm_config_account: Option, - voter_weight_record: Option, + realm_account: Option, + governance_account: Option, + governed_account: Option, + governing_token_owner_record: Option, + payer: Option, + system_program: Option, + governance_authority: Option, + realm_config_account: Option, + voter_weight_record: Option, config: Option, __remaining_accounts: Vec, } @@ -173,20 +171,20 @@ impl CreateGovernanceBuilder { } /// Realm account the created governance belongs to #[inline(always)] - pub fn realm_account(&mut self, realm_account: solana_pubkey::Pubkey) -> &mut Self { + pub fn realm_account(&mut self, realm_account: solana_address::Address) -> &mut Self { self.realm_account = Some(realm_account); self } /// seeds=['account-governance', realm, governed_account] #[inline(always)] - pub fn governance_account(&mut self, governance_account: solana_pubkey::Pubkey) -> &mut Self { + pub fn governance_account(&mut self, governance_account: solana_address::Address) -> &mut Self { self.governance_account = Some(governance_account); self } /// Account governed by this Governance (governing_account). /// Note: the account doesn't have to exist and can be used only as a unique identified for the Governance account #[inline(always)] - pub fn governed_account(&mut self, governed_account: solana_pubkey::Pubkey) -> &mut Self { + pub fn governed_account(&mut self, governed_account: solana_address::Address) -> &mut Self { self.governed_account = Some(governed_account); self } @@ -194,26 +192,26 @@ impl CreateGovernanceBuilder { #[inline(always)] pub fn governing_token_owner_record( &mut self, - governing_token_owner_record: solana_pubkey::Pubkey, + governing_token_owner_record: solana_address::Address, ) -> &mut Self { self.governing_token_owner_record = Some(governing_token_owner_record); self } #[inline(always)] - pub fn payer(&mut self, payer: solana_pubkey::Pubkey) -> &mut Self { + pub fn payer(&mut self, payer: solana_address::Address) -> &mut Self { self.payer = Some(payer); self } /// `[optional account, default to '11111111111111111111111111111111']` #[inline(always)] - pub fn system_program(&mut self, system_program: solana_pubkey::Pubkey) -> &mut Self { + pub fn system_program(&mut self, system_program: solana_address::Address) -> &mut Self { self.system_program = Some(system_program); self } #[inline(always)] pub fn governance_authority( &mut self, - governance_authority: solana_pubkey::Pubkey, + governance_authority: solana_address::Address, ) -> &mut Self { self.governance_authority = Some(governance_authority); self @@ -222,7 +220,7 @@ impl CreateGovernanceBuilder { #[inline(always)] pub fn realm_config_account( &mut self, - realm_config_account: solana_pubkey::Pubkey, + realm_config_account: solana_address::Address, ) -> &mut Self { self.realm_config_account = Some(realm_config_account); self @@ -232,7 +230,7 @@ impl CreateGovernanceBuilder { #[inline(always)] pub fn voter_weight_record( &mut self, - voter_weight_record: Option, + voter_weight_record: Option, ) -> &mut Self { self.voter_weight_record = voter_weight_record; self @@ -271,7 +269,7 @@ impl CreateGovernanceBuilder { payer: self.payer.expect("payer is not set"), system_program: self .system_program - .unwrap_or(solana_pubkey::pubkey!("11111111111111111111111111111111")), + .unwrap_or(solana_address::address!("11111111111111111111111111111111")), governance_authority: self .governance_authority .expect("governance_authority is not set"), diff --git a/e2e/governance/src/generated/instructions/create_mint_governance.rs b/e2e/governance/src/generated/instructions/create_mint_governance.rs index 221ea76..c715de4 100644 --- a/e2e/governance/src/generated/instructions/create_mint_governance.rs +++ b/e2e/governance/src/generated/instructions/create_mint_governance.rs @@ -15,27 +15,27 @@ pub const CREATE_MINT_GOVERNANCE_DISCRIMINATOR: u8 = 17; #[derive(Debug)] pub struct CreateMintGovernance { /// Realm account the created Governance belongs to - pub realm_account: solana_pubkey::Pubkey, + pub realm_account: solana_address::Address, /// Mint Governance account. seeds=['mint-governance', realm, governed_mint] - pub mint_governance_account: solana_pubkey::Pubkey, + pub mint_governance_account: solana_address::Address, /// Mint governed by this Governance account - pub governed_mint: solana_pubkey::Pubkey, + pub governed_mint: solana_address::Address, /// Current Mint authority (MintTokens and optionally FreezeAccount) - pub mint_authority: solana_pubkey::Pubkey, + pub mint_authority: solana_address::Address, /// Governing TokenOwnerRecord account (Used only if not signed by RealmAuthority) - pub governing_token_owner_record: solana_pubkey::Pubkey, + pub governing_token_owner_record: solana_address::Address, - pub payer: solana_pubkey::Pubkey, + pub payer: solana_address::Address, - pub token_program: solana_pubkey::Pubkey, + pub token_program: solana_address::Address, - pub system_program: solana_pubkey::Pubkey, + pub system_program: solana_address::Address, - pub governance_authority: solana_pubkey::Pubkey, + pub governance_authority: solana_address::Address, /// RealmConfig account. seeds=['realm-config', realm] - pub realm_config: solana_pubkey::Pubkey, + pub realm_config: solana_address::Address, /// Optional Voter Weight Record - pub voter_weight_record: Option, + pub voter_weight_record: Option, } impl CreateMintGovernance { @@ -119,7 +119,6 @@ impl CreateMintGovernance { } #[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] -#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct CreateMintGovernanceInstructionData { discriminator: u8, } @@ -141,7 +140,6 @@ impl Default for CreateMintGovernanceInstructionData { } #[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] -#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct CreateMintGovernanceInstructionArgs { pub config: GovernanceConfig, pub transfer_mint_authorities: bool, @@ -170,17 +168,17 @@ impl CreateMintGovernanceInstructionArgs { /// 10. `[optional]` voter_weight_record #[derive(Clone, Debug, Default)] pub struct CreateMintGovernanceBuilder { - realm_account: Option, - mint_governance_account: Option, - governed_mint: Option, - mint_authority: Option, - governing_token_owner_record: Option, - payer: Option, - token_program: Option, - system_program: Option, - governance_authority: Option, - realm_config: Option, - voter_weight_record: Option, + realm_account: Option, + mint_governance_account: Option, + governed_mint: Option, + mint_authority: Option, + governing_token_owner_record: Option, + payer: Option, + token_program: Option, + system_program: Option, + governance_authority: Option, + realm_config: Option, + voter_weight_record: Option, config: Option, transfer_mint_authorities: Option, __remaining_accounts: Vec, @@ -192,7 +190,7 @@ impl CreateMintGovernanceBuilder { } /// Realm account the created Governance belongs to #[inline(always)] - pub fn realm_account(&mut self, realm_account: solana_pubkey::Pubkey) -> &mut Self { + pub fn realm_account(&mut self, realm_account: solana_address::Address) -> &mut Self { self.realm_account = Some(realm_account); self } @@ -200,20 +198,20 @@ impl CreateMintGovernanceBuilder { #[inline(always)] pub fn mint_governance_account( &mut self, - mint_governance_account: solana_pubkey::Pubkey, + mint_governance_account: solana_address::Address, ) -> &mut Self { self.mint_governance_account = Some(mint_governance_account); self } /// Mint governed by this Governance account #[inline(always)] - pub fn governed_mint(&mut self, governed_mint: solana_pubkey::Pubkey) -> &mut Self { + pub fn governed_mint(&mut self, governed_mint: solana_address::Address) -> &mut Self { self.governed_mint = Some(governed_mint); self } /// Current Mint authority (MintTokens and optionally FreezeAccount) #[inline(always)] - pub fn mint_authority(&mut self, mint_authority: solana_pubkey::Pubkey) -> &mut Self { + pub fn mint_authority(&mut self, mint_authority: solana_address::Address) -> &mut Self { self.mint_authority = Some(mint_authority); self } @@ -221,39 +219,39 @@ impl CreateMintGovernanceBuilder { #[inline(always)] pub fn governing_token_owner_record( &mut self, - governing_token_owner_record: solana_pubkey::Pubkey, + governing_token_owner_record: solana_address::Address, ) -> &mut Self { self.governing_token_owner_record = Some(governing_token_owner_record); self } #[inline(always)] - pub fn payer(&mut self, payer: solana_pubkey::Pubkey) -> &mut Self { + pub fn payer(&mut self, payer: solana_address::Address) -> &mut Self { self.payer = Some(payer); self } /// `[optional account, default to 'TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA']` #[inline(always)] - pub fn token_program(&mut self, token_program: solana_pubkey::Pubkey) -> &mut Self { + pub fn token_program(&mut self, token_program: solana_address::Address) -> &mut Self { self.token_program = Some(token_program); self } /// `[optional account, default to '11111111111111111111111111111111']` #[inline(always)] - pub fn system_program(&mut self, system_program: solana_pubkey::Pubkey) -> &mut Self { + pub fn system_program(&mut self, system_program: solana_address::Address) -> &mut Self { self.system_program = Some(system_program); self } #[inline(always)] pub fn governance_authority( &mut self, - governance_authority: solana_pubkey::Pubkey, + governance_authority: solana_address::Address, ) -> &mut Self { self.governance_authority = Some(governance_authority); self } /// RealmConfig account. seeds=['realm-config', realm] #[inline(always)] - pub fn realm_config(&mut self, realm_config: solana_pubkey::Pubkey) -> &mut Self { + pub fn realm_config(&mut self, realm_config: solana_address::Address) -> &mut Self { self.realm_config = Some(realm_config); self } @@ -262,7 +260,7 @@ impl CreateMintGovernanceBuilder { #[inline(always)] pub fn voter_weight_record( &mut self, - voter_weight_record: Option, + voter_weight_record: Option, ) -> &mut Self { self.voter_weight_record = voter_weight_record; self @@ -305,12 +303,12 @@ impl CreateMintGovernanceBuilder { .governing_token_owner_record .expect("governing_token_owner_record is not set"), payer: self.payer.expect("payer is not set"), - token_program: self.token_program.unwrap_or(solana_pubkey::pubkey!( + token_program: self.token_program.unwrap_or(solana_address::address!( "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA" )), system_program: self .system_program - .unwrap_or(solana_pubkey::pubkey!("11111111111111111111111111111111")), + .unwrap_or(solana_address::address!("11111111111111111111111111111111")), governance_authority: self .governance_authority .expect("governance_authority is not set"), diff --git a/e2e/governance/src/generated/instructions/create_native_treasury.rs b/e2e/governance/src/generated/instructions/create_native_treasury.rs index 35036e8..fa85864 100644 --- a/e2e/governance/src/generated/instructions/create_native_treasury.rs +++ b/e2e/governance/src/generated/instructions/create_native_treasury.rs @@ -14,13 +14,13 @@ pub const CREATE_NATIVE_TREASURY_DISCRIMINATOR: u8 = 25; #[derive(Debug)] pub struct CreateNativeTreasury { /// Governance account the treasury account is for - pub governance_account: solana_pubkey::Pubkey, + pub governance_account: solana_address::Address, /// seeds=['native-treasury', governance] - pub native_treasury_account: solana_pubkey::Pubkey, + pub native_treasury_account: solana_address::Address, - pub payer: solana_pubkey::Pubkey, + pub payer: solana_address::Address, - pub system_program: solana_pubkey::Pubkey, + pub system_program: solana_address::Address, } impl CreateNativeTreasury { @@ -63,7 +63,6 @@ impl CreateNativeTreasury { } #[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] -#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct CreateNativeTreasuryInstructionData { discriminator: u8, } @@ -94,10 +93,10 @@ impl Default for CreateNativeTreasuryInstructionData { /// 3. `[optional]` system_program (default to `11111111111111111111111111111111`) #[derive(Clone, Debug, Default)] pub struct CreateNativeTreasuryBuilder { - governance_account: Option, - native_treasury_account: Option, - payer: Option, - system_program: Option, + governance_account: Option, + native_treasury_account: Option, + payer: Option, + system_program: Option, __remaining_accounts: Vec, } @@ -107,7 +106,7 @@ impl CreateNativeTreasuryBuilder { } /// Governance account the treasury account is for #[inline(always)] - pub fn governance_account(&mut self, governance_account: solana_pubkey::Pubkey) -> &mut Self { + pub fn governance_account(&mut self, governance_account: solana_address::Address) -> &mut Self { self.governance_account = Some(governance_account); self } @@ -115,19 +114,19 @@ impl CreateNativeTreasuryBuilder { #[inline(always)] pub fn native_treasury_account( &mut self, - native_treasury_account: solana_pubkey::Pubkey, + native_treasury_account: solana_address::Address, ) -> &mut Self { self.native_treasury_account = Some(native_treasury_account); self } #[inline(always)] - pub fn payer(&mut self, payer: solana_pubkey::Pubkey) -> &mut Self { + pub fn payer(&mut self, payer: solana_address::Address) -> &mut Self { self.payer = Some(payer); self } /// `[optional account, default to '11111111111111111111111111111111']` #[inline(always)] - pub fn system_program(&mut self, system_program: solana_pubkey::Pubkey) -> &mut Self { + pub fn system_program(&mut self, system_program: solana_address::Address) -> &mut Self { self.system_program = Some(system_program); self } @@ -158,7 +157,7 @@ impl CreateNativeTreasuryBuilder { payer: self.payer.expect("payer is not set"), system_program: self .system_program - .unwrap_or(solana_pubkey::pubkey!("11111111111111111111111111111111")), + .unwrap_or(solana_address::address!("11111111111111111111111111111111")), }; accounts.instruction_with_remaining_accounts(&self.__remaining_accounts) diff --git a/e2e/governance/src/generated/instructions/create_program_governance.rs b/e2e/governance/src/generated/instructions/create_program_governance.rs index 545e74e..ec6f169 100644 --- a/e2e/governance/src/generated/instructions/create_program_governance.rs +++ b/e2e/governance/src/generated/instructions/create_program_governance.rs @@ -15,29 +15,29 @@ pub const CREATE_PROGRAM_GOVERNANCE_DISCRIMINATOR: u8 = 5; #[derive(Debug)] pub struct CreateProgramGovernance { /// Realm account the created Governance belongs to - pub realm_account: solana_pubkey::Pubkey, + pub realm_account: solana_address::Address, /// Program Governance account. seeds: ['program-governance', realm, governed_program] - pub program_governance_account: solana_pubkey::Pubkey, + pub program_governance_account: solana_address::Address, /// Program governed by this Governance account - pub governed_program: solana_pubkey::Pubkey, + pub governed_program: solana_address::Address, /// Program Data account of the Program governed by this Governance account - pub program_data: solana_pubkey::Pubkey, + pub program_data: solana_address::Address, /// Current Upgrade Authority account of the Program governed by this Governance account - pub current_upgrade_authority: solana_pubkey::Pubkey, + pub current_upgrade_authority: solana_address::Address, /// Governing TokenOwnerRecord account (Used only if not signed by RealmAuthority) - pub governing_token_owner_record: solana_pubkey::Pubkey, + pub governing_token_owner_record: solana_address::Address, - pub payer: solana_pubkey::Pubkey, + pub payer: solana_address::Address, /// bpf_upgradeable_loader_program program - pub bpf_upgradeable_loader_program: solana_pubkey::Pubkey, + pub bpf_upgradeable_loader_program: solana_address::Address, - pub system_program: solana_pubkey::Pubkey, + pub system_program: solana_address::Address, - pub governance_authority: solana_pubkey::Pubkey, + pub governance_authority: solana_address::Address, /// RealmConfig account. seeds=['realm-config', realm] - pub realm_config: solana_pubkey::Pubkey, + pub realm_config: solana_address::Address, /// Optional Voter Weight Record - pub voter_weight_record: Option, + pub voter_weight_record: Option, } impl CreateProgramGovernance { @@ -125,7 +125,6 @@ impl CreateProgramGovernance { } #[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] -#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct CreateProgramGovernanceInstructionData { discriminator: u8, } @@ -147,7 +146,6 @@ impl Default for CreateProgramGovernanceInstructionData { } #[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] -#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct CreateProgramGovernanceInstructionArgs { pub config: GovernanceConfig, pub transfer_upgrade_authority: bool, @@ -177,18 +175,18 @@ impl CreateProgramGovernanceInstructionArgs { /// 11. `[optional]` voter_weight_record #[derive(Clone, Debug, Default)] pub struct CreateProgramGovernanceBuilder { - realm_account: Option, - program_governance_account: Option, - governed_program: Option, - program_data: Option, - current_upgrade_authority: Option, - governing_token_owner_record: Option, - payer: Option, - bpf_upgradeable_loader_program: Option, - system_program: Option, - governance_authority: Option, - realm_config: Option, - voter_weight_record: Option, + realm_account: Option, + program_governance_account: Option, + governed_program: Option, + program_data: Option, + current_upgrade_authority: Option, + governing_token_owner_record: Option, + payer: Option, + bpf_upgradeable_loader_program: Option, + system_program: Option, + governance_authority: Option, + realm_config: Option, + voter_weight_record: Option, config: Option, transfer_upgrade_authority: Option, __remaining_accounts: Vec, @@ -200,7 +198,7 @@ impl CreateProgramGovernanceBuilder { } /// Realm account the created Governance belongs to #[inline(always)] - pub fn realm_account(&mut self, realm_account: solana_pubkey::Pubkey) -> &mut Self { + pub fn realm_account(&mut self, realm_account: solana_address::Address) -> &mut Self { self.realm_account = Some(realm_account); self } @@ -208,20 +206,20 @@ impl CreateProgramGovernanceBuilder { #[inline(always)] pub fn program_governance_account( &mut self, - program_governance_account: solana_pubkey::Pubkey, + program_governance_account: solana_address::Address, ) -> &mut Self { self.program_governance_account = Some(program_governance_account); self } /// Program governed by this Governance account #[inline(always)] - pub fn governed_program(&mut self, governed_program: solana_pubkey::Pubkey) -> &mut Self { + pub fn governed_program(&mut self, governed_program: solana_address::Address) -> &mut Self { self.governed_program = Some(governed_program); self } /// Program Data account of the Program governed by this Governance account #[inline(always)] - pub fn program_data(&mut self, program_data: solana_pubkey::Pubkey) -> &mut Self { + pub fn program_data(&mut self, program_data: solana_address::Address) -> &mut Self { self.program_data = Some(program_data); self } @@ -229,7 +227,7 @@ impl CreateProgramGovernanceBuilder { #[inline(always)] pub fn current_upgrade_authority( &mut self, - current_upgrade_authority: solana_pubkey::Pubkey, + current_upgrade_authority: solana_address::Address, ) -> &mut Self { self.current_upgrade_authority = Some(current_upgrade_authority); self @@ -238,13 +236,13 @@ impl CreateProgramGovernanceBuilder { #[inline(always)] pub fn governing_token_owner_record( &mut self, - governing_token_owner_record: solana_pubkey::Pubkey, + governing_token_owner_record: solana_address::Address, ) -> &mut Self { self.governing_token_owner_record = Some(governing_token_owner_record); self } #[inline(always)] - pub fn payer(&mut self, payer: solana_pubkey::Pubkey) -> &mut Self { + pub fn payer(&mut self, payer: solana_address::Address) -> &mut Self { self.payer = Some(payer); self } @@ -252,28 +250,28 @@ impl CreateProgramGovernanceBuilder { #[inline(always)] pub fn bpf_upgradeable_loader_program( &mut self, - bpf_upgradeable_loader_program: solana_pubkey::Pubkey, + bpf_upgradeable_loader_program: solana_address::Address, ) -> &mut Self { self.bpf_upgradeable_loader_program = Some(bpf_upgradeable_loader_program); self } /// `[optional account, default to '11111111111111111111111111111111']` #[inline(always)] - pub fn system_program(&mut self, system_program: solana_pubkey::Pubkey) -> &mut Self { + pub fn system_program(&mut self, system_program: solana_address::Address) -> &mut Self { self.system_program = Some(system_program); self } #[inline(always)] pub fn governance_authority( &mut self, - governance_authority: solana_pubkey::Pubkey, + governance_authority: solana_address::Address, ) -> &mut Self { self.governance_authority = Some(governance_authority); self } /// RealmConfig account. seeds=['realm-config', realm] #[inline(always)] - pub fn realm_config(&mut self, realm_config: solana_pubkey::Pubkey) -> &mut Self { + pub fn realm_config(&mut self, realm_config: solana_address::Address) -> &mut Self { self.realm_config = Some(realm_config); self } @@ -282,7 +280,7 @@ impl CreateProgramGovernanceBuilder { #[inline(always)] pub fn voter_weight_record( &mut self, - voter_weight_record: Option, + voter_weight_record: Option, ) -> &mut Self { self.voter_weight_record = voter_weight_record; self @@ -333,7 +331,7 @@ impl CreateProgramGovernanceBuilder { .expect("bpf_upgradeable_loader_program is not set"), system_program: self .system_program - .unwrap_or(solana_pubkey::pubkey!("11111111111111111111111111111111")), + .unwrap_or(solana_address::address!("11111111111111111111111111111111")), governance_authority: self .governance_authority .expect("governance_authority is not set"), diff --git a/e2e/governance/src/generated/instructions/create_proposal.rs b/e2e/governance/src/generated/instructions/create_proposal.rs index 02d16d8..c4f4184 100644 --- a/e2e/governance/src/generated/instructions/create_proposal.rs +++ b/e2e/governance/src/generated/instructions/create_proposal.rs @@ -8,7 +8,7 @@ use crate::generated::types::VoteType; use borsh::BorshDeserialize; use borsh::BorshSerialize; -use solana_pubkey::Pubkey; +use solana_address::Address; pub const CREATE_PROPOSAL_DISCRIMINATOR: u8 = 6; @@ -16,29 +16,29 @@ pub const CREATE_PROPOSAL_DISCRIMINATOR: u8 = 6; #[derive(Debug)] pub struct CreateProposal { /// Realm account the created Proposal belongs to - pub realm_account: solana_pubkey::Pubkey, + pub realm_account: solana_address::Address, /// Proposal account. PDA seeds ['governance',governance, governing_token_mint, proposal_index] - pub proposal_account: solana_pubkey::Pubkey, + pub proposal_account: solana_address::Address, /// Governance account - pub governance_account: solana_pubkey::Pubkey, + pub governance_account: solana_address::Address, /// TokenOwnerRecord account of the Proposal owner - pub token_owner_record: solana_pubkey::Pubkey, + pub token_owner_record: solana_address::Address, /// Token Mint the Proposal is created for - pub governing_token_mint: solana_pubkey::Pubkey, + pub governing_token_mint: solana_address::Address, /// Governance Authority (Token Owner or Governance Delegate) - pub governance_authority: solana_pubkey::Pubkey, + pub governance_authority: solana_address::Address, - pub payer: solana_pubkey::Pubkey, + pub payer: solana_address::Address, - pub system_program: solana_pubkey::Pubkey, + pub system_program: solana_address::Address, /// RealmConfig account. PDA seeds: ['realm-config', realm] - pub realm_config: solana_pubkey::Pubkey, + pub realm_config: solana_address::Address, /// Optional Voter Weight Record - pub voter_weight_record: Option, + pub voter_weight_record: Option, /// Optional Proposal deposit is required when there are more active /// proposals than the configured deposit exempt amount. /// PDA seeds: ['proposal-deposit', proposal, deposit payer] - pub proposal_deposit_account: Option, + pub proposal_deposit_account: Option, } impl CreateProposal { @@ -127,7 +127,6 @@ impl CreateProposal { } #[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] -#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct CreateProposalInstructionData { discriminator: u8, } @@ -149,14 +148,13 @@ impl Default for CreateProposalInstructionData { } #[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] -#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct CreateProposalInstructionArgs { pub name: String, pub description_link: String, pub vote_type: VoteType, pub options: Vec, pub use_deny_option: bool, - pub proposal_seed: Pubkey, + pub proposal_seed: Address, } impl CreateProposalInstructionArgs { @@ -182,23 +180,23 @@ impl CreateProposalInstructionArgs { /// 10. `[optional]` proposal_deposit_account #[derive(Clone, Debug, Default)] pub struct CreateProposalBuilder { - realm_account: Option, - proposal_account: Option, - governance_account: Option, - token_owner_record: Option, - governing_token_mint: Option, - governance_authority: Option, - payer: Option, - system_program: Option, - realm_config: Option, - voter_weight_record: Option, - proposal_deposit_account: Option, + realm_account: Option, + proposal_account: Option, + governance_account: Option, + token_owner_record: Option, + governing_token_mint: Option, + governance_authority: Option, + payer: Option, + system_program: Option, + realm_config: Option, + voter_weight_record: Option, + proposal_deposit_account: Option, name: Option, description_link: Option, vote_type: Option, options: Option>, use_deny_option: Option, - proposal_seed: Option, + proposal_seed: Option
, __remaining_accounts: Vec, } @@ -208,25 +206,25 @@ impl CreateProposalBuilder { } /// Realm account the created Proposal belongs to #[inline(always)] - pub fn realm_account(&mut self, realm_account: solana_pubkey::Pubkey) -> &mut Self { + pub fn realm_account(&mut self, realm_account: solana_address::Address) -> &mut Self { self.realm_account = Some(realm_account); self } /// Proposal account. PDA seeds ['governance',governance, governing_token_mint, proposal_index] #[inline(always)] - pub fn proposal_account(&mut self, proposal_account: solana_pubkey::Pubkey) -> &mut Self { + pub fn proposal_account(&mut self, proposal_account: solana_address::Address) -> &mut Self { self.proposal_account = Some(proposal_account); self } /// Governance account #[inline(always)] - pub fn governance_account(&mut self, governance_account: solana_pubkey::Pubkey) -> &mut Self { + pub fn governance_account(&mut self, governance_account: solana_address::Address) -> &mut Self { self.governance_account = Some(governance_account); self } /// TokenOwnerRecord account of the Proposal owner #[inline(always)] - pub fn token_owner_record(&mut self, token_owner_record: solana_pubkey::Pubkey) -> &mut Self { + pub fn token_owner_record(&mut self, token_owner_record: solana_address::Address) -> &mut Self { self.token_owner_record = Some(token_owner_record); self } @@ -234,7 +232,7 @@ impl CreateProposalBuilder { #[inline(always)] pub fn governing_token_mint( &mut self, - governing_token_mint: solana_pubkey::Pubkey, + governing_token_mint: solana_address::Address, ) -> &mut Self { self.governing_token_mint = Some(governing_token_mint); self @@ -243,25 +241,25 @@ impl CreateProposalBuilder { #[inline(always)] pub fn governance_authority( &mut self, - governance_authority: solana_pubkey::Pubkey, + governance_authority: solana_address::Address, ) -> &mut Self { self.governance_authority = Some(governance_authority); self } #[inline(always)] - pub fn payer(&mut self, payer: solana_pubkey::Pubkey) -> &mut Self { + pub fn payer(&mut self, payer: solana_address::Address) -> &mut Self { self.payer = Some(payer); self } /// `[optional account, default to '11111111111111111111111111111111']` #[inline(always)] - pub fn system_program(&mut self, system_program: solana_pubkey::Pubkey) -> &mut Self { + pub fn system_program(&mut self, system_program: solana_address::Address) -> &mut Self { self.system_program = Some(system_program); self } /// RealmConfig account. PDA seeds: ['realm-config', realm] #[inline(always)] - pub fn realm_config(&mut self, realm_config: solana_pubkey::Pubkey) -> &mut Self { + pub fn realm_config(&mut self, realm_config: solana_address::Address) -> &mut Self { self.realm_config = Some(realm_config); self } @@ -270,7 +268,7 @@ impl CreateProposalBuilder { #[inline(always)] pub fn voter_weight_record( &mut self, - voter_weight_record: Option, + voter_weight_record: Option, ) -> &mut Self { self.voter_weight_record = voter_weight_record; self @@ -282,7 +280,7 @@ impl CreateProposalBuilder { #[inline(always)] pub fn proposal_deposit_account( &mut self, - proposal_deposit_account: Option, + proposal_deposit_account: Option, ) -> &mut Self { self.proposal_deposit_account = proposal_deposit_account; self @@ -313,7 +311,7 @@ impl CreateProposalBuilder { self } #[inline(always)] - pub fn proposal_seed(&mut self, proposal_seed: Pubkey) -> &mut Self { + pub fn proposal_seed(&mut self, proposal_seed: Address) -> &mut Self { self.proposal_seed = Some(proposal_seed); self } @@ -352,7 +350,7 @@ impl CreateProposalBuilder { payer: self.payer.expect("payer is not set"), system_program: self .system_program - .unwrap_or(solana_pubkey::pubkey!("11111111111111111111111111111111")), + .unwrap_or(solana_address::address!("11111111111111111111111111111111")), realm_config: self.realm_config.expect("realm_config is not set"), voter_weight_record: self.voter_weight_record, proposal_deposit_account: self.proposal_deposit_account, @@ -757,7 +755,7 @@ impl<'a, 'b> CreateProposalCpiBuilder<'a, 'b> { self } #[inline(always)] - pub fn proposal_seed(&mut self, proposal_seed: Pubkey) -> &mut Self { + pub fn proposal_seed(&mut self, proposal_seed: Address) -> &mut Self { self.instruction.proposal_seed = Some(proposal_seed); self } @@ -899,7 +897,7 @@ struct CreateProposalCpiBuilderInstruction<'a, 'b> { vote_type: Option, options: Option>, use_deny_option: Option, - proposal_seed: Option, + proposal_seed: Option
, /// Additional instruction accounts `(AccountInfo, is_writable, is_signer)`. __remaining_accounts: Vec<(&'b solana_account_info::AccountInfo<'a>, bool, bool)>, } diff --git a/e2e/governance/src/generated/instructions/create_realm.rs b/e2e/governance/src/generated/instructions/create_realm.rs index 6b8e8cc..395868f 100644 --- a/e2e/governance/src/generated/instructions/create_realm.rs +++ b/e2e/governance/src/generated/instructions/create_realm.rs @@ -15,38 +15,38 @@ pub const CREATE_REALM_DISCRIMINATOR: u8 = 0; #[derive(Debug)] pub struct CreateRealm { /// Governance Realm account - pub realm_account: solana_pubkey::Pubkey, + pub realm_account: solana_address::Address, /// The authority of the Realm - pub realm_authority: solana_pubkey::Pubkey, + pub realm_authority: solana_address::Address, /// The mint address of the token to be used as the community mint - pub community_token_mint: solana_pubkey::Pubkey, + pub community_token_mint: solana_address::Address, /// The account to hold the community tokens. /// PDA seeds=['governance', realm, community_mint] - pub community_token_holding_account: solana_pubkey::Pubkey, + pub community_token_holding_account: solana_address::Address, /// the payer of this transaction - pub payer: solana_pubkey::Pubkey, + pub payer: solana_address::Address, /// System Program - pub system_program: solana_pubkey::Pubkey, + pub system_program: solana_address::Address, /// SPL Token Program - pub token_program: solana_pubkey::Pubkey, + pub token_program: solana_address::Address, /// SysVar Rent - pub rent: solana_pubkey::Pubkey, + pub rent: solana_address::Address, /// The mint address of the token to be used as the council mint - pub council_token_mint: Option, + pub council_token_mint: Option, /// The account to hold the council tokens. /// PDA seeds: ['governance',realm,council_mint] /// - pub council_token_holding_account: Option, + pub council_token_holding_account: Option, /// Realm Config account - pub realm_config: solana_pubkey::Pubkey, + pub realm_config: solana_address::Address, /// Optional Community Voter Weight Addin Program Id - pub community_voter_weight_addin: Option, + pub community_voter_weight_addin: Option, /// Optional Max Community Voter Weight Addin Program Id - pub max_community_voter_weight_addin: Option, + pub max_community_voter_weight_addin: Option, /// Optional Council Voter Weight Addin Program Id - pub council_voter_weight_addin: Option, + pub council_voter_weight_addin: Option, /// Optional Max Council Voter Weight Addin Program Id - pub max_council_voter_weight_addin: Option, + pub max_council_voter_weight_addin: Option, } impl CreateRealm { @@ -173,7 +173,6 @@ impl CreateRealm { } #[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] -#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct CreateRealmInstructionData { discriminator: u8, } @@ -195,7 +194,6 @@ impl Default for CreateRealmInstructionData { } #[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] -#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct CreateRealmInstructionArgs { pub name: String, pub config_args: RealmConfigParams, @@ -228,21 +226,21 @@ impl CreateRealmInstructionArgs { /// 14. `[optional]` max_council_voter_weight_addin #[derive(Clone, Debug, Default)] pub struct CreateRealmBuilder { - realm_account: Option, - realm_authority: Option, - community_token_mint: Option, - community_token_holding_account: Option, - payer: Option, - system_program: Option, - token_program: Option, - rent: Option, - council_token_mint: Option, - council_token_holding_account: Option, - realm_config: Option, - community_voter_weight_addin: Option, - max_community_voter_weight_addin: Option, - council_voter_weight_addin: Option, - max_council_voter_weight_addin: Option, + realm_account: Option, + realm_authority: Option, + community_token_mint: Option, + community_token_holding_account: Option, + payer: Option, + system_program: Option, + token_program: Option, + rent: Option, + council_token_mint: Option, + council_token_holding_account: Option, + realm_config: Option, + community_voter_weight_addin: Option, + max_community_voter_weight_addin: Option, + council_voter_weight_addin: Option, + max_council_voter_weight_addin: Option, name: Option, config_args: Option, __remaining_accounts: Vec, @@ -254,13 +252,13 @@ impl CreateRealmBuilder { } /// Governance Realm account #[inline(always)] - pub fn realm_account(&mut self, realm_account: solana_pubkey::Pubkey) -> &mut Self { + pub fn realm_account(&mut self, realm_account: solana_address::Address) -> &mut Self { self.realm_account = Some(realm_account); self } /// The authority of the Realm #[inline(always)] - pub fn realm_authority(&mut self, realm_authority: solana_pubkey::Pubkey) -> &mut Self { + pub fn realm_authority(&mut self, realm_authority: solana_address::Address) -> &mut Self { self.realm_authority = Some(realm_authority); self } @@ -268,7 +266,7 @@ impl CreateRealmBuilder { #[inline(always)] pub fn community_token_mint( &mut self, - community_token_mint: solana_pubkey::Pubkey, + community_token_mint: solana_address::Address, ) -> &mut Self { self.community_token_mint = Some(community_token_mint); self @@ -278,35 +276,35 @@ impl CreateRealmBuilder { #[inline(always)] pub fn community_token_holding_account( &mut self, - community_token_holding_account: solana_pubkey::Pubkey, + community_token_holding_account: solana_address::Address, ) -> &mut Self { self.community_token_holding_account = Some(community_token_holding_account); self } /// the payer of this transaction #[inline(always)] - pub fn payer(&mut self, payer: solana_pubkey::Pubkey) -> &mut Self { + pub fn payer(&mut self, payer: solana_address::Address) -> &mut Self { self.payer = Some(payer); self } /// `[optional account, default to '11111111111111111111111111111111']` /// System Program #[inline(always)] - pub fn system_program(&mut self, system_program: solana_pubkey::Pubkey) -> &mut Self { + pub fn system_program(&mut self, system_program: solana_address::Address) -> &mut Self { self.system_program = Some(system_program); self } /// `[optional account, default to 'TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA']` /// SPL Token Program #[inline(always)] - pub fn token_program(&mut self, token_program: solana_pubkey::Pubkey) -> &mut Self { + pub fn token_program(&mut self, token_program: solana_address::Address) -> &mut Self { self.token_program = Some(token_program); self } /// `[optional account, default to 'SysvarRent111111111111111111111111111111111']` /// SysVar Rent #[inline(always)] - pub fn rent(&mut self, rent: solana_pubkey::Pubkey) -> &mut Self { + pub fn rent(&mut self, rent: solana_address::Address) -> &mut Self { self.rent = Some(rent); self } @@ -315,7 +313,7 @@ impl CreateRealmBuilder { #[inline(always)] pub fn council_token_mint( &mut self, - council_token_mint: Option, + council_token_mint: Option, ) -> &mut Self { self.council_token_mint = council_token_mint; self @@ -327,14 +325,14 @@ impl CreateRealmBuilder { #[inline(always)] pub fn council_token_holding_account( &mut self, - council_token_holding_account: Option, + council_token_holding_account: Option, ) -> &mut Self { self.council_token_holding_account = council_token_holding_account; self } /// Realm Config account #[inline(always)] - pub fn realm_config(&mut self, realm_config: solana_pubkey::Pubkey) -> &mut Self { + pub fn realm_config(&mut self, realm_config: solana_address::Address) -> &mut Self { self.realm_config = Some(realm_config); self } @@ -343,7 +341,7 @@ impl CreateRealmBuilder { #[inline(always)] pub fn community_voter_weight_addin( &mut self, - community_voter_weight_addin: Option, + community_voter_weight_addin: Option, ) -> &mut Self { self.community_voter_weight_addin = community_voter_weight_addin; self @@ -353,7 +351,7 @@ impl CreateRealmBuilder { #[inline(always)] pub fn max_community_voter_weight_addin( &mut self, - max_community_voter_weight_addin: Option, + max_community_voter_weight_addin: Option, ) -> &mut Self { self.max_community_voter_weight_addin = max_community_voter_weight_addin; self @@ -363,7 +361,7 @@ impl CreateRealmBuilder { #[inline(always)] pub fn council_voter_weight_addin( &mut self, - council_voter_weight_addin: Option, + council_voter_weight_addin: Option, ) -> &mut Self { self.council_voter_weight_addin = council_voter_weight_addin; self @@ -373,7 +371,7 @@ impl CreateRealmBuilder { #[inline(always)] pub fn max_council_voter_weight_addin( &mut self, - max_council_voter_weight_addin: Option, + max_council_voter_weight_addin: Option, ) -> &mut Self { self.max_council_voter_weight_addin = max_council_voter_weight_addin; self @@ -417,11 +415,11 @@ impl CreateRealmBuilder { payer: self.payer.expect("payer is not set"), system_program: self .system_program - .unwrap_or(solana_pubkey::pubkey!("11111111111111111111111111111111")), - token_program: self.token_program.unwrap_or(solana_pubkey::pubkey!( + .unwrap_or(solana_address::address!("11111111111111111111111111111111")), + token_program: self.token_program.unwrap_or(solana_address::address!( "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA" )), - rent: self.rent.unwrap_or(solana_pubkey::pubkey!( + rent: self.rent.unwrap_or(solana_address::address!( "SysvarRent111111111111111111111111111111111" )), council_token_mint: self.council_token_mint, diff --git a/e2e/governance/src/generated/instructions/create_token_governance.rs b/e2e/governance/src/generated/instructions/create_token_governance.rs index 50425d3..a63a4b0 100644 --- a/e2e/governance/src/generated/instructions/create_token_governance.rs +++ b/e2e/governance/src/generated/instructions/create_token_governance.rs @@ -15,27 +15,27 @@ pub const CREATE_TOKEN_GOVERNANCE_DISCRIMINATOR: u8 = 18; #[derive(Debug)] pub struct CreateTokenGovernance { /// Realm account the created Governance belongs to - pub realm_account: solana_pubkey::Pubkey, + pub realm_account: solana_address::Address, /// Token Governance account. seeds=['token-governance', realm, governed_token] - pub token_governance_account: solana_pubkey::Pubkey, + pub token_governance_account: solana_address::Address, /// Token account governed by this Governance account - pub token_account: solana_pubkey::Pubkey, + pub token_account: solana_address::Address, /// Current token account authority (AccountOwner and optionally CloseAccount - pub token_account_authority: solana_pubkey::Pubkey, + pub token_account_authority: solana_address::Address, /// Governing TokenOwnerRecord account (Used only if not signed by RealmAuthority - pub governing_token_owner_record: solana_pubkey::Pubkey, + pub governing_token_owner_record: solana_address::Address, - pub payer: solana_pubkey::Pubkey, + pub payer: solana_address::Address, - pub token_program: solana_pubkey::Pubkey, + pub token_program: solana_address::Address, - pub system_program: solana_pubkey::Pubkey, + pub system_program: solana_address::Address, - pub governance_authority: solana_pubkey::Pubkey, + pub governance_authority: solana_address::Address, /// seeds=['realm-config', realm] - pub realm_config: solana_pubkey::Pubkey, + pub realm_config: solana_address::Address, /// Optional Voter Weight Record - pub voter_weight_record: Option, + pub voter_weight_record: Option, } impl CreateTokenGovernance { @@ -119,7 +119,6 @@ impl CreateTokenGovernance { } #[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] -#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct CreateTokenGovernanceInstructionData { discriminator: u8, } @@ -141,7 +140,6 @@ impl Default for CreateTokenGovernanceInstructionData { } #[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] -#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct CreateTokenGovernanceInstructionArgs { pub config: GovernanceConfig, pub transfer_account_authorities: bool, @@ -170,17 +168,17 @@ impl CreateTokenGovernanceInstructionArgs { /// 10. `[optional]` voter_weight_record #[derive(Clone, Debug, Default)] pub struct CreateTokenGovernanceBuilder { - realm_account: Option, - token_governance_account: Option, - token_account: Option, - token_account_authority: Option, - governing_token_owner_record: Option, - payer: Option, - token_program: Option, - system_program: Option, - governance_authority: Option, - realm_config: Option, - voter_weight_record: Option, + realm_account: Option, + token_governance_account: Option, + token_account: Option, + token_account_authority: Option, + governing_token_owner_record: Option, + payer: Option, + token_program: Option, + system_program: Option, + governance_authority: Option, + realm_config: Option, + voter_weight_record: Option, config: Option, transfer_account_authorities: Option, __remaining_accounts: Vec, @@ -192,7 +190,7 @@ impl CreateTokenGovernanceBuilder { } /// Realm account the created Governance belongs to #[inline(always)] - pub fn realm_account(&mut self, realm_account: solana_pubkey::Pubkey) -> &mut Self { + pub fn realm_account(&mut self, realm_account: solana_address::Address) -> &mut Self { self.realm_account = Some(realm_account); self } @@ -200,14 +198,14 @@ impl CreateTokenGovernanceBuilder { #[inline(always)] pub fn token_governance_account( &mut self, - token_governance_account: solana_pubkey::Pubkey, + token_governance_account: solana_address::Address, ) -> &mut Self { self.token_governance_account = Some(token_governance_account); self } /// Token account governed by this Governance account #[inline(always)] - pub fn token_account(&mut self, token_account: solana_pubkey::Pubkey) -> &mut Self { + pub fn token_account(&mut self, token_account: solana_address::Address) -> &mut Self { self.token_account = Some(token_account); self } @@ -215,7 +213,7 @@ impl CreateTokenGovernanceBuilder { #[inline(always)] pub fn token_account_authority( &mut self, - token_account_authority: solana_pubkey::Pubkey, + token_account_authority: solana_address::Address, ) -> &mut Self { self.token_account_authority = Some(token_account_authority); self @@ -224,39 +222,39 @@ impl CreateTokenGovernanceBuilder { #[inline(always)] pub fn governing_token_owner_record( &mut self, - governing_token_owner_record: solana_pubkey::Pubkey, + governing_token_owner_record: solana_address::Address, ) -> &mut Self { self.governing_token_owner_record = Some(governing_token_owner_record); self } #[inline(always)] - pub fn payer(&mut self, payer: solana_pubkey::Pubkey) -> &mut Self { + pub fn payer(&mut self, payer: solana_address::Address) -> &mut Self { self.payer = Some(payer); self } /// `[optional account, default to 'TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA']` #[inline(always)] - pub fn token_program(&mut self, token_program: solana_pubkey::Pubkey) -> &mut Self { + pub fn token_program(&mut self, token_program: solana_address::Address) -> &mut Self { self.token_program = Some(token_program); self } /// `[optional account, default to '11111111111111111111111111111111']` #[inline(always)] - pub fn system_program(&mut self, system_program: solana_pubkey::Pubkey) -> &mut Self { + pub fn system_program(&mut self, system_program: solana_address::Address) -> &mut Self { self.system_program = Some(system_program); self } #[inline(always)] pub fn governance_authority( &mut self, - governance_authority: solana_pubkey::Pubkey, + governance_authority: solana_address::Address, ) -> &mut Self { self.governance_authority = Some(governance_authority); self } /// seeds=['realm-config', realm] #[inline(always)] - pub fn realm_config(&mut self, realm_config: solana_pubkey::Pubkey) -> &mut Self { + pub fn realm_config(&mut self, realm_config: solana_address::Address) -> &mut Self { self.realm_config = Some(realm_config); self } @@ -265,7 +263,7 @@ impl CreateTokenGovernanceBuilder { #[inline(always)] pub fn voter_weight_record( &mut self, - voter_weight_record: Option, + voter_weight_record: Option, ) -> &mut Self { self.voter_weight_record = voter_weight_record; self @@ -313,12 +311,12 @@ impl CreateTokenGovernanceBuilder { .governing_token_owner_record .expect("governing_token_owner_record is not set"), payer: self.payer.expect("payer is not set"), - token_program: self.token_program.unwrap_or(solana_pubkey::pubkey!( + token_program: self.token_program.unwrap_or(solana_address::address!( "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA" )), system_program: self .system_program - .unwrap_or(solana_pubkey::pubkey!("11111111111111111111111111111111")), + .unwrap_or(solana_address::address!("11111111111111111111111111111111")), governance_authority: self .governance_authority .expect("governance_authority is not set"), diff --git a/e2e/governance/src/generated/instructions/create_token_owner_record.rs b/e2e/governance/src/generated/instructions/create_token_owner_record.rs index 25b7c74..441dc4d 100644 --- a/e2e/governance/src/generated/instructions/create_token_owner_record.rs +++ b/e2e/governance/src/generated/instructions/create_token_owner_record.rs @@ -13,17 +13,17 @@ pub const CREATE_TOKEN_OWNER_RECORD_DISCRIMINATOR: u8 = 23; /// Accounts. #[derive(Debug)] pub struct CreateTokenOwnerRecord { - pub realm_account: solana_pubkey::Pubkey, + pub realm_account: solana_address::Address, - pub governing_token_owner_account: solana_pubkey::Pubkey, + pub governing_token_owner_account: solana_address::Address, /// seeds=['governance', realm, governing_token_mint, governing_token_owner] - pub token_owner_record: solana_pubkey::Pubkey, + pub token_owner_record: solana_address::Address, - pub governing_token_mint: solana_pubkey::Pubkey, + pub governing_token_mint: solana_address::Address, - pub payer: solana_pubkey::Pubkey, + pub payer: solana_address::Address, - pub system_program: solana_pubkey::Pubkey, + pub system_program: solana_address::Address, } impl CreateTokenOwnerRecord { @@ -74,7 +74,6 @@ impl CreateTokenOwnerRecord { } #[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] -#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct CreateTokenOwnerRecordInstructionData { discriminator: u8, } @@ -107,12 +106,12 @@ impl Default for CreateTokenOwnerRecordInstructionData { /// 5. `[optional]` system_program (default to `11111111111111111111111111111111`) #[derive(Clone, Debug, Default)] pub struct CreateTokenOwnerRecordBuilder { - realm_account: Option, - governing_token_owner_account: Option, - token_owner_record: Option, - governing_token_mint: Option, - payer: Option, - system_program: Option, + realm_account: Option, + governing_token_owner_account: Option, + token_owner_record: Option, + governing_token_mint: Option, + payer: Option, + system_program: Option, __remaining_accounts: Vec, } @@ -121,40 +120,40 @@ impl CreateTokenOwnerRecordBuilder { Self::default() } #[inline(always)] - pub fn realm_account(&mut self, realm_account: solana_pubkey::Pubkey) -> &mut Self { + pub fn realm_account(&mut self, realm_account: solana_address::Address) -> &mut Self { self.realm_account = Some(realm_account); self } #[inline(always)] pub fn governing_token_owner_account( &mut self, - governing_token_owner_account: solana_pubkey::Pubkey, + governing_token_owner_account: solana_address::Address, ) -> &mut Self { self.governing_token_owner_account = Some(governing_token_owner_account); self } /// seeds=['governance', realm, governing_token_mint, governing_token_owner] #[inline(always)] - pub fn token_owner_record(&mut self, token_owner_record: solana_pubkey::Pubkey) -> &mut Self { + pub fn token_owner_record(&mut self, token_owner_record: solana_address::Address) -> &mut Self { self.token_owner_record = Some(token_owner_record); self } #[inline(always)] pub fn governing_token_mint( &mut self, - governing_token_mint: solana_pubkey::Pubkey, + governing_token_mint: solana_address::Address, ) -> &mut Self { self.governing_token_mint = Some(governing_token_mint); self } #[inline(always)] - pub fn payer(&mut self, payer: solana_pubkey::Pubkey) -> &mut Self { + pub fn payer(&mut self, payer: solana_address::Address) -> &mut Self { self.payer = Some(payer); self } /// `[optional account, default to '11111111111111111111111111111111']` #[inline(always)] - pub fn system_program(&mut self, system_program: solana_pubkey::Pubkey) -> &mut Self { + pub fn system_program(&mut self, system_program: solana_address::Address) -> &mut Self { self.system_program = Some(system_program); self } @@ -189,7 +188,7 @@ impl CreateTokenOwnerRecordBuilder { payer: self.payer.expect("payer is not set"), system_program: self .system_program - .unwrap_or(solana_pubkey::pubkey!("11111111111111111111111111111111")), + .unwrap_or(solana_address::address!("11111111111111111111111111111111")), }; accounts.instruction_with_remaining_accounts(&self.__remaining_accounts) diff --git a/e2e/governance/src/generated/instructions/deposit_governing_tokens.rs b/e2e/governance/src/generated/instructions/deposit_governing_tokens.rs index a4390ae..5ef3ce3 100644 --- a/e2e/governance/src/generated/instructions/deposit_governing_tokens.rs +++ b/e2e/governance/src/generated/instructions/deposit_governing_tokens.rs @@ -13,25 +13,25 @@ pub const DEPOSIT_GOVERNING_TOKENS_DISCRIMINATOR: u8 = 1; /// Accounts. #[derive(Debug)] pub struct DepositGoverningTokens { - pub realm_account: solana_pubkey::Pubkey, + pub realm_account: solana_address::Address, /// seeds=['governance', realm, governing_token_mint] - pub governing_token_holding_account: solana_pubkey::Pubkey, + pub governing_token_holding_account: solana_address::Address, /// It can either be spl-token TokenAccount or MintAccount. Tokens will be transferred or minted to the holding account - pub governing_token_source_account: solana_pubkey::Pubkey, + pub governing_token_source_account: solana_address::Address, - pub governing_token_owner_account: solana_pubkey::Pubkey, + pub governing_token_owner_account: solana_address::Address, /// It should be owner for TokenAccount and mint_authority for MintAccount - pub governing_token_source_account_authority: solana_pubkey::Pubkey, + pub governing_token_source_account_authority: solana_address::Address, /// seeds=['governance', realm, governing_token_mint, governing_token_owner] - pub token_owner_record: solana_pubkey::Pubkey, + pub token_owner_record: solana_address::Address, - pub payer: solana_pubkey::Pubkey, + pub payer: solana_address::Address, - pub system_program: solana_pubkey::Pubkey, + pub system_program: solana_address::Address, - pub token_program: solana_pubkey::Pubkey, + pub token_program: solana_address::Address, /// seeds=['realm-config', realm] - pub realm_config_account: solana_pubkey::Pubkey, + pub realm_config_account: solana_address::Address, } impl DepositGoverningTokens { @@ -102,7 +102,6 @@ impl DepositGoverningTokens { } #[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] -#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct DepositGoverningTokensInstructionData { discriminator: u8, } @@ -124,7 +123,6 @@ impl Default for DepositGoverningTokensInstructionData { } #[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] -#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct DepositGoverningTokensInstructionArgs { pub amount: u64, } @@ -151,16 +149,16 @@ impl DepositGoverningTokensInstructionArgs { /// 9. `[]` realm_config_account #[derive(Clone, Debug, Default)] pub struct DepositGoverningTokensBuilder { - realm_account: Option, - governing_token_holding_account: Option, - governing_token_source_account: Option, - governing_token_owner_account: Option, - governing_token_source_account_authority: Option, - token_owner_record: Option, - payer: Option, - system_program: Option, - token_program: Option, - realm_config_account: Option, + realm_account: Option, + governing_token_holding_account: Option, + governing_token_source_account: Option, + governing_token_owner_account: Option, + governing_token_source_account_authority: Option, + token_owner_record: Option, + payer: Option, + system_program: Option, + token_program: Option, + realm_config_account: Option, amount: Option, __remaining_accounts: Vec, } @@ -170,7 +168,7 @@ impl DepositGoverningTokensBuilder { Self::default() } #[inline(always)] - pub fn realm_account(&mut self, realm_account: solana_pubkey::Pubkey) -> &mut Self { + pub fn realm_account(&mut self, realm_account: solana_address::Address) -> &mut Self { self.realm_account = Some(realm_account); self } @@ -178,7 +176,7 @@ impl DepositGoverningTokensBuilder { #[inline(always)] pub fn governing_token_holding_account( &mut self, - governing_token_holding_account: solana_pubkey::Pubkey, + governing_token_holding_account: solana_address::Address, ) -> &mut Self { self.governing_token_holding_account = Some(governing_token_holding_account); self @@ -187,7 +185,7 @@ impl DepositGoverningTokensBuilder { #[inline(always)] pub fn governing_token_source_account( &mut self, - governing_token_source_account: solana_pubkey::Pubkey, + governing_token_source_account: solana_address::Address, ) -> &mut Self { self.governing_token_source_account = Some(governing_token_source_account); self @@ -195,7 +193,7 @@ impl DepositGoverningTokensBuilder { #[inline(always)] pub fn governing_token_owner_account( &mut self, - governing_token_owner_account: solana_pubkey::Pubkey, + governing_token_owner_account: solana_address::Address, ) -> &mut Self { self.governing_token_owner_account = Some(governing_token_owner_account); self @@ -204,7 +202,7 @@ impl DepositGoverningTokensBuilder { #[inline(always)] pub fn governing_token_source_account_authority( &mut self, - governing_token_source_account_authority: solana_pubkey::Pubkey, + governing_token_source_account_authority: solana_address::Address, ) -> &mut Self { self.governing_token_source_account_authority = Some(governing_token_source_account_authority); @@ -212,24 +210,24 @@ impl DepositGoverningTokensBuilder { } /// seeds=['governance', realm, governing_token_mint, governing_token_owner] #[inline(always)] - pub fn token_owner_record(&mut self, token_owner_record: solana_pubkey::Pubkey) -> &mut Self { + pub fn token_owner_record(&mut self, token_owner_record: solana_address::Address) -> &mut Self { self.token_owner_record = Some(token_owner_record); self } #[inline(always)] - pub fn payer(&mut self, payer: solana_pubkey::Pubkey) -> &mut Self { + pub fn payer(&mut self, payer: solana_address::Address) -> &mut Self { self.payer = Some(payer); self } /// `[optional account, default to '11111111111111111111111111111111']` #[inline(always)] - pub fn system_program(&mut self, system_program: solana_pubkey::Pubkey) -> &mut Self { + pub fn system_program(&mut self, system_program: solana_address::Address) -> &mut Self { self.system_program = Some(system_program); self } /// `[optional account, default to 'TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA']` #[inline(always)] - pub fn token_program(&mut self, token_program: solana_pubkey::Pubkey) -> &mut Self { + pub fn token_program(&mut self, token_program: solana_address::Address) -> &mut Self { self.token_program = Some(token_program); self } @@ -237,7 +235,7 @@ impl DepositGoverningTokensBuilder { #[inline(always)] pub fn realm_config_account( &mut self, - realm_config_account: solana_pubkey::Pubkey, + realm_config_account: solana_address::Address, ) -> &mut Self { self.realm_config_account = Some(realm_config_account); self @@ -284,8 +282,8 @@ impl DepositGoverningTokensBuilder { payer: self.payer.expect("payer is not set"), system_program: self .system_program - .unwrap_or(solana_pubkey::pubkey!("11111111111111111111111111111111")), - token_program: self.token_program.unwrap_or(solana_pubkey::pubkey!( + .unwrap_or(solana_address::address!("11111111111111111111111111111111")), + token_program: self.token_program.unwrap_or(solana_address::address!( "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA" )), realm_config_account: self diff --git a/e2e/governance/src/generated/instructions/execute_transaction.rs b/e2e/governance/src/generated/instructions/execute_transaction.rs index a26c75c..25bb355 100644 --- a/e2e/governance/src/generated/instructions/execute_transaction.rs +++ b/e2e/governance/src/generated/instructions/execute_transaction.rs @@ -13,11 +13,11 @@ pub const EXECUTE_TRANSACTION_DISCRIMINATOR: u8 = 16; /// Accounts. #[derive(Debug)] pub struct ExecuteTransaction { - pub governance_account: solana_pubkey::Pubkey, + pub governance_account: solana_address::Address, - pub proposal_account: solana_pubkey::Pubkey, + pub proposal_account: solana_address::Address, - pub proposal_transaction_account: solana_pubkey::Pubkey, + pub proposal_transaction_account: solana_address::Address, } impl ExecuteTransaction { @@ -57,7 +57,6 @@ impl ExecuteTransaction { } #[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] -#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct ExecuteTransactionInstructionData { discriminator: u8, } @@ -87,9 +86,9 @@ impl Default for ExecuteTransactionInstructionData { /// 2. `[writable]` proposal_transaction_account #[derive(Clone, Debug, Default)] pub struct ExecuteTransactionBuilder { - governance_account: Option, - proposal_account: Option, - proposal_transaction_account: Option, + governance_account: Option, + proposal_account: Option, + proposal_transaction_account: Option, __remaining_accounts: Vec, } @@ -98,19 +97,19 @@ impl ExecuteTransactionBuilder { Self::default() } #[inline(always)] - pub fn governance_account(&mut self, governance_account: solana_pubkey::Pubkey) -> &mut Self { + pub fn governance_account(&mut self, governance_account: solana_address::Address) -> &mut Self { self.governance_account = Some(governance_account); self } #[inline(always)] - pub fn proposal_account(&mut self, proposal_account: solana_pubkey::Pubkey) -> &mut Self { + pub fn proposal_account(&mut self, proposal_account: solana_address::Address) -> &mut Self { self.proposal_account = Some(proposal_account); self } #[inline(always)] pub fn proposal_transaction_account( &mut self, - proposal_transaction_account: solana_pubkey::Pubkey, + proposal_transaction_account: solana_address::Address, ) -> &mut Self { self.proposal_transaction_account = Some(proposal_transaction_account); self diff --git a/e2e/governance/src/generated/instructions/finalize_vote.rs b/e2e/governance/src/generated/instructions/finalize_vote.rs index cb800b2..2615d9e 100644 --- a/e2e/governance/src/generated/instructions/finalize_vote.rs +++ b/e2e/governance/src/generated/instructions/finalize_vote.rs @@ -13,19 +13,19 @@ pub const FINALIZE_VOTE_DISCRIMINATOR: u8 = 14; /// Accounts. #[derive(Debug)] pub struct FinalizeVote { - pub realm_account: solana_pubkey::Pubkey, + pub realm_account: solana_address::Address, - pub governance_account: solana_pubkey::Pubkey, + pub governance_account: solana_address::Address, - pub proposal_account: solana_pubkey::Pubkey, + pub proposal_account: solana_address::Address, /// TokenOwnerRecord of the Proposal owner - pub token_owner_record: solana_pubkey::Pubkey, + pub token_owner_record: solana_address::Address, - pub governing_token_mint: solana_pubkey::Pubkey, + pub governing_token_mint: solana_address::Address, /// RealmConfig account. PDA seeds: ['realm-config', realm] - pub realm_config: solana_pubkey::Pubkey, + pub realm_config: solana_address::Address, /// Optional Max Voter Weight Record - pub max_voter_weight_record: Option, + pub max_voter_weight_record: Option, } impl FinalizeVote { @@ -86,7 +86,6 @@ impl FinalizeVote { } #[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] -#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct FinalizeVoteInstructionData { discriminator: u8, } @@ -120,13 +119,13 @@ impl Default for FinalizeVoteInstructionData { /// 6. `[optional]` max_voter_weight_record #[derive(Clone, Debug, Default)] pub struct FinalizeVoteBuilder { - realm_account: Option, - governance_account: Option, - proposal_account: Option, - token_owner_record: Option, - governing_token_mint: Option, - realm_config: Option, - max_voter_weight_record: Option, + realm_account: Option, + governance_account: Option, + proposal_account: Option, + token_owner_record: Option, + governing_token_mint: Option, + realm_config: Option, + max_voter_weight_record: Option, __remaining_accounts: Vec, } @@ -135,37 +134,37 @@ impl FinalizeVoteBuilder { Self::default() } #[inline(always)] - pub fn realm_account(&mut self, realm_account: solana_pubkey::Pubkey) -> &mut Self { + pub fn realm_account(&mut self, realm_account: solana_address::Address) -> &mut Self { self.realm_account = Some(realm_account); self } #[inline(always)] - pub fn governance_account(&mut self, governance_account: solana_pubkey::Pubkey) -> &mut Self { + pub fn governance_account(&mut self, governance_account: solana_address::Address) -> &mut Self { self.governance_account = Some(governance_account); self } #[inline(always)] - pub fn proposal_account(&mut self, proposal_account: solana_pubkey::Pubkey) -> &mut Self { + pub fn proposal_account(&mut self, proposal_account: solana_address::Address) -> &mut Self { self.proposal_account = Some(proposal_account); self } /// TokenOwnerRecord of the Proposal owner #[inline(always)] - pub fn token_owner_record(&mut self, token_owner_record: solana_pubkey::Pubkey) -> &mut Self { + pub fn token_owner_record(&mut self, token_owner_record: solana_address::Address) -> &mut Self { self.token_owner_record = Some(token_owner_record); self } #[inline(always)] pub fn governing_token_mint( &mut self, - governing_token_mint: solana_pubkey::Pubkey, + governing_token_mint: solana_address::Address, ) -> &mut Self { self.governing_token_mint = Some(governing_token_mint); self } /// RealmConfig account. PDA seeds: ['realm-config', realm] #[inline(always)] - pub fn realm_config(&mut self, realm_config: solana_pubkey::Pubkey) -> &mut Self { + pub fn realm_config(&mut self, realm_config: solana_address::Address) -> &mut Self { self.realm_config = Some(realm_config); self } @@ -174,7 +173,7 @@ impl FinalizeVoteBuilder { #[inline(always)] pub fn max_voter_weight_record( &mut self, - max_voter_weight_record: Option, + max_voter_weight_record: Option, ) -> &mut Self { self.max_voter_weight_record = max_voter_weight_record; self diff --git a/e2e/governance/src/generated/instructions/flag_transaction_error.rs b/e2e/governance/src/generated/instructions/flag_transaction_error.rs index 3549368..0216457 100644 --- a/e2e/governance/src/generated/instructions/flag_transaction_error.rs +++ b/e2e/governance/src/generated/instructions/flag_transaction_error.rs @@ -13,13 +13,13 @@ pub const FLAG_TRANSACTION_ERROR_DISCRIMINATOR: u8 = 20; /// Accounts. #[derive(Debug)] pub struct FlagTransactionError { - pub proposal_account: solana_pubkey::Pubkey, + pub proposal_account: solana_address::Address, /// TokenOwnerRecord account of the Proposal owner - pub token_owner_record: solana_pubkey::Pubkey, + pub token_owner_record: solana_address::Address, /// Governance Authority (Token Owner or Governance Delegate) - pub governance_authority: solana_pubkey::Pubkey, + pub governance_authority: solana_address::Address, /// ProposalTransaction account to flag - pub proposal_transaction_account: solana_pubkey::Pubkey, + pub proposal_transaction_account: solana_address::Address, } impl FlagTransactionError { @@ -63,7 +63,6 @@ impl FlagTransactionError { } #[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] -#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct FlagTransactionErrorInstructionData { discriminator: u8, } @@ -94,10 +93,10 @@ impl Default for FlagTransactionErrorInstructionData { /// 3. `[writable]` proposal_transaction_account #[derive(Clone, Debug, Default)] pub struct FlagTransactionErrorBuilder { - proposal_account: Option, - token_owner_record: Option, - governance_authority: Option, - proposal_transaction_account: Option, + proposal_account: Option, + token_owner_record: Option, + governance_authority: Option, + proposal_transaction_account: Option, __remaining_accounts: Vec, } @@ -106,13 +105,13 @@ impl FlagTransactionErrorBuilder { Self::default() } #[inline(always)] - pub fn proposal_account(&mut self, proposal_account: solana_pubkey::Pubkey) -> &mut Self { + pub fn proposal_account(&mut self, proposal_account: solana_address::Address) -> &mut Self { self.proposal_account = Some(proposal_account); self } /// TokenOwnerRecord account of the Proposal owner #[inline(always)] - pub fn token_owner_record(&mut self, token_owner_record: solana_pubkey::Pubkey) -> &mut Self { + pub fn token_owner_record(&mut self, token_owner_record: solana_address::Address) -> &mut Self { self.token_owner_record = Some(token_owner_record); self } @@ -120,7 +119,7 @@ impl FlagTransactionErrorBuilder { #[inline(always)] pub fn governance_authority( &mut self, - governance_authority: solana_pubkey::Pubkey, + governance_authority: solana_address::Address, ) -> &mut Self { self.governance_authority = Some(governance_authority); self @@ -129,7 +128,7 @@ impl FlagTransactionErrorBuilder { #[inline(always)] pub fn proposal_transaction_account( &mut self, - proposal_transaction_account: solana_pubkey::Pubkey, + proposal_transaction_account: solana_address::Address, ) -> &mut Self { self.proposal_transaction_account = Some(proposal_transaction_account); self diff --git a/e2e/governance/src/generated/instructions/insert_transaction.rs b/e2e/governance/src/generated/instructions/insert_transaction.rs index e670906..574fa62 100644 --- a/e2e/governance/src/generated/instructions/insert_transaction.rs +++ b/e2e/governance/src/generated/instructions/insert_transaction.rs @@ -14,21 +14,21 @@ pub const INSERT_TRANSACTION_DISCRIMINATOR: u8 = 9; /// Accounts. #[derive(Debug)] pub struct InsertTransaction { - pub governance_account: solana_pubkey::Pubkey, + pub governance_account: solana_address::Address, - pub proposal_account: solana_pubkey::Pubkey, + pub proposal_account: solana_address::Address, /// TokenOwnerRecord account of the Proposal owner - pub token_owner_record: solana_pubkey::Pubkey, + pub token_owner_record: solana_address::Address, /// Governance Authority (Token Owner or Governance Delegate) - pub governance_authority: solana_pubkey::Pubkey, + pub governance_authority: solana_address::Address, /// ProposalTransaction, account. PDA seeds: ['governance', proposal, option_index, index] - pub proposal_transaction_account: solana_pubkey::Pubkey, + pub proposal_transaction_account: solana_address::Address, - pub payer: solana_pubkey::Pubkey, + pub payer: solana_address::Address, - pub system_program: solana_pubkey::Pubkey, + pub system_program: solana_address::Address, - pub rent: solana_pubkey::Pubkey, + pub rent: solana_address::Address, } impl InsertTransaction { @@ -92,7 +92,6 @@ impl InsertTransaction { } #[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] -#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct InsertTransactionInstructionData { discriminator: u8, } @@ -114,7 +113,6 @@ impl Default for InsertTransactionInstructionData { } #[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] -#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct InsertTransactionInstructionArgs { pub option_index: u8, pub index: u16, @@ -142,14 +140,14 @@ impl InsertTransactionInstructionArgs { /// 7. `[optional]` rent (default to `SysvarRent111111111111111111111111111111111`) #[derive(Clone, Debug, Default)] pub struct InsertTransactionBuilder { - governance_account: Option, - proposal_account: Option, - token_owner_record: Option, - governance_authority: Option, - proposal_transaction_account: Option, - payer: Option, - system_program: Option, - rent: Option, + governance_account: Option, + proposal_account: Option, + token_owner_record: Option, + governance_authority: Option, + proposal_transaction_account: Option, + payer: Option, + system_program: Option, + rent: Option, option_index: Option, index: Option, hold_up_time: Option, @@ -162,18 +160,18 @@ impl InsertTransactionBuilder { Self::default() } #[inline(always)] - pub fn governance_account(&mut self, governance_account: solana_pubkey::Pubkey) -> &mut Self { + pub fn governance_account(&mut self, governance_account: solana_address::Address) -> &mut Self { self.governance_account = Some(governance_account); self } #[inline(always)] - pub fn proposal_account(&mut self, proposal_account: solana_pubkey::Pubkey) -> &mut Self { + pub fn proposal_account(&mut self, proposal_account: solana_address::Address) -> &mut Self { self.proposal_account = Some(proposal_account); self } /// TokenOwnerRecord account of the Proposal owner #[inline(always)] - pub fn token_owner_record(&mut self, token_owner_record: solana_pubkey::Pubkey) -> &mut Self { + pub fn token_owner_record(&mut self, token_owner_record: solana_address::Address) -> &mut Self { self.token_owner_record = Some(token_owner_record); self } @@ -181,7 +179,7 @@ impl InsertTransactionBuilder { #[inline(always)] pub fn governance_authority( &mut self, - governance_authority: solana_pubkey::Pubkey, + governance_authority: solana_address::Address, ) -> &mut Self { self.governance_authority = Some(governance_authority); self @@ -190,25 +188,25 @@ impl InsertTransactionBuilder { #[inline(always)] pub fn proposal_transaction_account( &mut self, - proposal_transaction_account: solana_pubkey::Pubkey, + proposal_transaction_account: solana_address::Address, ) -> &mut Self { self.proposal_transaction_account = Some(proposal_transaction_account); self } #[inline(always)] - pub fn payer(&mut self, payer: solana_pubkey::Pubkey) -> &mut Self { + pub fn payer(&mut self, payer: solana_address::Address) -> &mut Self { self.payer = Some(payer); self } /// `[optional account, default to '11111111111111111111111111111111']` #[inline(always)] - pub fn system_program(&mut self, system_program: solana_pubkey::Pubkey) -> &mut Self { + pub fn system_program(&mut self, system_program: solana_address::Address) -> &mut Self { self.system_program = Some(system_program); self } /// `[optional account, default to 'SysvarRent111111111111111111111111111111111']` #[inline(always)] - pub fn rent(&mut self, rent: solana_pubkey::Pubkey) -> &mut Self { + pub fn rent(&mut self, rent: solana_address::Address) -> &mut Self { self.rent = Some(rent); self } @@ -266,8 +264,8 @@ impl InsertTransactionBuilder { payer: self.payer.expect("payer is not set"), system_program: self .system_program - .unwrap_or(solana_pubkey::pubkey!("11111111111111111111111111111111")), - rent: self.rent.unwrap_or(solana_pubkey::pubkey!( + .unwrap_or(solana_address::address!("11111111111111111111111111111111")), + rent: self.rent.unwrap_or(solana_address::address!( "SysvarRent111111111111111111111111111111111" )), }; diff --git a/e2e/governance/src/generated/instructions/legacy1.rs b/e2e/governance/src/generated/instructions/legacy1.rs index 9e155f0..db81623 100644 --- a/e2e/governance/src/generated/instructions/legacy1.rs +++ b/e2e/governance/src/generated/instructions/legacy1.rs @@ -37,7 +37,6 @@ impl Legacy1 { } #[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] -#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct Legacy1InstructionData { discriminator: u8, } diff --git a/e2e/governance/src/generated/instructions/refund_proposal_deposit.rs b/e2e/governance/src/generated/instructions/refund_proposal_deposit.rs index 9c672c1..3300dfe 100644 --- a/e2e/governance/src/generated/instructions/refund_proposal_deposit.rs +++ b/e2e/governance/src/generated/instructions/refund_proposal_deposit.rs @@ -13,11 +13,11 @@ pub const REFUND_PROPOSAL_DEPOSIT_DISCRIMINATOR: u8 = 27; /// Accounts. #[derive(Debug)] pub struct RefundProposalDeposit { - pub proposal_account: solana_pubkey::Pubkey, + pub proposal_account: solana_address::Address, /// PDA Seeds: ['proposal-deposit', proposal, deposit payer] - pub proposal_deposit_account: solana_pubkey::Pubkey, + pub proposal_deposit_account: solana_address::Address, /// Proposal Deposit Payer (beneficiary) account - pub proposal_deposit_payer: solana_pubkey::Pubkey, + pub proposal_deposit_payer: solana_address::Address, } impl RefundProposalDeposit { @@ -57,7 +57,6 @@ impl RefundProposalDeposit { } #[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] -#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct RefundProposalDepositInstructionData { discriminator: u8, } @@ -87,9 +86,9 @@ impl Default for RefundProposalDepositInstructionData { /// 2. `[writable]` proposal_deposit_payer #[derive(Clone, Debug, Default)] pub struct RefundProposalDepositBuilder { - proposal_account: Option, - proposal_deposit_account: Option, - proposal_deposit_payer: Option, + proposal_account: Option, + proposal_deposit_account: Option, + proposal_deposit_payer: Option, __remaining_accounts: Vec, } @@ -98,7 +97,7 @@ impl RefundProposalDepositBuilder { Self::default() } #[inline(always)] - pub fn proposal_account(&mut self, proposal_account: solana_pubkey::Pubkey) -> &mut Self { + pub fn proposal_account(&mut self, proposal_account: solana_address::Address) -> &mut Self { self.proposal_account = Some(proposal_account); self } @@ -106,7 +105,7 @@ impl RefundProposalDepositBuilder { #[inline(always)] pub fn proposal_deposit_account( &mut self, - proposal_deposit_account: solana_pubkey::Pubkey, + proposal_deposit_account: solana_address::Address, ) -> &mut Self { self.proposal_deposit_account = Some(proposal_deposit_account); self @@ -115,7 +114,7 @@ impl RefundProposalDepositBuilder { #[inline(always)] pub fn proposal_deposit_payer( &mut self, - proposal_deposit_payer: solana_pubkey::Pubkey, + proposal_deposit_payer: solana_address::Address, ) -> &mut Self { self.proposal_deposit_payer = Some(proposal_deposit_payer); self diff --git a/e2e/governance/src/generated/instructions/relinquish_vote.rs b/e2e/governance/src/generated/instructions/relinquish_vote.rs index 8721fc5..4eaa0d1 100644 --- a/e2e/governance/src/generated/instructions/relinquish_vote.rs +++ b/e2e/governance/src/generated/instructions/relinquish_vote.rs @@ -13,22 +13,22 @@ pub const RELINQUISH_VOTE_DISCRIMINATOR: u8 = 15; /// Accounts. #[derive(Debug)] pub struct RelinquishVote { - pub realm_account: solana_pubkey::Pubkey, + pub realm_account: solana_address::Address, - pub governance_account: solana_pubkey::Pubkey, + pub governance_account: solana_address::Address, - pub proposal_account: solana_pubkey::Pubkey, + pub proposal_account: solana_address::Address, /// TokenOwnerRecord account. PDA seeds: ['governance',realm, vote_governing_token_mint, governing_token_owner] - pub token_owner_record: solana_pubkey::Pubkey, + pub token_owner_record: solana_address::Address, /// Proposal VoteRecord account. PDA seeds: ['governance',proposal, token_owner_record] - pub proposal_vote_record: solana_pubkey::Pubkey, + pub proposal_vote_record: solana_address::Address, /// The Governing Token Mint which was used to cast the vote (vote_governing_token_mint) - pub governing_token_mint: solana_pubkey::Pubkey, + pub governing_token_mint: solana_address::Address, - pub governance_authority: Option, + pub governance_authority: Option, /// Optional Beneficiary account which would receive lamports when VoteRecord Account is disposed. /// It's required only when Proposal is still being voted on - pub beneficiary_account: Option, + pub beneficiary_account: Option, } impl RelinquishVote { @@ -100,7 +100,6 @@ impl RelinquishVote { } #[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] -#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct RelinquishVoteInstructionData { discriminator: u8, } @@ -135,14 +134,14 @@ impl Default for RelinquishVoteInstructionData { /// 7. `[writable, optional]` beneficiary_account #[derive(Clone, Debug, Default)] pub struct RelinquishVoteBuilder { - realm_account: Option, - governance_account: Option, - proposal_account: Option, - token_owner_record: Option, - proposal_vote_record: Option, - governing_token_mint: Option, - governance_authority: Option, - beneficiary_account: Option, + realm_account: Option, + governance_account: Option, + proposal_account: Option, + token_owner_record: Option, + proposal_vote_record: Option, + governing_token_mint: Option, + governance_authority: Option, + beneficiary_account: Option, __remaining_accounts: Vec, } @@ -151,23 +150,23 @@ impl RelinquishVoteBuilder { Self::default() } #[inline(always)] - pub fn realm_account(&mut self, realm_account: solana_pubkey::Pubkey) -> &mut Self { + pub fn realm_account(&mut self, realm_account: solana_address::Address) -> &mut Self { self.realm_account = Some(realm_account); self } #[inline(always)] - pub fn governance_account(&mut self, governance_account: solana_pubkey::Pubkey) -> &mut Self { + pub fn governance_account(&mut self, governance_account: solana_address::Address) -> &mut Self { self.governance_account = Some(governance_account); self } #[inline(always)] - pub fn proposal_account(&mut self, proposal_account: solana_pubkey::Pubkey) -> &mut Self { + pub fn proposal_account(&mut self, proposal_account: solana_address::Address) -> &mut Self { self.proposal_account = Some(proposal_account); self } /// TokenOwnerRecord account. PDA seeds: ['governance',realm, vote_governing_token_mint, governing_token_owner] #[inline(always)] - pub fn token_owner_record(&mut self, token_owner_record: solana_pubkey::Pubkey) -> &mut Self { + pub fn token_owner_record(&mut self, token_owner_record: solana_address::Address) -> &mut Self { self.token_owner_record = Some(token_owner_record); self } @@ -175,7 +174,7 @@ impl RelinquishVoteBuilder { #[inline(always)] pub fn proposal_vote_record( &mut self, - proposal_vote_record: solana_pubkey::Pubkey, + proposal_vote_record: solana_address::Address, ) -> &mut Self { self.proposal_vote_record = Some(proposal_vote_record); self @@ -184,7 +183,7 @@ impl RelinquishVoteBuilder { #[inline(always)] pub fn governing_token_mint( &mut self, - governing_token_mint: solana_pubkey::Pubkey, + governing_token_mint: solana_address::Address, ) -> &mut Self { self.governing_token_mint = Some(governing_token_mint); self @@ -193,7 +192,7 @@ impl RelinquishVoteBuilder { #[inline(always)] pub fn governance_authority( &mut self, - governance_authority: Option, + governance_authority: Option, ) -> &mut Self { self.governance_authority = governance_authority; self @@ -204,7 +203,7 @@ impl RelinquishVoteBuilder { #[inline(always)] pub fn beneficiary_account( &mut self, - beneficiary_account: Option, + beneficiary_account: Option, ) -> &mut Self { self.beneficiary_account = beneficiary_account; self diff --git a/e2e/governance/src/generated/instructions/remove_required_signatory.rs b/e2e/governance/src/generated/instructions/remove_required_signatory.rs index 8b8367d..180efe0 100644 --- a/e2e/governance/src/generated/instructions/remove_required_signatory.rs +++ b/e2e/governance/src/generated/instructions/remove_required_signatory.rs @@ -13,11 +13,11 @@ pub const REMOVE_REQUIRED_SIGNATORY_DISCRIMINATOR: u8 = 30; /// Accounts. #[derive(Debug)] pub struct RemoveRequiredSignatory { - pub governance_account: solana_pubkey::Pubkey, + pub governance_account: solana_address::Address, - pub required_signatory_account: solana_pubkey::Pubkey, + pub required_signatory_account: solana_address::Address, /// Beneficiary Account which would receive lamports from the disposed RequiredSignatory Account - pub beneficiary_account: solana_pubkey::Pubkey, + pub beneficiary_account: solana_address::Address, } impl RemoveRequiredSignatory { @@ -57,7 +57,6 @@ impl RemoveRequiredSignatory { } #[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] -#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct RemoveRequiredSignatoryInstructionData { discriminator: u8, } @@ -87,9 +86,9 @@ impl Default for RemoveRequiredSignatoryInstructionData { /// 2. `[writable]` beneficiary_account #[derive(Clone, Debug, Default)] pub struct RemoveRequiredSignatoryBuilder { - governance_account: Option, - required_signatory_account: Option, - beneficiary_account: Option, + governance_account: Option, + required_signatory_account: Option, + beneficiary_account: Option, __remaining_accounts: Vec, } @@ -98,21 +97,24 @@ impl RemoveRequiredSignatoryBuilder { Self::default() } #[inline(always)] - pub fn governance_account(&mut self, governance_account: solana_pubkey::Pubkey) -> &mut Self { + pub fn governance_account(&mut self, governance_account: solana_address::Address) -> &mut Self { self.governance_account = Some(governance_account); self } #[inline(always)] pub fn required_signatory_account( &mut self, - required_signatory_account: solana_pubkey::Pubkey, + required_signatory_account: solana_address::Address, ) -> &mut Self { self.required_signatory_account = Some(required_signatory_account); self } /// Beneficiary Account which would receive lamports from the disposed RequiredSignatory Account #[inline(always)] - pub fn beneficiary_account(&mut self, beneficiary_account: solana_pubkey::Pubkey) -> &mut Self { + pub fn beneficiary_account( + &mut self, + beneficiary_account: solana_address::Address, + ) -> &mut Self { self.beneficiary_account = Some(beneficiary_account); self } diff --git a/e2e/governance/src/generated/instructions/remove_transaction.rs b/e2e/governance/src/generated/instructions/remove_transaction.rs index 7188295..9afdeb5 100644 --- a/e2e/governance/src/generated/instructions/remove_transaction.rs +++ b/e2e/governance/src/generated/instructions/remove_transaction.rs @@ -13,15 +13,15 @@ pub const REMOVE_TRANSACTION_DISCRIMINATOR: u8 = 10; /// Accounts. #[derive(Debug)] pub struct RemoveTransaction { - pub proposal_account: solana_pubkey::Pubkey, + pub proposal_account: solana_address::Address, /// TokenOwnerRecord account of the Proposal owner - pub token_owner_record: solana_pubkey::Pubkey, + pub token_owner_record: solana_address::Address, /// Governance Authority (Token Owner or Governance Delegate) - pub governance_authority: solana_pubkey::Pubkey, + pub governance_authority: solana_address::Address, - pub proposal_transaction_account: solana_pubkey::Pubkey, + pub proposal_transaction_account: solana_address::Address, /// Beneficiary Account which would receive lamports from the disposed ProposalTransaction account - pub beneficiary_account: solana_pubkey::Pubkey, + pub beneficiary_account: solana_address::Address, } impl RemoveTransaction { @@ -69,7 +69,6 @@ impl RemoveTransaction { } #[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] -#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct RemoveTransactionInstructionData { discriminator: u8, } @@ -101,11 +100,11 @@ impl Default for RemoveTransactionInstructionData { /// 4. `[writable]` beneficiary_account #[derive(Clone, Debug, Default)] pub struct RemoveTransactionBuilder { - proposal_account: Option, - token_owner_record: Option, - governance_authority: Option, - proposal_transaction_account: Option, - beneficiary_account: Option, + proposal_account: Option, + token_owner_record: Option, + governance_authority: Option, + proposal_transaction_account: Option, + beneficiary_account: Option, __remaining_accounts: Vec, } @@ -114,13 +113,13 @@ impl RemoveTransactionBuilder { Self::default() } #[inline(always)] - pub fn proposal_account(&mut self, proposal_account: solana_pubkey::Pubkey) -> &mut Self { + pub fn proposal_account(&mut self, proposal_account: solana_address::Address) -> &mut Self { self.proposal_account = Some(proposal_account); self } /// TokenOwnerRecord account of the Proposal owner #[inline(always)] - pub fn token_owner_record(&mut self, token_owner_record: solana_pubkey::Pubkey) -> &mut Self { + pub fn token_owner_record(&mut self, token_owner_record: solana_address::Address) -> &mut Self { self.token_owner_record = Some(token_owner_record); self } @@ -128,7 +127,7 @@ impl RemoveTransactionBuilder { #[inline(always)] pub fn governance_authority( &mut self, - governance_authority: solana_pubkey::Pubkey, + governance_authority: solana_address::Address, ) -> &mut Self { self.governance_authority = Some(governance_authority); self @@ -136,14 +135,17 @@ impl RemoveTransactionBuilder { #[inline(always)] pub fn proposal_transaction_account( &mut self, - proposal_transaction_account: solana_pubkey::Pubkey, + proposal_transaction_account: solana_address::Address, ) -> &mut Self { self.proposal_transaction_account = Some(proposal_transaction_account); self } /// Beneficiary Account which would receive lamports from the disposed ProposalTransaction account #[inline(always)] - pub fn beneficiary_account(&mut self, beneficiary_account: solana_pubkey::Pubkey) -> &mut Self { + pub fn beneficiary_account( + &mut self, + beneficiary_account: solana_address::Address, + ) -> &mut Self { self.beneficiary_account = Some(beneficiary_account); self } diff --git a/e2e/governance/src/generated/instructions/revoke_governing_tokens.rs b/e2e/governance/src/generated/instructions/revoke_governing_tokens.rs index 2f09cb0..aa382c4 100644 --- a/e2e/governance/src/generated/instructions/revoke_governing_tokens.rs +++ b/e2e/governance/src/generated/instructions/revoke_governing_tokens.rs @@ -13,19 +13,19 @@ pub const REVOKE_GOVERNING_TOKENS_DISCRIMINATOR: u8 = 26; /// Accounts. #[derive(Debug)] pub struct RevokeGoverningTokens { - pub realm_account: solana_pubkey::Pubkey, + pub realm_account: solana_address::Address, /// seeds=['governance', realm, governing_token_mint] - pub governing_token_holding_account: solana_pubkey::Pubkey, + pub governing_token_holding_account: solana_address::Address, /// seeds=['governance', realm, governing_token_mint, governing_token_owner] - pub token_owner_record: solana_pubkey::Pubkey, + pub token_owner_record: solana_address::Address, - pub governing_token_mint: solana_pubkey::Pubkey, + pub governing_token_mint: solana_address::Address, /// GoverningTokenMint mint_authority - pub governing_token_mint_authority_or_token_owner: solana_pubkey::Pubkey, + pub governing_token_mint_authority_or_token_owner: solana_address::Address, /// seeds=['realm-config', realm] - pub realm_config_account: solana_pubkey::Pubkey, + pub realm_config_account: solana_address::Address, - pub token_program: solana_pubkey::Pubkey, + pub token_program: solana_address::Address, } impl RevokeGoverningTokens { @@ -87,7 +87,6 @@ impl RevokeGoverningTokens { } #[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] -#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct RevokeGoverningTokensInstructionData { discriminator: u8, } @@ -109,7 +108,6 @@ impl Default for RevokeGoverningTokensInstructionData { } #[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] -#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct RevokeGoverningTokensInstructionArgs { pub amount: u64, } @@ -133,13 +131,13 @@ impl RevokeGoverningTokensInstructionArgs { /// 6. `[optional]` token_program (default to `TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA`) #[derive(Clone, Debug, Default)] pub struct RevokeGoverningTokensBuilder { - realm_account: Option, - governing_token_holding_account: Option, - token_owner_record: Option, - governing_token_mint: Option, - governing_token_mint_authority_or_token_owner: Option, - realm_config_account: Option, - token_program: Option, + realm_account: Option, + governing_token_holding_account: Option, + token_owner_record: Option, + governing_token_mint: Option, + governing_token_mint_authority_or_token_owner: Option, + realm_config_account: Option, + token_program: Option, amount: Option, __remaining_accounts: Vec, } @@ -149,7 +147,7 @@ impl RevokeGoverningTokensBuilder { Self::default() } #[inline(always)] - pub fn realm_account(&mut self, realm_account: solana_pubkey::Pubkey) -> &mut Self { + pub fn realm_account(&mut self, realm_account: solana_address::Address) -> &mut Self { self.realm_account = Some(realm_account); self } @@ -157,21 +155,21 @@ impl RevokeGoverningTokensBuilder { #[inline(always)] pub fn governing_token_holding_account( &mut self, - governing_token_holding_account: solana_pubkey::Pubkey, + governing_token_holding_account: solana_address::Address, ) -> &mut Self { self.governing_token_holding_account = Some(governing_token_holding_account); self } /// seeds=['governance', realm, governing_token_mint, governing_token_owner] #[inline(always)] - pub fn token_owner_record(&mut self, token_owner_record: solana_pubkey::Pubkey) -> &mut Self { + pub fn token_owner_record(&mut self, token_owner_record: solana_address::Address) -> &mut Self { self.token_owner_record = Some(token_owner_record); self } #[inline(always)] pub fn governing_token_mint( &mut self, - governing_token_mint: solana_pubkey::Pubkey, + governing_token_mint: solana_address::Address, ) -> &mut Self { self.governing_token_mint = Some(governing_token_mint); self @@ -180,7 +178,7 @@ impl RevokeGoverningTokensBuilder { #[inline(always)] pub fn governing_token_mint_authority_or_token_owner( &mut self, - governing_token_mint_authority_or_token_owner: solana_pubkey::Pubkey, + governing_token_mint_authority_or_token_owner: solana_address::Address, ) -> &mut Self { self.governing_token_mint_authority_or_token_owner = Some(governing_token_mint_authority_or_token_owner); @@ -190,14 +188,14 @@ impl RevokeGoverningTokensBuilder { #[inline(always)] pub fn realm_config_account( &mut self, - realm_config_account: solana_pubkey::Pubkey, + realm_config_account: solana_address::Address, ) -> &mut Self { self.realm_config_account = Some(realm_config_account); self } /// `[optional account, default to 'TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA']` #[inline(always)] - pub fn token_program(&mut self, token_program: solana_pubkey::Pubkey) -> &mut Self { + pub fn token_program(&mut self, token_program: solana_address::Address) -> &mut Self { self.token_program = Some(token_program); self } @@ -240,7 +238,7 @@ impl RevokeGoverningTokensBuilder { realm_config_account: self .realm_config_account .expect("realm_config_account is not set"), - token_program: self.token_program.unwrap_or(solana_pubkey::pubkey!( + token_program: self.token_program.unwrap_or(solana_address::address!( "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA" )), }; diff --git a/e2e/governance/src/generated/instructions/set_governance_config.rs b/e2e/governance/src/generated/instructions/set_governance_config.rs index 99ec8f7..3fe2df3 100644 --- a/e2e/governance/src/generated/instructions/set_governance_config.rs +++ b/e2e/governance/src/generated/instructions/set_governance_config.rs @@ -15,7 +15,7 @@ pub const SET_GOVERNANCE_CONFIG_DISCRIMINATOR: u8 = 19; #[derive(Debug)] pub struct SetGovernanceConfig { /// The governance account the config is for - pub governance_account: solana_pubkey::Pubkey, + pub governance_account: solana_address::Address, } impl SetGovernanceConfig { @@ -53,7 +53,6 @@ impl SetGovernanceConfig { } #[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] -#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct SetGovernanceConfigInstructionData { discriminator: u8, } @@ -75,7 +74,6 @@ impl Default for SetGovernanceConfigInstructionData { } #[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] -#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct SetGovernanceConfigInstructionArgs { pub config: GovernanceConfig, } @@ -93,7 +91,7 @@ impl SetGovernanceConfigInstructionArgs { /// 0. `[writable, signer]` governance_account #[derive(Clone, Debug, Default)] pub struct SetGovernanceConfigBuilder { - governance_account: Option, + governance_account: Option, config: Option, __remaining_accounts: Vec, } @@ -104,7 +102,7 @@ impl SetGovernanceConfigBuilder { } /// The governance account the config is for #[inline(always)] - pub fn governance_account(&mut self, governance_account: solana_pubkey::Pubkey) -> &mut Self { + pub fn governance_account(&mut self, governance_account: solana_address::Address) -> &mut Self { self.governance_account = Some(governance_account); self } diff --git a/e2e/governance/src/generated/instructions/set_governance_delegate.rs b/e2e/governance/src/generated/instructions/set_governance_delegate.rs index d542369..1d6c050 100644 --- a/e2e/governance/src/generated/instructions/set_governance_delegate.rs +++ b/e2e/governance/src/generated/instructions/set_governance_delegate.rs @@ -7,7 +7,7 @@ use borsh::BorshDeserialize; use borsh::BorshSerialize; -use solana_pubkey::Pubkey; +use solana_address::Address; pub const SET_GOVERNANCE_DELEGATE_DISCRIMINATOR: u8 = 3; @@ -15,9 +15,9 @@ pub const SET_GOVERNANCE_DELEGATE_DISCRIMINATOR: u8 = 3; #[derive(Debug)] pub struct SetGovernanceDelegate { /// Current governance delegate or governing token owner - pub current_delegate_or_owner: solana_pubkey::Pubkey, + pub current_delegate_or_owner: solana_address::Address, - pub token_owner_record: solana_pubkey::Pubkey, + pub token_owner_record: solana_address::Address, } impl SetGovernanceDelegate { @@ -59,7 +59,6 @@ impl SetGovernanceDelegate { } #[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] -#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct SetGovernanceDelegateInstructionData { discriminator: u8, } @@ -81,9 +80,8 @@ impl Default for SetGovernanceDelegateInstructionData { } #[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] -#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct SetGovernanceDelegateInstructionArgs { - pub new_governance_delegate: Option, + pub new_governance_delegate: Option
, } impl SetGovernanceDelegateInstructionArgs { @@ -100,9 +98,9 @@ impl SetGovernanceDelegateInstructionArgs { /// 1. `[writable]` token_owner_record #[derive(Clone, Debug, Default)] pub struct SetGovernanceDelegateBuilder { - current_delegate_or_owner: Option, - token_owner_record: Option, - new_governance_delegate: Option, + current_delegate_or_owner: Option, + token_owner_record: Option, + new_governance_delegate: Option
, __remaining_accounts: Vec, } @@ -114,19 +112,19 @@ impl SetGovernanceDelegateBuilder { #[inline(always)] pub fn current_delegate_or_owner( &mut self, - current_delegate_or_owner: solana_pubkey::Pubkey, + current_delegate_or_owner: solana_address::Address, ) -> &mut Self { self.current_delegate_or_owner = Some(current_delegate_or_owner); self } #[inline(always)] - pub fn token_owner_record(&mut self, token_owner_record: solana_pubkey::Pubkey) -> &mut Self { + pub fn token_owner_record(&mut self, token_owner_record: solana_address::Address) -> &mut Self { self.token_owner_record = Some(token_owner_record); self } /// `[optional argument]` #[inline(always)] - pub fn new_governance_delegate(&mut self, new_governance_delegate: Pubkey) -> &mut Self { + pub fn new_governance_delegate(&mut self, new_governance_delegate: Address) -> &mut Self { self.new_governance_delegate = Some(new_governance_delegate); self } @@ -303,7 +301,7 @@ impl<'a, 'b> SetGovernanceDelegateCpiBuilder<'a, 'b> { } /// `[optional argument]` #[inline(always)] - pub fn new_governance_delegate(&mut self, new_governance_delegate: Pubkey) -> &mut Self { + pub fn new_governance_delegate(&mut self, new_governance_delegate: Address) -> &mut Self { self.instruction.new_governance_delegate = Some(new_governance_delegate); self } @@ -370,7 +368,7 @@ struct SetGovernanceDelegateCpiBuilderInstruction<'a, 'b> { __program: &'b solana_account_info::AccountInfo<'a>, current_delegate_or_owner: Option<&'b solana_account_info::AccountInfo<'a>>, token_owner_record: Option<&'b solana_account_info::AccountInfo<'a>>, - new_governance_delegate: Option, + new_governance_delegate: Option
, /// Additional instruction accounts `(AccountInfo, is_writable, is_signer)`. __remaining_accounts: Vec<(&'b solana_account_info::AccountInfo<'a>, bool, bool)>, } diff --git a/e2e/governance/src/generated/instructions/set_realm_authority.rs b/e2e/governance/src/generated/instructions/set_realm_authority.rs index eeb20a8..ef11a15 100644 --- a/e2e/governance/src/generated/instructions/set_realm_authority.rs +++ b/e2e/governance/src/generated/instructions/set_realm_authority.rs @@ -14,11 +14,11 @@ pub const SET_REALM_AUTHORITY_DISCRIMINATOR: u8 = 21; /// Accounts. #[derive(Debug)] pub struct SetRealmAuthority { - pub realm_account: solana_pubkey::Pubkey, + pub realm_account: solana_address::Address, - pub realm_authority: solana_pubkey::Pubkey, + pub realm_authority: solana_address::Address, /// Must be one of the realm governances when set - pub new_realm_authority: Option, + pub new_realm_authority: Option, } impl SetRealmAuthority { @@ -71,7 +71,6 @@ impl SetRealmAuthority { } #[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] -#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct SetRealmAuthorityInstructionData { discriminator: u8, } @@ -93,7 +92,6 @@ impl Default for SetRealmAuthorityInstructionData { } #[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] -#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct SetRealmAuthorityInstructionArgs { pub action: SetRealmAuthorityAction, } @@ -113,9 +111,9 @@ impl SetRealmAuthorityInstructionArgs { /// 2. `[optional]` new_realm_authority #[derive(Clone, Debug, Default)] pub struct SetRealmAuthorityBuilder { - realm_account: Option, - realm_authority: Option, - new_realm_authority: Option, + realm_account: Option, + realm_authority: Option, + new_realm_authority: Option, action: Option, __remaining_accounts: Vec, } @@ -125,12 +123,12 @@ impl SetRealmAuthorityBuilder { Self::default() } #[inline(always)] - pub fn realm_account(&mut self, realm_account: solana_pubkey::Pubkey) -> &mut Self { + pub fn realm_account(&mut self, realm_account: solana_address::Address) -> &mut Self { self.realm_account = Some(realm_account); self } #[inline(always)] - pub fn realm_authority(&mut self, realm_authority: solana_pubkey::Pubkey) -> &mut Self { + pub fn realm_authority(&mut self, realm_authority: solana_address::Address) -> &mut Self { self.realm_authority = Some(realm_authority); self } @@ -139,7 +137,7 @@ impl SetRealmAuthorityBuilder { #[inline(always)] pub fn new_realm_authority( &mut self, - new_realm_authority: Option, + new_realm_authority: Option, ) -> &mut Self { self.new_realm_authority = new_realm_authority; self diff --git a/e2e/governance/src/generated/instructions/set_realm_config.rs b/e2e/governance/src/generated/instructions/set_realm_config.rs index ab27076..82554fd 100644 --- a/e2e/governance/src/generated/instructions/set_realm_config.rs +++ b/e2e/governance/src/generated/instructions/set_realm_config.rs @@ -14,30 +14,30 @@ pub const SET_REALM_CONFIG_DISCRIMINATOR: u8 = 22; /// Accounts. #[derive(Debug)] pub struct SetRealmConfig { - pub realm_account: solana_pubkey::Pubkey, + pub realm_account: solana_address::Address, - pub realm_authority: solana_pubkey::Pubkey, + pub realm_authority: solana_address::Address, /// Council Token Mint - optional. /// Note: In the current version it's only possible to remove council mint (set it to None) /// After setting council to None it won't be possible to withdraw the tokens from the Realm any longer. /// If that's required then it must be done before executing this instruction - pub council_token_mint: Option, + pub council_token_mint: Option, /// Optional unless council is used. seeds=['governance', realm, council_mint] - pub council_token_holding_account: Option, + pub council_token_holding_account: Option, - pub system_program: solana_pubkey::Pubkey, + pub system_program: solana_address::Address, /// RealmConfig account. seeds=['realm-config', realm] - pub realm_config: solana_pubkey::Pubkey, + pub realm_config: solana_address::Address, /// Optional Community Voter Weight Addin Program Id - pub community_voter_weight_addin_program_id: Option, + pub community_voter_weight_addin_program_id: Option, /// Optional Max Community Voter Weight Addin Program Id - pub max_community_voter_weight_addin_program_id: Option, + pub max_community_voter_weight_addin_program_id: Option, /// Optional Council Voter Weight Adding Program Id - pub council_voter_weight_addin_program_id: Option, + pub council_voter_weight_addin_program_id: Option, /// Optional Max Council Voter Weight Addin Program Id - pub max_council_voter_weight_addin_program_id: Option, + pub max_council_voter_weight_addin_program_id: Option, /// Optional Payer. Required if RealmConfig doesn't exist and needs to be created - pub payer: Option, + pub payer: Option, } impl SetRealmConfig { @@ -167,7 +167,6 @@ impl SetRealmConfig { } #[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] -#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct SetRealmConfigInstructionData { discriminator: u8, } @@ -189,7 +188,6 @@ impl Default for SetRealmConfigInstructionData { } #[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] -#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct SetRealmConfigInstructionArgs { pub config_args: RealmConfigParams, } @@ -217,17 +215,17 @@ impl SetRealmConfigInstructionArgs { /// 10. `[signer, optional]` payer #[derive(Clone, Debug, Default)] pub struct SetRealmConfigBuilder { - realm_account: Option, - realm_authority: Option, - council_token_mint: Option, - council_token_holding_account: Option, - system_program: Option, - realm_config: Option, - community_voter_weight_addin_program_id: Option, - max_community_voter_weight_addin_program_id: Option, - council_voter_weight_addin_program_id: Option, - max_council_voter_weight_addin_program_id: Option, - payer: Option, + realm_account: Option, + realm_authority: Option, + council_token_mint: Option, + council_token_holding_account: Option, + system_program: Option, + realm_config: Option, + community_voter_weight_addin_program_id: Option, + max_community_voter_weight_addin_program_id: Option, + council_voter_weight_addin_program_id: Option, + max_council_voter_weight_addin_program_id: Option, + payer: Option, config_args: Option, __remaining_accounts: Vec, } @@ -237,12 +235,12 @@ impl SetRealmConfigBuilder { Self::default() } #[inline(always)] - pub fn realm_account(&mut self, realm_account: solana_pubkey::Pubkey) -> &mut Self { + pub fn realm_account(&mut self, realm_account: solana_address::Address) -> &mut Self { self.realm_account = Some(realm_account); self } #[inline(always)] - pub fn realm_authority(&mut self, realm_authority: solana_pubkey::Pubkey) -> &mut Self { + pub fn realm_authority(&mut self, realm_authority: solana_address::Address) -> &mut Self { self.realm_authority = Some(realm_authority); self } @@ -254,7 +252,7 @@ impl SetRealmConfigBuilder { #[inline(always)] pub fn council_token_mint( &mut self, - council_token_mint: Option, + council_token_mint: Option, ) -> &mut Self { self.council_token_mint = council_token_mint; self @@ -264,20 +262,20 @@ impl SetRealmConfigBuilder { #[inline(always)] pub fn council_token_holding_account( &mut self, - council_token_holding_account: Option, + council_token_holding_account: Option, ) -> &mut Self { self.council_token_holding_account = council_token_holding_account; self } /// `[optional account, default to '11111111111111111111111111111111']` #[inline(always)] - pub fn system_program(&mut self, system_program: solana_pubkey::Pubkey) -> &mut Self { + pub fn system_program(&mut self, system_program: solana_address::Address) -> &mut Self { self.system_program = Some(system_program); self } /// RealmConfig account. seeds=['realm-config', realm] #[inline(always)] - pub fn realm_config(&mut self, realm_config: solana_pubkey::Pubkey) -> &mut Self { + pub fn realm_config(&mut self, realm_config: solana_address::Address) -> &mut Self { self.realm_config = Some(realm_config); self } @@ -286,7 +284,7 @@ impl SetRealmConfigBuilder { #[inline(always)] pub fn community_voter_weight_addin_program_id( &mut self, - community_voter_weight_addin_program_id: Option, + community_voter_weight_addin_program_id: Option, ) -> &mut Self { self.community_voter_weight_addin_program_id = community_voter_weight_addin_program_id; self @@ -296,7 +294,7 @@ impl SetRealmConfigBuilder { #[inline(always)] pub fn max_community_voter_weight_addin_program_id( &mut self, - max_community_voter_weight_addin_program_id: Option, + max_community_voter_weight_addin_program_id: Option, ) -> &mut Self { self.max_community_voter_weight_addin_program_id = max_community_voter_weight_addin_program_id; @@ -307,7 +305,7 @@ impl SetRealmConfigBuilder { #[inline(always)] pub fn council_voter_weight_addin_program_id( &mut self, - council_voter_weight_addin_program_id: Option, + council_voter_weight_addin_program_id: Option, ) -> &mut Self { self.council_voter_weight_addin_program_id = council_voter_weight_addin_program_id; self @@ -317,7 +315,7 @@ impl SetRealmConfigBuilder { #[inline(always)] pub fn max_council_voter_weight_addin_program_id( &mut self, - max_council_voter_weight_addin_program_id: Option, + max_council_voter_weight_addin_program_id: Option, ) -> &mut Self { self.max_council_voter_weight_addin_program_id = max_council_voter_weight_addin_program_id; self @@ -325,7 +323,7 @@ impl SetRealmConfigBuilder { /// `[optional account]` /// Optional Payer. Required if RealmConfig doesn't exist and needs to be created #[inline(always)] - pub fn payer(&mut self, payer: Option) -> &mut Self { + pub fn payer(&mut self, payer: Option) -> &mut Self { self.payer = payer; self } @@ -358,7 +356,7 @@ impl SetRealmConfigBuilder { council_token_holding_account: self.council_token_holding_account, system_program: self .system_program - .unwrap_or(solana_pubkey::pubkey!("11111111111111111111111111111111")), + .unwrap_or(solana_address::address!("11111111111111111111111111111111")), realm_config: self.realm_config.expect("realm_config is not set"), community_voter_weight_addin_program_id: self.community_voter_weight_addin_program_id, max_community_voter_weight_addin_program_id: self diff --git a/e2e/governance/src/generated/instructions/sign_off_proposal.rs b/e2e/governance/src/generated/instructions/sign_off_proposal.rs index 436fa66..39e9483 100644 --- a/e2e/governance/src/generated/instructions/sign_off_proposal.rs +++ b/e2e/governance/src/generated/instructions/sign_off_proposal.rs @@ -13,17 +13,17 @@ pub const SIGN_OFF_PROPOSAL_DISCRIMINATOR: u8 = 12; /// Accounts. #[derive(Debug)] pub struct SignOffProposal { - pub realm_account: solana_pubkey::Pubkey, + pub realm_account: solana_address::Address, - pub governance_account: solana_pubkey::Pubkey, + pub governance_account: solana_address::Address, - pub proposal_account: solana_pubkey::Pubkey, + pub proposal_account: solana_address::Address, /// Signatory account signing off the Proposal. /// Or Proposal owner if the owner hasn't appointed any signatories - pub signatory_account: solana_pubkey::Pubkey, + pub signatory_account: solana_address::Address, /// TokenOwnerRecord for the Proposal owner, required when the owner signs off the Proposal. /// Or `[writable]` SignatoryRecord account, required when non owner signs off the Proposal - pub token_owner_record: solana_pubkey::Pubkey, + pub token_owner_record: solana_address::Address, } impl SignOffProposal { @@ -69,7 +69,6 @@ impl SignOffProposal { } #[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] -#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct SignOffProposalInstructionData { discriminator: u8, } @@ -101,11 +100,11 @@ impl Default for SignOffProposalInstructionData { /// 4. `[writable]` token_owner_record #[derive(Clone, Debug, Default)] pub struct SignOffProposalBuilder { - realm_account: Option, - governance_account: Option, - proposal_account: Option, - signatory_account: Option, - token_owner_record: Option, + realm_account: Option, + governance_account: Option, + proposal_account: Option, + signatory_account: Option, + token_owner_record: Option, __remaining_accounts: Vec, } @@ -114,31 +113,31 @@ impl SignOffProposalBuilder { Self::default() } #[inline(always)] - pub fn realm_account(&mut self, realm_account: solana_pubkey::Pubkey) -> &mut Self { + pub fn realm_account(&mut self, realm_account: solana_address::Address) -> &mut Self { self.realm_account = Some(realm_account); self } #[inline(always)] - pub fn governance_account(&mut self, governance_account: solana_pubkey::Pubkey) -> &mut Self { + pub fn governance_account(&mut self, governance_account: solana_address::Address) -> &mut Self { self.governance_account = Some(governance_account); self } #[inline(always)] - pub fn proposal_account(&mut self, proposal_account: solana_pubkey::Pubkey) -> &mut Self { + pub fn proposal_account(&mut self, proposal_account: solana_address::Address) -> &mut Self { self.proposal_account = Some(proposal_account); self } /// Signatory account signing off the Proposal. /// Or Proposal owner if the owner hasn't appointed any signatories #[inline(always)] - pub fn signatory_account(&mut self, signatory_account: solana_pubkey::Pubkey) -> &mut Self { + pub fn signatory_account(&mut self, signatory_account: solana_address::Address) -> &mut Self { self.signatory_account = Some(signatory_account); self } /// TokenOwnerRecord for the Proposal owner, required when the owner signs off the Proposal. /// Or `[writable]` SignatoryRecord account, required when non owner signs off the Proposal #[inline(always)] - pub fn token_owner_record(&mut self, token_owner_record: solana_pubkey::Pubkey) -> &mut Self { + pub fn token_owner_record(&mut self, token_owner_record: solana_address::Address) -> &mut Self { self.token_owner_record = Some(token_owner_record); self } diff --git a/e2e/governance/src/generated/instructions/update_program_metadata.rs b/e2e/governance/src/generated/instructions/update_program_metadata.rs index fbb3cfa..54a07c4 100644 --- a/e2e/governance/src/generated/instructions/update_program_metadata.rs +++ b/e2e/governance/src/generated/instructions/update_program_metadata.rs @@ -14,11 +14,11 @@ pub const UPDATE_PROGRAM_METADATA_DISCRIMINATOR: u8 = 24; #[derive(Debug)] pub struct UpdateProgramMetadata { /// seeds=['metadata'] - pub program_metadata_account: solana_pubkey::Pubkey, + pub program_metadata_account: solana_address::Address, - pub payer: solana_pubkey::Pubkey, + pub payer: solana_address::Address, - pub system_program: solana_pubkey::Pubkey, + pub system_program: solana_address::Address, } impl UpdateProgramMetadata { @@ -57,7 +57,6 @@ impl UpdateProgramMetadata { } #[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] -#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct UpdateProgramMetadataInstructionData { discriminator: u8, } @@ -87,9 +86,9 @@ impl Default for UpdateProgramMetadataInstructionData { /// 2. `[optional]` system_program (default to `11111111111111111111111111111111`) #[derive(Clone, Debug, Default)] pub struct UpdateProgramMetadataBuilder { - program_metadata_account: Option, - payer: Option, - system_program: Option, + program_metadata_account: Option, + payer: Option, + system_program: Option, __remaining_accounts: Vec, } @@ -101,19 +100,19 @@ impl UpdateProgramMetadataBuilder { #[inline(always)] pub fn program_metadata_account( &mut self, - program_metadata_account: solana_pubkey::Pubkey, + program_metadata_account: solana_address::Address, ) -> &mut Self { self.program_metadata_account = Some(program_metadata_account); self } #[inline(always)] - pub fn payer(&mut self, payer: solana_pubkey::Pubkey) -> &mut Self { + pub fn payer(&mut self, payer: solana_address::Address) -> &mut Self { self.payer = Some(payer); self } /// `[optional account, default to '11111111111111111111111111111111']` #[inline(always)] - pub fn system_program(&mut self, system_program: solana_pubkey::Pubkey) -> &mut Self { + pub fn system_program(&mut self, system_program: solana_address::Address) -> &mut Self { self.system_program = Some(system_program); self } @@ -141,7 +140,7 @@ impl UpdateProgramMetadataBuilder { payer: self.payer.expect("payer is not set"), system_program: self .system_program - .unwrap_or(solana_pubkey::pubkey!("11111111111111111111111111111111")), + .unwrap_or(solana_address::address!("11111111111111111111111111111111")), }; accounts.instruction_with_remaining_accounts(&self.__remaining_accounts) diff --git a/e2e/governance/src/generated/instructions/withdraw_governing_tokens.rs b/e2e/governance/src/generated/instructions/withdraw_governing_tokens.rs index 434989f..8a2cbe0 100644 --- a/e2e/governance/src/generated/instructions/withdraw_governing_tokens.rs +++ b/e2e/governance/src/generated/instructions/withdraw_governing_tokens.rs @@ -13,19 +13,19 @@ pub const WITHDRAW_GOVERNING_TOKENS_DISCRIMINATOR: u8 = 2; /// Accounts. #[derive(Debug)] pub struct WithdrawGoverningTokens { - pub realm_account: solana_pubkey::Pubkey, + pub realm_account: solana_address::Address, /// seeds=['governance', realm, governing_token_mint] - pub governing_token_holding_account: solana_pubkey::Pubkey, + pub governing_token_holding_account: solana_address::Address, /// All tokens will be transferred to this account - pub governing_token_destination_account: solana_pubkey::Pubkey, + pub governing_token_destination_account: solana_address::Address, - pub governing_token_owner_account: solana_pubkey::Pubkey, + pub governing_token_owner_account: solana_address::Address, /// seeds=['governance',realm, governing_token_mint, governing_token_owner] - pub token_owner_record: solana_pubkey::Pubkey, + pub token_owner_record: solana_address::Address, - pub token_program: solana_pubkey::Pubkey, + pub token_program: solana_address::Address, /// seeds=['realm-config', realm] - pub realm_config_account: solana_pubkey::Pubkey, + pub realm_config_account: solana_address::Address, } impl WithdrawGoverningTokens { @@ -81,7 +81,6 @@ impl WithdrawGoverningTokens { } #[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] -#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct WithdrawGoverningTokensInstructionData { discriminator: u8, } @@ -115,13 +114,13 @@ impl Default for WithdrawGoverningTokensInstructionData { /// 6. `[]` realm_config_account #[derive(Clone, Debug, Default)] pub struct WithdrawGoverningTokensBuilder { - realm_account: Option, - governing_token_holding_account: Option, - governing_token_destination_account: Option, - governing_token_owner_account: Option, - token_owner_record: Option, - token_program: Option, - realm_config_account: Option, + realm_account: Option, + governing_token_holding_account: Option, + governing_token_destination_account: Option, + governing_token_owner_account: Option, + token_owner_record: Option, + token_program: Option, + realm_config_account: Option, __remaining_accounts: Vec, } @@ -130,7 +129,7 @@ impl WithdrawGoverningTokensBuilder { Self::default() } #[inline(always)] - pub fn realm_account(&mut self, realm_account: solana_pubkey::Pubkey) -> &mut Self { + pub fn realm_account(&mut self, realm_account: solana_address::Address) -> &mut Self { self.realm_account = Some(realm_account); self } @@ -138,7 +137,7 @@ impl WithdrawGoverningTokensBuilder { #[inline(always)] pub fn governing_token_holding_account( &mut self, - governing_token_holding_account: solana_pubkey::Pubkey, + governing_token_holding_account: solana_address::Address, ) -> &mut Self { self.governing_token_holding_account = Some(governing_token_holding_account); self @@ -147,7 +146,7 @@ impl WithdrawGoverningTokensBuilder { #[inline(always)] pub fn governing_token_destination_account( &mut self, - governing_token_destination_account: solana_pubkey::Pubkey, + governing_token_destination_account: solana_address::Address, ) -> &mut Self { self.governing_token_destination_account = Some(governing_token_destination_account); self @@ -155,20 +154,20 @@ impl WithdrawGoverningTokensBuilder { #[inline(always)] pub fn governing_token_owner_account( &mut self, - governing_token_owner_account: solana_pubkey::Pubkey, + governing_token_owner_account: solana_address::Address, ) -> &mut Self { self.governing_token_owner_account = Some(governing_token_owner_account); self } /// seeds=['governance',realm, governing_token_mint, governing_token_owner] #[inline(always)] - pub fn token_owner_record(&mut self, token_owner_record: solana_pubkey::Pubkey) -> &mut Self { + pub fn token_owner_record(&mut self, token_owner_record: solana_address::Address) -> &mut Self { self.token_owner_record = Some(token_owner_record); self } /// `[optional account, default to 'TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA']` #[inline(always)] - pub fn token_program(&mut self, token_program: solana_pubkey::Pubkey) -> &mut Self { + pub fn token_program(&mut self, token_program: solana_address::Address) -> &mut Self { self.token_program = Some(token_program); self } @@ -176,7 +175,7 @@ impl WithdrawGoverningTokensBuilder { #[inline(always)] pub fn realm_config_account( &mut self, - realm_config_account: solana_pubkey::Pubkey, + realm_config_account: solana_address::Address, ) -> &mut Self { self.realm_config_account = Some(realm_config_account); self @@ -212,7 +211,7 @@ impl WithdrawGoverningTokensBuilder { token_owner_record: self .token_owner_record .expect("token_owner_record is not set"), - token_program: self.token_program.unwrap_or(solana_pubkey::pubkey!( + token_program: self.token_program.unwrap_or(solana_address::address!( "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA" )), realm_config_account: self diff --git a/e2e/governance/src/generated/pdas/community_token_holding.rs b/e2e/governance/src/generated/pdas/community_token_holding.rs index c014544..b5a3d5f 100644 --- a/e2e/governance/src/generated/pdas/community_token_holding.rs +++ b/e2e/governance/src/generated/pdas/community_token_holding.rs @@ -5,16 +5,18 @@ //! //! +use solana_address::Address; + use crate::SPL_GOVERNANCE_ID; pub const COMMUNITY_TOKEN_HOLDING_SEED: &'static [u8] = b"governance"; /// Community token holding account of a realm pub fn create_community_token_holding_pda( - realm: solana_pubkey::Pubkey, - community_mint: solana_pubkey::Pubkey, + realm: Address, + community_mint: Address, bump: u8, -) -> Result { - solana_pubkey::Pubkey::create_program_address( +) -> Result { + solana_address::Address::create_program_address( &[ COMMUNITY_TOKEN_HOLDING_SEED, realm.as_ref(), @@ -26,10 +28,10 @@ pub fn create_community_token_holding_pda( } /// Community token holding account of a realm pub fn find_community_token_holding_pda( - realm: &solana_pubkey::Pubkey, - community_mint: &solana_pubkey::Pubkey, -) -> (solana_pubkey::Pubkey, u8) { - solana_pubkey::Pubkey::find_program_address( + realm: &Address, + community_mint: &Address, +) -> (solana_address::Address, u8) { + solana_address::Address::find_program_address( &[ COMMUNITY_TOKEN_HOLDING_SEED, realm.as_ref(), diff --git a/e2e/governance/src/generated/pdas/council_token_holding.rs b/e2e/governance/src/generated/pdas/council_token_holding.rs index 6403a68..c23caf4 100644 --- a/e2e/governance/src/generated/pdas/council_token_holding.rs +++ b/e2e/governance/src/generated/pdas/council_token_holding.rs @@ -5,16 +5,18 @@ //! //! +use solana_address::Address; + use crate::SPL_GOVERNANCE_ID; pub const COUNCIL_TOKEN_HOLDING_SEED: &'static [u8] = b"governance"; /// Council token holding account of a realm pub fn create_council_token_holding_pda( - realm: solana_pubkey::Pubkey, - council_mint: solana_pubkey::Pubkey, + realm: Address, + council_mint: Address, bump: u8, -) -> Result { - solana_pubkey::Pubkey::create_program_address( +) -> Result { + solana_address::Address::create_program_address( &[ COUNCIL_TOKEN_HOLDING_SEED, realm.as_ref(), @@ -26,10 +28,10 @@ pub fn create_council_token_holding_pda( } /// Council token holding account of a realm pub fn find_council_token_holding_pda( - realm: &solana_pubkey::Pubkey, - council_mint: &solana_pubkey::Pubkey, -) -> (solana_pubkey::Pubkey, u8) { - solana_pubkey::Pubkey::find_program_address( + realm: &Address, + council_mint: &Address, +) -> (solana_address::Address, u8) { + solana_address::Address::find_program_address( &[ COUNCIL_TOKEN_HOLDING_SEED, realm.as_ref(), diff --git a/e2e/governance/src/generated/pdas/governance.rs b/e2e/governance/src/generated/pdas/governance.rs index fda84c7..4e71153 100644 --- a/e2e/governance/src/generated/pdas/governance.rs +++ b/e2e/governance/src/generated/pdas/governance.rs @@ -5,26 +5,25 @@ //! //! +use solana_address::Address; + use crate::SPL_GOVERNANCE_ID; pub const GOVERNANCE_SEED: &'static [u8] = b"account-governance"; /// Governance account within a realm pub fn create_governance_pda( - realm: solana_pubkey::Pubkey, - seed: solana_pubkey::Pubkey, + realm: Address, + seed: Address, bump: u8, -) -> Result { - solana_pubkey::Pubkey::create_program_address( +) -> Result { + solana_address::Address::create_program_address( &[GOVERNANCE_SEED, realm.as_ref(), seed.as_ref(), &[bump]], &SPL_GOVERNANCE_ID, ) } /// Governance account within a realm -pub fn find_governance_pda( - realm: &solana_pubkey::Pubkey, - seed: &solana_pubkey::Pubkey, -) -> (solana_pubkey::Pubkey, u8) { - solana_pubkey::Pubkey::find_program_address( +pub fn find_governance_pda(realm: &Address, seed: &Address) -> (solana_address::Address, u8) { + solana_address::Address::find_program_address( &[GOVERNANCE_SEED, realm.as_ref(), seed.as_ref()], &SPL_GOVERNANCE_ID, ) diff --git a/e2e/governance/src/generated/pdas/governing_token_holding.rs b/e2e/governance/src/generated/pdas/governing_token_holding.rs index 301bd8c..6cfdda1 100644 --- a/e2e/governance/src/generated/pdas/governing_token_holding.rs +++ b/e2e/governance/src/generated/pdas/governing_token_holding.rs @@ -5,16 +5,18 @@ //! //! +use solana_address::Address; + use crate::SPL_GOVERNANCE_ID; pub const GOVERNING_TOKEN_HOLDING_SEED: &'static [u8] = b"governance"; /// Governing token holding account pub fn create_governing_token_holding_pda( - realm: solana_pubkey::Pubkey, - governing_token_mint: solana_pubkey::Pubkey, + realm: Address, + governing_token_mint: Address, bump: u8, -) -> Result { - solana_pubkey::Pubkey::create_program_address( +) -> Result { + solana_address::Address::create_program_address( &[ GOVERNING_TOKEN_HOLDING_SEED, realm.as_ref(), @@ -26,10 +28,10 @@ pub fn create_governing_token_holding_pda( } /// Governing token holding account pub fn find_governing_token_holding_pda( - realm: &solana_pubkey::Pubkey, - governing_token_mint: &solana_pubkey::Pubkey, -) -> (solana_pubkey::Pubkey, u8) { - solana_pubkey::Pubkey::find_program_address( + realm: &Address, + governing_token_mint: &Address, +) -> (solana_address::Address, u8) { + solana_address::Address::find_program_address( &[ GOVERNING_TOKEN_HOLDING_SEED, realm.as_ref(), diff --git a/e2e/governance/src/generated/pdas/native_treasury.rs b/e2e/governance/src/generated/pdas/native_treasury.rs index 1dc03e3..4a545ae 100644 --- a/e2e/governance/src/generated/pdas/native_treasury.rs +++ b/e2e/governance/src/generated/pdas/native_treasury.rs @@ -5,22 +5,24 @@ //! //! +use solana_address::Address; + use crate::SPL_GOVERNANCE_ID; pub const NATIVE_TREASURY_SEED: &'static [u8] = b"native-treasury"; /// Governance's native SOL treasury account pub fn create_native_treasury_pda( - governance: solana_pubkey::Pubkey, + governance: Address, bump: u8, -) -> Result { - solana_pubkey::Pubkey::create_program_address( +) -> Result { + solana_address::Address::create_program_address( &[NATIVE_TREASURY_SEED, governance.as_ref(), &[bump]], &SPL_GOVERNANCE_ID, ) } /// Governance's native SOL treasury account -pub fn find_native_treasury_pda(governance: &solana_pubkey::Pubkey) -> (solana_pubkey::Pubkey, u8) { - solana_pubkey::Pubkey::find_program_address( +pub fn find_native_treasury_pda(governance: &Address) -> (solana_address::Address, u8) { + solana_address::Address::find_program_address( &[NATIVE_TREASURY_SEED, governance.as_ref()], &SPL_GOVERNANCE_ID, ) diff --git a/e2e/governance/src/generated/pdas/proposal.rs b/e2e/governance/src/generated/pdas/proposal.rs index 6c27861..a11f0d1 100644 --- a/e2e/governance/src/generated/pdas/proposal.rs +++ b/e2e/governance/src/generated/pdas/proposal.rs @@ -5,17 +5,19 @@ //! //! +use solana_address::Address; + use crate::SPL_GOVERNANCE_ID; pub const PROPOSAL_SEED: &'static [u8] = b"governance"; /// Governance proposal pub fn create_proposal_pda( - governance: solana_pubkey::Pubkey, - governing_token_mint: solana_pubkey::Pubkey, - proposal_seed: solana_pubkey::Pubkey, + governance: Address, + governing_token_mint: Address, + proposal_seed: Address, bump: u8, -) -> Result { - solana_pubkey::Pubkey::create_program_address( +) -> Result { + solana_address::Address::create_program_address( &[ PROPOSAL_SEED, governance.as_ref(), @@ -28,11 +30,11 @@ pub fn create_proposal_pda( } /// Governance proposal pub fn find_proposal_pda( - governance: &solana_pubkey::Pubkey, - governing_token_mint: &solana_pubkey::Pubkey, - proposal_seed: &solana_pubkey::Pubkey, -) -> (solana_pubkey::Pubkey, u8) { - solana_pubkey::Pubkey::find_program_address( + governance: &Address, + governing_token_mint: &Address, + proposal_seed: &Address, +) -> (solana_address::Address, u8) { + solana_address::Address::find_program_address( &[ PROPOSAL_SEED, governance.as_ref(), diff --git a/e2e/governance/src/generated/pdas/proposal_deposit.rs b/e2e/governance/src/generated/pdas/proposal_deposit.rs index 4953042..182132b 100644 --- a/e2e/governance/src/generated/pdas/proposal_deposit.rs +++ b/e2e/governance/src/generated/pdas/proposal_deposit.rs @@ -5,16 +5,18 @@ //! //! +use solana_address::Address; + use crate::SPL_GOVERNANCE_ID; pub const PROPOSAL_DEPOSIT_SEED: &'static [u8] = b"proposal-deposit"; /// Proposal deposit made by a specific payer pub fn create_proposal_deposit_pda( - proposal: solana_pubkey::Pubkey, - deposit_payer: solana_pubkey::Pubkey, + proposal: Address, + deposit_payer: Address, bump: u8, -) -> Result { - solana_pubkey::Pubkey::create_program_address( +) -> Result { + solana_address::Address::create_program_address( &[ PROPOSAL_DEPOSIT_SEED, proposal.as_ref(), @@ -26,10 +28,10 @@ pub fn create_proposal_deposit_pda( } /// Proposal deposit made by a specific payer pub fn find_proposal_deposit_pda( - proposal: &solana_pubkey::Pubkey, - deposit_payer: &solana_pubkey::Pubkey, -) -> (solana_pubkey::Pubkey, u8) { - solana_pubkey::Pubkey::find_program_address( + proposal: &Address, + deposit_payer: &Address, +) -> (solana_address::Address, u8) { + solana_address::Address::find_program_address( &[ PROPOSAL_DEPOSIT_SEED, proposal.as_ref(), diff --git a/e2e/governance/src/generated/pdas/proposal_transaction.rs b/e2e/governance/src/generated/pdas/proposal_transaction.rs index 952345e..c13bf94 100644 --- a/e2e/governance/src/generated/pdas/proposal_transaction.rs +++ b/e2e/governance/src/generated/pdas/proposal_transaction.rs @@ -5,17 +5,19 @@ //! //! +use solana_address::Address; + use crate::SPL_GOVERNANCE_ID; pub const PROPOSAL_TRANSACTION_SEED: &'static [u8] = b"governance"; /// Transaction within a proposal option pub fn create_proposal_transaction_pda( - proposal: solana_pubkey::Pubkey, + proposal: Address, option_index: u8, index: u16, bump: u8, -) -> Result { - solana_pubkey::Pubkey::create_program_address( +) -> Result { + solana_address::Address::create_program_address( &[ PROPOSAL_TRANSACTION_SEED, proposal.as_ref(), @@ -28,11 +30,11 @@ pub fn create_proposal_transaction_pda( } /// Transaction within a proposal option pub fn find_proposal_transaction_pda( - proposal: &solana_pubkey::Pubkey, + proposal: &Address, option_index: u8, index: u16, -) -> (solana_pubkey::Pubkey, u8) { - solana_pubkey::Pubkey::find_program_address( +) -> (solana_address::Address, u8) { + solana_address::Address::find_program_address( &[ PROPOSAL_TRANSACTION_SEED, proposal.as_ref(), diff --git a/e2e/governance/src/generated/pdas/realm.rs b/e2e/governance/src/generated/pdas/realm.rs index 84f5c58..33890e6 100644 --- a/e2e/governance/src/generated/pdas/realm.rs +++ b/e2e/governance/src/generated/pdas/realm.rs @@ -5,22 +5,24 @@ //! //! +use spl_collections::TrailingStr; + use crate::SPL_GOVERNANCE_ID; pub const REALM_SEED: &'static [u8] = b"governance"; /// Realm account identified by its name pub fn create_realm_pda( - name: RemainderStr, + name: TrailingStr, bump: u8, -) -> Result { - solana_pubkey::Pubkey::create_program_address( +) -> Result { + solana_address::Address::create_program_address( &[REALM_SEED, name.to_string().as_ref(), &[bump]], &SPL_GOVERNANCE_ID, ) } /// Realm account identified by its name -pub fn find_realm_pda(name: RemainderStr) -> (solana_pubkey::Pubkey, u8) { - solana_pubkey::Pubkey::find_program_address( +pub fn find_realm_pda(name: TrailingStr) -> (solana_address::Address, u8) { + solana_address::Address::find_program_address( &[REALM_SEED, name.to_string().as_ref()], &SPL_GOVERNANCE_ID, ) diff --git a/e2e/governance/src/generated/pdas/realm_config.rs b/e2e/governance/src/generated/pdas/realm_config.rs index d285ea4..28c3bbc 100644 --- a/e2e/governance/src/generated/pdas/realm_config.rs +++ b/e2e/governance/src/generated/pdas/realm_config.rs @@ -5,22 +5,24 @@ //! //! +use solana_address::Address; + use crate::SPL_GOVERNANCE_ID; pub const REALM_CONFIG_SEED: &'static [u8] = b"realm-config"; /// Configuration of a realm pub fn create_realm_config_pda( - realm: solana_pubkey::Pubkey, + realm: Address, bump: u8, -) -> Result { - solana_pubkey::Pubkey::create_program_address( +) -> Result { + solana_address::Address::create_program_address( &[REALM_CONFIG_SEED, realm.as_ref(), &[bump]], &SPL_GOVERNANCE_ID, ) } /// Configuration of a realm -pub fn find_realm_config_pda(realm: &solana_pubkey::Pubkey) -> (solana_pubkey::Pubkey, u8) { - solana_pubkey::Pubkey::find_program_address( +pub fn find_realm_config_pda(realm: &Address) -> (solana_address::Address, u8) { + solana_address::Address::find_program_address( &[REALM_CONFIG_SEED, realm.as_ref()], &SPL_GOVERNANCE_ID, ) diff --git a/e2e/governance/src/generated/pdas/required_signatory.rs b/e2e/governance/src/generated/pdas/required_signatory.rs index 0d43371..a168f3c 100644 --- a/e2e/governance/src/generated/pdas/required_signatory.rs +++ b/e2e/governance/src/generated/pdas/required_signatory.rs @@ -5,16 +5,18 @@ //! //! +use solana_address::Address; + use crate::SPL_GOVERNANCE_ID; pub const REQUIRED_SIGNATORY_SEED: &'static [u8] = b"required-signatory"; /// Required signatory on a governance pub fn create_required_signatory_pda( - governance: solana_pubkey::Pubkey, - signatory: solana_pubkey::Pubkey, + governance: Address, + signatory: Address, bump: u8, -) -> Result { - solana_pubkey::Pubkey::create_program_address( +) -> Result { + solana_address::Address::create_program_address( &[ REQUIRED_SIGNATORY_SEED, governance.as_ref(), @@ -26,10 +28,10 @@ pub fn create_required_signatory_pda( } /// Required signatory on a governance pub fn find_required_signatory_pda( - governance: &solana_pubkey::Pubkey, - signatory: &solana_pubkey::Pubkey, -) -> (solana_pubkey::Pubkey, u8) { - solana_pubkey::Pubkey::find_program_address( + governance: &Address, + signatory: &Address, +) -> (solana_address::Address, u8) { + solana_address::Address::find_program_address( &[ REQUIRED_SIGNATORY_SEED, governance.as_ref(), diff --git a/e2e/governance/src/generated/pdas/signatory_record.rs b/e2e/governance/src/generated/pdas/signatory_record.rs index b029efe..b38f225 100644 --- a/e2e/governance/src/generated/pdas/signatory_record.rs +++ b/e2e/governance/src/generated/pdas/signatory_record.rs @@ -5,16 +5,18 @@ //! //! +use solana_address::Address; + use crate::SPL_GOVERNANCE_ID; pub const SIGNATORY_RECORD_SEED: &'static [u8] = b"governance"; /// Signatory's record on a proposal pub fn create_signatory_record_pda( - proposal: solana_pubkey::Pubkey, - signatory: solana_pubkey::Pubkey, + proposal: Address, + signatory: Address, bump: u8, -) -> Result { - solana_pubkey::Pubkey::create_program_address( +) -> Result { + solana_address::Address::create_program_address( &[ SIGNATORY_RECORD_SEED, proposal.as_ref(), @@ -26,10 +28,10 @@ pub fn create_signatory_record_pda( } /// Signatory's record on a proposal pub fn find_signatory_record_pda( - proposal: &solana_pubkey::Pubkey, - signatory: &solana_pubkey::Pubkey, -) -> (solana_pubkey::Pubkey, u8) { - solana_pubkey::Pubkey::find_program_address( + proposal: &Address, + signatory: &Address, +) -> (solana_address::Address, u8) { + solana_address::Address::find_program_address( &[SIGNATORY_RECORD_SEED, proposal.as_ref(), signatory.as_ref()], &SPL_GOVERNANCE_ID, ) diff --git a/e2e/governance/src/generated/pdas/token_owner_record.rs b/e2e/governance/src/generated/pdas/token_owner_record.rs index 8199ea6..3482cf6 100644 --- a/e2e/governance/src/generated/pdas/token_owner_record.rs +++ b/e2e/governance/src/generated/pdas/token_owner_record.rs @@ -5,17 +5,19 @@ //! //! +use solana_address::Address; + use crate::SPL_GOVERNANCE_ID; pub const TOKEN_OWNER_RECORD_SEED: &'static [u8] = b"governance"; /// Token owner's record within a realm pub fn create_token_owner_record_pda( - realm: solana_pubkey::Pubkey, - governing_token_mint: solana_pubkey::Pubkey, - governing_token_owner: solana_pubkey::Pubkey, + realm: Address, + governing_token_mint: Address, + governing_token_owner: Address, bump: u8, -) -> Result { - solana_pubkey::Pubkey::create_program_address( +) -> Result { + solana_address::Address::create_program_address( &[ TOKEN_OWNER_RECORD_SEED, realm.as_ref(), @@ -28,11 +30,11 @@ pub fn create_token_owner_record_pda( } /// Token owner's record within a realm pub fn find_token_owner_record_pda( - realm: &solana_pubkey::Pubkey, - governing_token_mint: &solana_pubkey::Pubkey, - governing_token_owner: &solana_pubkey::Pubkey, -) -> (solana_pubkey::Pubkey, u8) { - solana_pubkey::Pubkey::find_program_address( + realm: &Address, + governing_token_mint: &Address, + governing_token_owner: &Address, +) -> (solana_address::Address, u8) { + solana_address::Address::find_program_address( &[ TOKEN_OWNER_RECORD_SEED, realm.as_ref(), diff --git a/e2e/governance/src/generated/pdas/vote_record.rs b/e2e/governance/src/generated/pdas/vote_record.rs index 366cc74..9b648a9 100644 --- a/e2e/governance/src/generated/pdas/vote_record.rs +++ b/e2e/governance/src/generated/pdas/vote_record.rs @@ -5,16 +5,18 @@ //! //! +use solana_address::Address; + use crate::SPL_GOVERNANCE_ID; pub const VOTE_RECORD_SEED: &'static [u8] = b"governance"; /// Vote record on a proposal pub fn create_vote_record_pda( - proposal: solana_pubkey::Pubkey, - token_owner_record: solana_pubkey::Pubkey, + proposal: Address, + token_owner_record: Address, bump: u8, -) -> Result { - solana_pubkey::Pubkey::create_program_address( +) -> Result { + solana_address::Address::create_program_address( &[ VOTE_RECORD_SEED, proposal.as_ref(), @@ -26,10 +28,10 @@ pub fn create_vote_record_pda( } /// Vote record on a proposal pub fn find_vote_record_pda( - proposal: &solana_pubkey::Pubkey, - token_owner_record: &solana_pubkey::Pubkey, -) -> (solana_pubkey::Pubkey, u8) { - solana_pubkey::Pubkey::find_program_address( + proposal: &Address, + token_owner_record: &Address, +) -> (solana_address::Address, u8) { + solana_address::Address::find_program_address( &[ VOTE_RECORD_SEED, proposal.as_ref(), diff --git a/e2e/governance/src/generated/programs.rs b/e2e/governance/src/generated/programs.rs index 1a3d43e..77fa696 100644 --- a/e2e/governance/src/generated/programs.rs +++ b/e2e/governance/src/generated/programs.rs @@ -5,7 +5,7 @@ //! //! -use solana_pubkey::{pubkey, Pubkey}; +use solana_address::{address, Address}; /// `spl_governance` program ID. -pub const SPL_GOVERNANCE_ID: Pubkey = pubkey!("GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw"); +pub const SPL_GOVERNANCE_ID: Address = address!("GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw"); diff --git a/e2e/governance/src/generated/shared.rs b/e2e/governance/src/generated/shared.rs index 71b906d..42eae7f 100644 --- a/e2e/governance/src/generated/shared.rs +++ b/e2e/governance/src/generated/shared.rs @@ -8,7 +8,7 @@ #[cfg(feature = "fetch")] #[derive(Debug, Clone)] pub struct DecodedAccount { - pub address: solana_pubkey::Pubkey, + pub address: solana_address::Address, pub account: solana_account::Account, pub data: T, } @@ -17,5 +17,5 @@ pub struct DecodedAccount { #[derive(Debug, Clone)] pub enum MaybeAccount { Exists(DecodedAccount), - NotFound(solana_pubkey::Pubkey), + NotFound(solana_address::Address), } diff --git a/e2e/governance/src/generated/types/account_meta_data.rs b/e2e/governance/src/generated/types/account_meta_data.rs index c15ed18..71c8886 100644 --- a/e2e/governance/src/generated/types/account_meta_data.rs +++ b/e2e/governance/src/generated/types/account_meta_data.rs @@ -7,16 +7,11 @@ use borsh::BorshDeserialize; use borsh::BorshSerialize; -use solana_pubkey::Pubkey; +use solana_address::Address; #[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] -#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct AccountMetaData { - #[cfg_attr( - feature = "serde", - serde(with = "serde_with::As::") - )] - pub pubkey: Pubkey, + pub pubkey: Address, pub is_signer: bool, pub is_writable: bool, } diff --git a/e2e/governance/src/generated/types/governance_account_type.rs b/e2e/governance/src/generated/types/governance_account_type.rs index 5554407..aaba23a 100644 --- a/e2e/governance/src/generated/types/governance_account_type.rs +++ b/e2e/governance/src/generated/types/governance_account_type.rs @@ -21,7 +21,6 @@ use num_derive::FromPrimitive; Hash, FromPrimitive, )] -#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub enum GovernanceAccountType { Uninitialized, RealmV1, diff --git a/e2e/governance/src/generated/types/governance_config.rs b/e2e/governance/src/generated/types/governance_config.rs index d84716c..d7ac461 100644 --- a/e2e/governance/src/generated/types/governance_config.rs +++ b/e2e/governance/src/generated/types/governance_config.rs @@ -11,7 +11,6 @@ use borsh::BorshDeserialize; use borsh::BorshSerialize; #[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] -#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct GovernanceConfig { pub community_vote_threshold: VoteThreshold, pub min_community_weight_to_create_proposal: u64, diff --git a/e2e/governance/src/generated/types/governance_instruction_v1.rs b/e2e/governance/src/generated/types/governance_instruction_v1.rs index fbef779..787bb2b 100644 --- a/e2e/governance/src/generated/types/governance_instruction_v1.rs +++ b/e2e/governance/src/generated/types/governance_instruction_v1.rs @@ -10,7 +10,6 @@ use borsh::BorshDeserialize; use borsh::BorshSerialize; #[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] -#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub enum GovernanceInstructionV1 { CreateRealm { name: String, diff --git a/e2e/governance/src/generated/types/governing_token_config.rs b/e2e/governance/src/generated/types/governing_token_config.rs index 55bf0fe..dfbe0d8 100644 --- a/e2e/governance/src/generated/types/governing_token_config.rs +++ b/e2e/governance/src/generated/types/governing_token_config.rs @@ -8,13 +8,12 @@ use crate::generated::types::GoverningTokenType; use borsh::BorshDeserialize; use borsh::BorshSerialize; -use solana_pubkey::Pubkey; +use solana_address::Address; #[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] -#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct GoverningTokenConfig { - pub voter_weight_addin: Option, - pub max_voter_weight_addin: Option, + pub voter_weight_addin: Option
, + pub max_voter_weight_addin: Option
, pub token_type: GoverningTokenType, pub reserved: [u8; 8], } diff --git a/e2e/governance/src/generated/types/governing_token_config_account_args.rs b/e2e/governance/src/generated/types/governing_token_config_account_args.rs index a536aba..396788c 100644 --- a/e2e/governance/src/generated/types/governing_token_config_account_args.rs +++ b/e2e/governance/src/generated/types/governing_token_config_account_args.rs @@ -8,12 +8,11 @@ use crate::generated::types::GoverningTokenType; use borsh::BorshDeserialize; use borsh::BorshSerialize; -use solana_pubkey::Pubkey; +use solana_address::Address; #[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] -#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct GoverningTokenConfigAccountArgs { - pub voter_weight_addin: Option, - pub max_voter_weight_addin: Option, + pub voter_weight_addin: Option
, + pub max_voter_weight_addin: Option
, pub token_type: GoverningTokenType, } diff --git a/e2e/governance/src/generated/types/governing_token_config_params.rs b/e2e/governance/src/generated/types/governing_token_config_params.rs index 997da2a..5ceee6e 100644 --- a/e2e/governance/src/generated/types/governing_token_config_params.rs +++ b/e2e/governance/src/generated/types/governing_token_config_params.rs @@ -10,7 +10,6 @@ use borsh::BorshDeserialize; use borsh::BorshSerialize; #[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] -#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct GoverningTokenConfigParams { pub use_voter_weight_addin: bool, pub use_max_voter_weight_addin: bool, diff --git a/e2e/governance/src/generated/types/governing_token_type.rs b/e2e/governance/src/generated/types/governing_token_type.rs index 38414f2..5f0557c 100644 --- a/e2e/governance/src/generated/types/governing_token_type.rs +++ b/e2e/governance/src/generated/types/governing_token_type.rs @@ -21,7 +21,6 @@ use num_derive::FromPrimitive; Hash, FromPrimitive, )] -#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub enum GoverningTokenType { Liquid, Membership, diff --git a/e2e/governance/src/generated/types/instruction_data.rs b/e2e/governance/src/generated/types/instruction_data.rs index c4d309b..8ef15a8 100644 --- a/e2e/governance/src/generated/types/instruction_data.rs +++ b/e2e/governance/src/generated/types/instruction_data.rs @@ -8,16 +8,11 @@ use crate::generated::types::AccountMetaData; use borsh::BorshDeserialize; use borsh::BorshSerialize; -use solana_pubkey::Pubkey; +use solana_address::Address; #[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] -#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct InstructionData { - #[cfg_attr( - feature = "serde", - serde(with = "serde_with::As::") - )] - pub program_id: Pubkey, + pub program_id: Address, pub accounts: Vec, pub data: Vec, } diff --git a/e2e/governance/src/generated/types/instruction_execution_flags.rs b/e2e/governance/src/generated/types/instruction_execution_flags.rs index e7d6fbf..5667518 100644 --- a/e2e/governance/src/generated/types/instruction_execution_flags.rs +++ b/e2e/governance/src/generated/types/instruction_execution_flags.rs @@ -21,7 +21,6 @@ use num_derive::FromPrimitive; Hash, FromPrimitive, )] -#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub enum InstructionExecutionFlags { None, Ordered, diff --git a/e2e/governance/src/generated/types/mint_max_voter_weight_source.rs b/e2e/governance/src/generated/types/mint_max_voter_weight_source.rs index b37c7a7..4e3fa26 100644 --- a/e2e/governance/src/generated/types/mint_max_voter_weight_source.rs +++ b/e2e/governance/src/generated/types/mint_max_voter_weight_source.rs @@ -9,7 +9,6 @@ use borsh::BorshDeserialize; use borsh::BorshSerialize; #[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] -#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub enum MintMaxVoterWeightSource { SupplyFraction(u64), Absolute(u64), diff --git a/e2e/governance/src/generated/types/multi_choice_type.rs b/e2e/governance/src/generated/types/multi_choice_type.rs index 711e515..17cd933 100644 --- a/e2e/governance/src/generated/types/multi_choice_type.rs +++ b/e2e/governance/src/generated/types/multi_choice_type.rs @@ -21,7 +21,6 @@ use num_derive::FromPrimitive; Hash, FromPrimitive, )] -#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub enum MultiChoiceType { FullWeight, Weighted, diff --git a/e2e/governance/src/generated/types/native_treasury.rs b/e2e/governance/src/generated/types/native_treasury.rs index 5fa3f7c..3ccef96 100644 --- a/e2e/governance/src/generated/types/native_treasury.rs +++ b/e2e/governance/src/generated/types/native_treasury.rs @@ -9,5 +9,4 @@ use borsh::BorshDeserialize; use borsh::BorshSerialize; #[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] -#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct NativeTreasury {} diff --git a/e2e/governance/src/generated/types/option_vote_result.rs b/e2e/governance/src/generated/types/option_vote_result.rs index 395fc8d..cef847c 100644 --- a/e2e/governance/src/generated/types/option_vote_result.rs +++ b/e2e/governance/src/generated/types/option_vote_result.rs @@ -21,7 +21,6 @@ use num_derive::FromPrimitive; Hash, FromPrimitive, )] -#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub enum OptionVoteResult { None, Succeeded, diff --git a/e2e/governance/src/generated/types/proposal_option.rs b/e2e/governance/src/generated/types/proposal_option.rs index e594325..208e536 100644 --- a/e2e/governance/src/generated/types/proposal_option.rs +++ b/e2e/governance/src/generated/types/proposal_option.rs @@ -10,7 +10,6 @@ use borsh::BorshDeserialize; use borsh::BorshSerialize; #[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] -#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct ProposalOption { pub label: String, pub vote_weight: u64, diff --git a/e2e/governance/src/generated/types/proposal_state.rs b/e2e/governance/src/generated/types/proposal_state.rs index 21ca864..7bd605b 100644 --- a/e2e/governance/src/generated/types/proposal_state.rs +++ b/e2e/governance/src/generated/types/proposal_state.rs @@ -21,7 +21,6 @@ use num_derive::FromPrimitive; Hash, FromPrimitive, )] -#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub enum ProposalState { Draft, SigningOff, diff --git a/e2e/governance/src/generated/types/realm_config.rs b/e2e/governance/src/generated/types/realm_config.rs index c102325..ad92b81 100644 --- a/e2e/governance/src/generated/types/realm_config.rs +++ b/e2e/governance/src/generated/types/realm_config.rs @@ -8,15 +8,14 @@ use crate::generated::types::MintMaxVoterWeightSource; use borsh::BorshDeserialize; use borsh::BorshSerialize; -use solana_pubkey::Pubkey; +use solana_address::Address; #[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] -#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct RealmConfig { pub legacy1: u8, pub legacy2: u8, pub reserved: [u8; 6], pub min_community_weight_to_create_governance: u64, pub community_mint_max_voter_weight_source: MintMaxVoterWeightSource, - pub council_mint: Option, + pub council_mint: Option
, } diff --git a/e2e/governance/src/generated/types/realm_config_params.rs b/e2e/governance/src/generated/types/realm_config_params.rs index 7675c7d..8bd42b4 100644 --- a/e2e/governance/src/generated/types/realm_config_params.rs +++ b/e2e/governance/src/generated/types/realm_config_params.rs @@ -11,7 +11,6 @@ use borsh::BorshDeserialize; use borsh::BorshSerialize; #[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] -#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct RealmConfigParams { pub use_council_mint: bool, pub min_community_weight_to_create_governance: u64, diff --git a/e2e/governance/src/generated/types/realm_config_params_v1.rs b/e2e/governance/src/generated/types/realm_config_params_v1.rs index 3c5ad52..9b52b1c 100644 --- a/e2e/governance/src/generated/types/realm_config_params_v1.rs +++ b/e2e/governance/src/generated/types/realm_config_params_v1.rs @@ -10,7 +10,6 @@ use borsh::BorshDeserialize; use borsh::BorshSerialize; #[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] -#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct RealmConfigParamsV1 { pub use_council_mint: bool, pub min_community_weight_to_create_governance: u64, diff --git a/e2e/governance/src/generated/types/reserved110.rs b/e2e/governance/src/generated/types/reserved110.rs index 3f64489..a0d3def 100644 --- a/e2e/governance/src/generated/types/reserved110.rs +++ b/e2e/governance/src/generated/types/reserved110.rs @@ -9,9 +9,7 @@ use borsh::BorshDeserialize; use borsh::BorshSerialize; #[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] -#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct Reserved110 { - #[cfg_attr(feature = "serde", serde(with = "serde_big_array::BigArray"))] pub reserved64: [u8; 64], pub reserved32: [u8; 32], pub reserved14: [u8; 14], diff --git a/e2e/governance/src/generated/types/reserved119.rs b/e2e/governance/src/generated/types/reserved119.rs index e669cd9..c904c4c 100644 --- a/e2e/governance/src/generated/types/reserved119.rs +++ b/e2e/governance/src/generated/types/reserved119.rs @@ -9,9 +9,7 @@ use borsh::BorshDeserialize; use borsh::BorshSerialize; #[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] -#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct Reserved119 { - #[cfg_attr(feature = "serde", serde(with = "serde_big_array::BigArray"))] pub reserved64: [u8; 64], pub reserved32: [u8; 32], pub reserved23: [u8; 23], diff --git a/e2e/governance/src/generated/types/set_realm_authority_action.rs b/e2e/governance/src/generated/types/set_realm_authority_action.rs index 10f16ab..b03caf8 100644 --- a/e2e/governance/src/generated/types/set_realm_authority_action.rs +++ b/e2e/governance/src/generated/types/set_realm_authority_action.rs @@ -21,7 +21,6 @@ use num_derive::FromPrimitive; Hash, FromPrimitive, )] -#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub enum SetRealmAuthorityAction { SetUnchecked, SetChecked, diff --git a/e2e/governance/src/generated/types/transaction_execution_status.rs b/e2e/governance/src/generated/types/transaction_execution_status.rs index af34c69..4ac3ddb 100644 --- a/e2e/governance/src/generated/types/transaction_execution_status.rs +++ b/e2e/governance/src/generated/types/transaction_execution_status.rs @@ -21,7 +21,6 @@ use num_derive::FromPrimitive; Hash, FromPrimitive, )] -#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub enum TransactionExecutionStatus { None, Success, diff --git a/e2e/governance/src/generated/types/vote.rs b/e2e/governance/src/generated/types/vote.rs index 6f1aa4f..95903bd 100644 --- a/e2e/governance/src/generated/types/vote.rs +++ b/e2e/governance/src/generated/types/vote.rs @@ -10,7 +10,6 @@ use borsh::BorshDeserialize; use borsh::BorshSerialize; #[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] -#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub enum Vote { Approve(Vec), Deny, diff --git a/e2e/governance/src/generated/types/vote_choice.rs b/e2e/governance/src/generated/types/vote_choice.rs index e6459ce..d5fbaa6 100644 --- a/e2e/governance/src/generated/types/vote_choice.rs +++ b/e2e/governance/src/generated/types/vote_choice.rs @@ -9,7 +9,6 @@ use borsh::BorshDeserialize; use borsh::BorshSerialize; #[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] -#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct VoteChoice { pub rank: u8, pub weight_percentage: u8, diff --git a/e2e/governance/src/generated/types/vote_kind.rs b/e2e/governance/src/generated/types/vote_kind.rs index 51d6ef8..5aae726 100644 --- a/e2e/governance/src/generated/types/vote_kind.rs +++ b/e2e/governance/src/generated/types/vote_kind.rs @@ -21,7 +21,6 @@ use num_derive::FromPrimitive; Hash, FromPrimitive, )] -#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub enum VoteKind { Electorate, Veto, diff --git a/e2e/governance/src/generated/types/vote_threshold.rs b/e2e/governance/src/generated/types/vote_threshold.rs index e608373..71bb356 100644 --- a/e2e/governance/src/generated/types/vote_threshold.rs +++ b/e2e/governance/src/generated/types/vote_threshold.rs @@ -9,7 +9,6 @@ use borsh::BorshDeserialize; use borsh::BorshSerialize; #[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] -#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub enum VoteThreshold { YesVotePercentage(u8), QuorumPercentage(u8), diff --git a/e2e/governance/src/generated/types/vote_tipping.rs b/e2e/governance/src/generated/types/vote_tipping.rs index 5c5a149..f15f308 100644 --- a/e2e/governance/src/generated/types/vote_tipping.rs +++ b/e2e/governance/src/generated/types/vote_tipping.rs @@ -21,7 +21,6 @@ use num_derive::FromPrimitive; Hash, FromPrimitive, )] -#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub enum VoteTipping { Strict, Early, diff --git a/e2e/governance/src/generated/types/vote_type.rs b/e2e/governance/src/generated/types/vote_type.rs index 16266c2..865ddde 100644 --- a/e2e/governance/src/generated/types/vote_type.rs +++ b/e2e/governance/src/generated/types/vote_type.rs @@ -10,7 +10,6 @@ use borsh::BorshDeserialize; use borsh::BorshSerialize; #[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] -#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub enum VoteType { SingleChoice, MultiChoice { diff --git a/e2e/governance/src/generated/types/vote_weight_v1.rs b/e2e/governance/src/generated/types/vote_weight_v1.rs index bb13f94..184b2b7 100644 --- a/e2e/governance/src/generated/types/vote_weight_v1.rs +++ b/e2e/governance/src/generated/types/vote_weight_v1.rs @@ -9,7 +9,6 @@ use borsh::BorshDeserialize; use borsh::BorshSerialize; #[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] -#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub enum VoteWeightV1 { Yes(u64), No(u64), diff --git a/public/templates/pdasPage.njk b/public/templates/pdasPage.njk index 9d27784..5295262 100644 --- a/public/templates/pdasPage.njk +++ b/public/templates/pdasPage.njk @@ -3,6 +3,8 @@ {% block main %} +{{ imports }} + {% if program %} use crate::{{ program.name | snakeCase | upper }}_ID; {% endif %} @@ -21,17 +23,13 @@ pub fn create_{{ pda.name | snakeCase }}_pda( {% if hasVariableSeeds %} {% for seed in seeds %} {% if seed.kind === 'variablePdaSeedNode' %} - {% if seed.resolvedType.kind == 'publicKeyTypeNode' %} - {{ seed.name | snakeCase }}: solana_pubkey::Pubkey, - {% else %} {{ seed.name | snakeCase }}: {{ seed.typeManifest.type }}, - {% endif %} {% endif %} {% endfor %} {% endif %} bump: u8, -) -> Result { - solana_pubkey::Pubkey::create_program_address( +) -> Result { + solana_address::Address::create_program_address( &[ {% set constantUsageIndex = 0 %} {% for seed in seeds %} @@ -64,17 +62,15 @@ pub fn create_{{ pda.name | snakeCase }}_pda( pub fn find_{{ pda.name | snakeCase }}_pda( {% if hasVariableSeeds %} {% for seed in seeds %} - {% if seed.kind == 'variablePdaSeedNode' %} - {% if seed.resolvedType.kind == 'publicKeyTypeNode' %} - {{ seed.name | snakeCase }}: &solana_pubkey::Pubkey, - {% else %} + {% if seed.kind == 'variablePdaSeedNode' and seed.resolvedType.kind == 'publicKeyTypeNode' %} + {{ seed.name | snakeCase }}: &{{ seed.typeManifest.type }}, + {% elif seed.kind === 'variablePdaSeedNode' %} {{ seed.name | snakeCase }}: {{ seed.typeManifest.type }}, - {% endif %} {% endif %} {% endfor %} {% endif %} -) -> (solana_pubkey::Pubkey, u8) { - solana_pubkey::Pubkey::find_program_address( +) -> (solana_address::Address, u8) { + solana_address::Address::find_program_address( &[ {% set constantUsageIndex2 = 0 %} {% for seed in seeds %} @@ -102,4 +98,4 @@ pub fn find_{{ pda.name | snakeCase }}_pda( ) } -{% endblock %} \ No newline at end of file +{% endblock %} diff --git a/src/getRenderMapVisitor.ts b/src/getRenderMapVisitor.ts index 0b94fe2..3a579fc 100644 --- a/src/getRenderMapVisitor.ts +++ b/src/getRenderMapVisitor.ts @@ -349,6 +349,7 @@ export function getRenderMapVisitor(options: GetRenderMapOptions = {}) { programsToExport.length > 0 || accountsToExport.length > 0 || instructionsToExport.length > 0 || + pdasToExport.length > 0 || definedTypesToExport.length > 0; const ctx = { diff --git a/test/pdasPage.test.ts b/test/pdasPage.test.ts index 1448961..b8b7a17 100644 --- a/test/pdasPage.test.ts +++ b/test/pdasPage.test.ts @@ -3,7 +3,6 @@ import { constantPdaSeedNode, constantPdaSeedNodeFromString, fixedSizeTypeNode, - getAllPdas, numberTypeNode, numberValueNode, pdaNode, @@ -39,14 +38,14 @@ test('it renders a standalone PDA with variable seeds', () => { const renderMap = visit(node, getRenderMapVisitor()); // Then we expect a standalone PDA file to be created. - codeContains(getFromRenderMap(renderMap, 'pdas/my_pda.rs'), [ + codeContains(getFromRenderMap(renderMap, 'pdas/my_pda.rs').content, [ 'pub const MY_PDA_SEED: &\'static [u8] = b"metadata";', 'pub fn create_my_pda_pda(', - 'mint: solana_pubkey::Pubkey,', + 'mint: Address,', 'bump: u8,', 'pub fn find_my_pda_pda(', - 'mint: &solana_pubkey::Pubkey,', - '-> (solana_pubkey::Pubkey, u8)', + 'mint: &Address,', + '-> (solana_address::Address, u8)', ]); }); @@ -70,13 +69,13 @@ test('it renders a PDA with only constant seeds', () => { const renderMap = visit(node, getRenderMapVisitor()); // Then we expect the PDA functions without variable parameters. - codeContains(getFromRenderMap(renderMap, 'pdas/config_pda.rs'), [ + codeContains(getFromRenderMap(renderMap, 'pdas/config_pda.rs').content, [ 'pub const CONFIG_PDA_SEED_0: &\'static [u8] = b"config";', 'pub const CONFIG_PDA_SEED_1: &\'static [u8] = b1;', 'pub fn create_config_pda_pda(', 'bump: u8,', 'pub fn find_config_pda_pda(', - ') -> (solana_pubkey::Pubkey, u8)', + ') -> (solana_address::Address, u8)', ]); }); @@ -100,7 +99,7 @@ test('it renders a PDA with byte array seeds', () => { const renderMap = visit(node, getRenderMapVisitor()); // Then we expect the byte array to be handled correctly. - codeContains(getFromRenderMap(renderMap, 'pdas/hash_pda.rs'), [ + codeContains(getFromRenderMap(renderMap, 'pdas/hash_pda.rs').content, [ 'pub const HASH_PDA_SEED: &\'static [u8] = b"hash";', 'pub fn create_hash_pda_pda(', 'data_hash: [u8; 32],', @@ -132,7 +131,7 @@ test('it renders a PDA module file', () => { const renderMap = visit(node, getRenderMapVisitor()); // Then we expect a module file to be created. - codeContains(getFromRenderMap(renderMap, 'pdas/mod.rs'), [ + codeContains(getFromRenderMap(renderMap, 'pdas/mod.rs').content, [ 'pub mod first_pda;', 'pub mod second_pda;', 'pub use self::first_pda::*;', @@ -154,13 +153,11 @@ test('it includes PDAs module in the root mod file', () => { }); const node = rootNode(program); - console.log("PDAs", getAllPdas(node)) - // When we render it. const renderMap = visit(node, getRenderMapVisitor()); // Then we expect the pdas module to be included in the root mod. - codeContains(getFromRenderMap(renderMap, 'mod.rs'), [ + codeContains(getFromRenderMap(renderMap, 'mod.rs').content, [ 'pub mod pdas;', ]); -}); \ No newline at end of file +}); From f5141f8dd9cd53713cb54c88fe48273a73db0ddb Mon Sep 17 00:00:00 2001 From: ioxde <228087182+ioxde@users.noreply.github.com> Date: Sat, 4 Apr 2026 12:09:59 -0700 Subject: [PATCH 15/24] add fetch feature to governance e2e project --- e2e/governance/Cargo.toml | 1 + src/getRenderMapVisitor.ts | 2 +- test/pdasPage.test.ts | 6 ++---- 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/e2e/governance/Cargo.toml b/e2e/governance/Cargo.toml index 0d057f7..989aedd 100644 --- a/e2e/governance/Cargo.toml +++ b/e2e/governance/Cargo.toml @@ -6,6 +6,7 @@ edition = "2021" [features] anchor = ["dep:anchor-lang"] anchor-idl-build = ["anchor", "anchor-lang?/idl-build"] +fetch = ["dep:solana-client"] serde = ["dep:serde", "dep:serde_with", "dep:serde-big-array"] test-sbf = [] diff --git a/src/getRenderMapVisitor.ts b/src/getRenderMapVisitor.ts index 3a579fc..73ba891 100644 --- a/src/getRenderMapVisitor.ts +++ b/src/getRenderMapVisitor.ts @@ -73,7 +73,7 @@ export function getRenderMapVisitor(options: GetRenderMapOptions = {}) { v => extendVisitor(v, { visitAccount(node) { - const accountPath = stack.getPath('accountNode'); + const accountPath = stack.getPath('accountNode'); const program = findProgramNodeFromPath(accountPath); if (!program) { throw new Error('Account must be visited inside a program.'); diff --git a/test/pdasPage.test.ts b/test/pdasPage.test.ts index b8b7a17..3912701 100644 --- a/test/pdasPage.test.ts +++ b/test/pdasPage.test.ts @@ -71,7 +71,7 @@ test('it renders a PDA with only constant seeds', () => { // Then we expect the PDA functions without variable parameters. codeContains(getFromRenderMap(renderMap, 'pdas/config_pda.rs').content, [ 'pub const CONFIG_PDA_SEED_0: &\'static [u8] = b"config";', - 'pub const CONFIG_PDA_SEED_1: &\'static [u8] = b1;', + "pub const CONFIG_PDA_SEED_1: &'static [u8] = b1;", 'pub fn create_config_pda_pda(', 'bump: u8,', 'pub fn find_config_pda_pda(', @@ -157,7 +157,5 @@ test('it includes PDAs module in the root mod file', () => { const renderMap = visit(node, getRenderMapVisitor()); // Then we expect the pdas module to be included in the root mod. - codeContains(getFromRenderMap(renderMap, 'mod.rs').content, [ - 'pub mod pdas;', - ]); + codeContains(getFromRenderMap(renderMap, 'mod.rs').content, ['pub mod pdas;']); }); From 29b8c21a45fbdb0afe57381fd81f7a1bfba07405 Mon Sep 17 00:00:00 2001 From: ioxde <228087182+ioxde@users.noreply.github.com> Date: Sat, 4 Apr 2026 12:50:25 -0700 Subject: [PATCH 16/24] Auto-derive PDA accounts in instruction builders When an instruction account has a pdaValueNode default (linked or inline), the builder now auto-derives the address instead of requiring it to be set explicitly. PDA-defaulted accounts are emitted as sequential let bindings, topologically sorted by seed dependencies, so accounts that reference other PDA-defaulted accounts resolve correctly. Constant seed rendering dispatches by value type: strings produce b"...", byte arrays &[...], and numbers &Nu64.to_le_bytes(). Bumps @codama/nodes-from-anchor to ^1.4.0 for extractPdasVisitor support (codama-idl/codama#984). --- .../generated/instructions/create_guard.rs | 34 +- .../src/generated/instructions/execute.rs | 15 +- .../src/generated/instructions/initialize.rs | 15 +- .../generated/instructions/update_guard.rs | 32 +- e2e/anchor/src/generated/mod.rs | 1 + .../src/generated/pdas/extra_metas_account.rs | 29 + e2e/anchor/src/generated/pdas/guard.rs | 31 + e2e/anchor/src/generated/pdas/mod.rs | 12 + e2e/dummy/idl.json | 121 +- .../generated/instructions/instruction8.rs | 355 ++++++ .../generated/instructions/instruction9.rs | 271 ++++ e2e/dummy/src/generated/instructions/mod.rs | 4 + e2e/dummy/src/generated/mod.rs | 1 + .../src/generated/pdas/derived_account.rs | 36 + e2e/dummy/src/generated/pdas/global_config.rs | 23 + e2e/dummy/src/generated/pdas/mod.rs | 12 + .../src/generated/accounts/governance_v1.rs | 10 +- .../src/generated/accounts/governance_v2.rs | 10 +- .../accounts/legacy_token_owner_record.rs | 6 +- .../generated/accounts/proposal_deposit.rs | 6 +- .../accounts/proposal_instruction_v1.rs | 6 +- .../accounts/proposal_transaction_v2.rs | 6 +- .../src/generated/accounts/proposal_v1.rs | 6 +- .../src/generated/accounts/proposal_v2.rs | 6 +- .../accounts/realm_config_account.rs | 6 +- .../src/generated/accounts/realm_v1.rs | 6 +- .../src/generated/accounts/realm_v2.rs | 6 +- .../generated/accounts/required_signatory.rs | 6 +- .../generated/accounts/signatory_record_v1.rs | 10 +- .../generated/accounts/signatory_record_v2.rs | 10 +- .../accounts/token_owner_record_v1.rs | 6 +- .../accounts/token_owner_record_v2.rs | 6 +- .../src/generated/accounts/vote_record_v1.rs | 6 +- .../src/generated/accounts/vote_record_v2.rs | 6 +- .../instructions/create_token_owner_record.rs | 21 +- e2e/governance/src/generated/pdas/mod.rs | 7 + package.json | 3 +- pnpm-lock.yaml | 1038 +++++++++------- public/templates/accountsPage.njk | 8 +- public/templates/instructionsPageBuilder.njk | 55 +- public/templates/pdasMod.njk | 8 +- public/templates/pdasPage.njk | 7 +- src/getRenderMapVisitor.ts | 411 ++++++- src/utils/computePda.ts | 159 +++ src/utils/index.ts | 1 + test/accountsPage.test.ts | 2 +- test/instructionsPage.test.ts | 1093 ++++++++++++++++- test/pdasPage.test.ts | 56 +- 48 files changed, 3410 insertions(+), 575 deletions(-) create mode 100644 e2e/anchor/src/generated/pdas/extra_metas_account.rs create mode 100644 e2e/anchor/src/generated/pdas/guard.rs create mode 100644 e2e/anchor/src/generated/pdas/mod.rs create mode 100644 e2e/dummy/src/generated/instructions/instruction8.rs create mode 100644 e2e/dummy/src/generated/instructions/instruction9.rs create mode 100644 e2e/dummy/src/generated/pdas/derived_account.rs create mode 100644 e2e/dummy/src/generated/pdas/global_config.rs create mode 100644 e2e/dummy/src/generated/pdas/mod.rs create mode 100644 src/utils/computePda.ts diff --git a/e2e/anchor/src/generated/instructions/create_guard.rs b/e2e/anchor/src/generated/instructions/create_guard.rs index fd28a57..e3858d0 100644 --- a/e2e/anchor/src/generated/instructions/create_guard.rs +++ b/e2e/anchor/src/generated/instructions/create_guard.rs @@ -124,9 +124,9 @@ impl CreateGuardInstructionArgs { /// /// ### Accounts: /// -/// 0. `[writable]` guard +/// 0. `[writable, optional]` guard (default to PDA derived from 'guard') /// 1. `[writable, signer]` mint -/// 2. `[writable]` mint_token_account +/// 2. `[writable, optional]` mint_token_account (default to PDA derived from 'mintTokenAccount') /// 3. `[signer]` guard_authority /// 4. `[writable, signer]` payer /// 5. `[optional]` associated_token_program (default to `ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL`) @@ -155,6 +155,7 @@ impl CreateGuardBuilder { pub fn new() -> Self { Self::default() } + /// `[optional account, default to PDA derived from 'guard']` #[inline(always)] pub fn guard(&mut self, guard: solana_address::Address) -> &mut Self { self.guard = Some(guard); @@ -165,6 +166,7 @@ impl CreateGuardBuilder { self.mint = Some(mint); self } + /// `[optional account, default to PDA derived from 'mintTokenAccount']` #[inline(always)] pub fn mint_token_account(&mut self, mint_token_account: solana_address::Address) -> &mut Self { self.mint_token_account = Some(mint_token_account); @@ -253,12 +255,32 @@ impl CreateGuardBuilder { } #[allow(clippy::clone_on_copy)] pub fn instruction(&self) -> solana_instruction::Instruction { + let guard = self.guard.unwrap_or_else(|| { + crate::pdas::find_guard_pda(&self.mint.expect("mint is needed for guard PDA")).0 + }); + let mint_token_account = self.mint_token_account.unwrap_or_else(|| { + solana_address::Address::find_program_address( + &[ + self.guard_authority + .expect("guard_authority is needed for mint_token_account PDA") + .as_ref(), + self.token_program + .unwrap_or(solana_address::address!( + "TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb" + )) + .as_ref(), + self.mint + .expect("mint is needed for mint_token_account PDA") + .as_ref(), + ], + &solana_address::address!("ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL"), + ) + .0 + }); let accounts = CreateGuard { - guard: self.guard.expect("guard is not set"), + guard, mint: self.mint.expect("mint is not set"), - mint_token_account: self - .mint_token_account - .expect("mint_token_account is not set"), + mint_token_account, guard_authority: self.guard_authority.expect("guard_authority is not set"), payer: self.payer.expect("payer is not set"), associated_token_program: self.associated_token_program.unwrap_or( diff --git a/e2e/anchor/src/generated/instructions/execute.rs b/e2e/anchor/src/generated/instructions/execute.rs index 410cbe4..8365564 100644 --- a/e2e/anchor/src/generated/instructions/execute.rs +++ b/e2e/anchor/src/generated/instructions/execute.rs @@ -121,7 +121,7 @@ impl ExecuteInstructionArgs { /// 1. `[]` mint /// 2. `[]` destination_account /// 3. `[]` owner_delegate -/// 4. `[]` extra_metas_account +/// 4. `[optional]` extra_metas_account (default to PDA derived from 'extraMetasAccount') /// 5. `[]` guard /// 6. `[optional]` instruction_sysvar_account (default to `Sysvar1nstructions1111111111111111111111111`) #[derive(Clone, Debug, Default)] @@ -164,6 +164,7 @@ impl ExecuteBuilder { self.owner_delegate = Some(owner_delegate); self } + /// `[optional account, default to PDA derived from 'extraMetasAccount']` #[inline(always)] pub fn extra_metas_account( &mut self, @@ -208,6 +209,14 @@ impl ExecuteBuilder { } #[allow(clippy::clone_on_copy)] pub fn instruction(&self) -> solana_instruction::Instruction { + let extra_metas_account = self.extra_metas_account.unwrap_or_else(|| { + crate::pdas::find_extra_metas_account_pda( + &self + .mint + .expect("mint is needed for extra_metas_account PDA"), + ) + .0 + }); let accounts = Execute { source_account: self.source_account.expect("source_account is not set"), mint: self.mint.expect("mint is not set"), @@ -215,9 +224,7 @@ impl ExecuteBuilder { .destination_account .expect("destination_account is not set"), owner_delegate: self.owner_delegate.expect("owner_delegate is not set"), - extra_metas_account: self - .extra_metas_account - .expect("extra_metas_account is not set"), + extra_metas_account, guard: self.guard.expect("guard is not set"), instruction_sysvar_account: self.instruction_sysvar_account.unwrap_or( solana_address::address!("Sysvar1nstructions1111111111111111111111111"), diff --git a/e2e/anchor/src/generated/instructions/initialize.rs b/e2e/anchor/src/generated/instructions/initialize.rs index ce30b3c..444ac75 100644 --- a/e2e/anchor/src/generated/instructions/initialize.rs +++ b/e2e/anchor/src/generated/instructions/initialize.rs @@ -94,7 +94,7 @@ impl Default for InitializeInstructionData { /// /// ### Accounts: /// -/// 0. `[writable]` extra_metas_account +/// 0. `[writable, optional]` extra_metas_account (default to PDA derived from 'extraMetasAccount') /// 1. `[]` guard /// 2. `[]` mint /// 3. `[writable, signer]` transfer_hook_authority @@ -115,6 +115,7 @@ impl InitializeBuilder { pub fn new() -> Self { Self::default() } + /// `[optional account, default to PDA derived from 'extraMetasAccount']` #[inline(always)] pub fn extra_metas_account( &mut self, @@ -169,10 +170,16 @@ impl InitializeBuilder { } #[allow(clippy::clone_on_copy)] pub fn instruction(&self) -> solana_instruction::Instruction { + let extra_metas_account = self.extra_metas_account.unwrap_or_else(|| { + crate::pdas::find_extra_metas_account_pda( + &self + .mint + .expect("mint is needed for extra_metas_account PDA"), + ) + .0 + }); let accounts = Initialize { - extra_metas_account: self - .extra_metas_account - .expect("extra_metas_account is not set"), + extra_metas_account, guard: self.guard.expect("guard is not set"), mint: self.mint.expect("mint is not set"), transfer_hook_authority: self diff --git a/e2e/anchor/src/generated/instructions/update_guard.rs b/e2e/anchor/src/generated/instructions/update_guard.rs index 9eb70a1..530eaf9 100644 --- a/e2e/anchor/src/generated/instructions/update_guard.rs +++ b/e2e/anchor/src/generated/instructions/update_guard.rs @@ -114,9 +114,9 @@ impl UpdateGuardInstructionArgs { /// /// ### Accounts: /// -/// 0. `[writable]` guard +/// 0. `[writable, optional]` guard (default to PDA derived from 'guard') /// 1. `[]` mint -/// 2. `[]` token_account +/// 2. `[optional]` token_account (default to PDA derived from 'tokenAccount') /// 3. `[signer]` guard_authority /// 4. `[optional]` token_program (default to `TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb`) /// 5. `[optional]` system_program (default to `11111111111111111111111111111111`) @@ -138,6 +138,7 @@ impl UpdateGuardBuilder { pub fn new() -> Self { Self::default() } + /// `[optional account, default to PDA derived from 'guard']` #[inline(always)] pub fn guard(&mut self, guard: solana_address::Address) -> &mut Self { self.guard = Some(guard); @@ -148,6 +149,7 @@ impl UpdateGuardBuilder { self.mint = Some(mint); self } + /// `[optional account, default to PDA derived from 'tokenAccount']` #[inline(always)] pub fn token_account(&mut self, token_account: solana_address::Address) -> &mut Self { self.token_account = Some(token_account); @@ -207,10 +209,32 @@ impl UpdateGuardBuilder { } #[allow(clippy::clone_on_copy)] pub fn instruction(&self) -> solana_instruction::Instruction { + let guard = self.guard.unwrap_or_else(|| { + crate::pdas::find_guard_pda(&self.mint.expect("mint is needed for guard PDA")).0 + }); + let token_account = self.token_account.unwrap_or_else(|| { + solana_address::Address::find_program_address( + &[ + self.guard_authority + .expect("guard_authority is needed for token_account PDA") + .as_ref(), + self.token_program + .unwrap_or(solana_address::address!( + "TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb" + )) + .as_ref(), + self.mint + .expect("mint is needed for token_account PDA") + .as_ref(), + ], + &solana_address::address!("ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL"), + ) + .0 + }); let accounts = UpdateGuard { - guard: self.guard.expect("guard is not set"), + guard, mint: self.mint.expect("mint is not set"), - token_account: self.token_account.expect("token_account is not set"), + token_account, guard_authority: self.guard_authority.expect("guard_authority is not set"), token_program: self.token_program.unwrap_or(solana_address::address!( "TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb" diff --git a/e2e/anchor/src/generated/mod.rs b/e2e/anchor/src/generated/mod.rs index e0d740a..d37d822 100644 --- a/e2e/anchor/src/generated/mod.rs +++ b/e2e/anchor/src/generated/mod.rs @@ -8,6 +8,7 @@ pub mod accounts; pub mod errors; pub mod instructions; +pub mod pdas; pub mod programs; pub mod shared; pub mod types; diff --git a/e2e/anchor/src/generated/pdas/extra_metas_account.rs b/e2e/anchor/src/generated/pdas/extra_metas_account.rs new file mode 100644 index 0000000..408a008 --- /dev/null +++ b/e2e/anchor/src/generated/pdas/extra_metas_account.rs @@ -0,0 +1,29 @@ +//! This code was AUTOGENERATED using the codama library. +//! Please DO NOT EDIT THIS FILE, instead use visitors +//! to add features, then rerun codama to update it. +//! +//! +//! + +use solana_address::Address; + +use crate::WEN_TRANSFER_GUARD_ID; + +pub const EXTRA_METAS_ACCOUNT_SEED: &'static [u8] = &[ + 101, 120, 116, 114, 97, 45, 97, 99, 99, 111, 117, 110, 116, 45, 109, 101, 116, 97, 115, +]; +pub fn create_extra_metas_account_pda( + mint: Address, + bump: u8, +) -> Result { + solana_address::Address::create_program_address( + &[EXTRA_METAS_ACCOUNT_SEED, mint.as_ref(), &[bump]], + &WEN_TRANSFER_GUARD_ID, + ) +} +pub fn find_extra_metas_account_pda(mint: &Address) -> (solana_address::Address, u8) { + solana_address::Address::find_program_address( + &[EXTRA_METAS_ACCOUNT_SEED, mint.as_ref()], + &WEN_TRANSFER_GUARD_ID, + ) +} diff --git a/e2e/anchor/src/generated/pdas/guard.rs b/e2e/anchor/src/generated/pdas/guard.rs new file mode 100644 index 0000000..a8c7888 --- /dev/null +++ b/e2e/anchor/src/generated/pdas/guard.rs @@ -0,0 +1,31 @@ +//! This code was AUTOGENERATED using the codama library. +//! Please DO NOT EDIT THIS FILE, instead use visitors +//! to add features, then rerun codama to update it. +//! +//! +//! + +use solana_address::Address; + +use crate::WEN_TRANSFER_GUARD_ID; + +pub const GUARD_SEED_0: &'static [u8] = &[ + 119, 101, 110, 95, 116, 111, 107, 101, 110, 95, 116, 114, 97, 110, 115, 102, 101, 114, 95, 103, + 117, 97, 114, 100, +]; +pub const GUARD_SEED_1: &'static [u8] = &[103, 117, 97, 114, 100, 95, 118, 49]; +pub fn create_guard_pda( + mint: Address, + bump: u8, +) -> Result { + solana_address::Address::create_program_address( + &[GUARD_SEED_0, GUARD_SEED_1, mint.as_ref(), &[bump]], + &WEN_TRANSFER_GUARD_ID, + ) +} +pub fn find_guard_pda(mint: &Address) -> (solana_address::Address, u8) { + solana_address::Address::find_program_address( + &[GUARD_SEED_0, GUARD_SEED_1, mint.as_ref()], + &WEN_TRANSFER_GUARD_ID, + ) +} diff --git a/e2e/anchor/src/generated/pdas/mod.rs b/e2e/anchor/src/generated/pdas/mod.rs new file mode 100644 index 0000000..25ee0c4 --- /dev/null +++ b/e2e/anchor/src/generated/pdas/mod.rs @@ -0,0 +1,12 @@ +//! This code was AUTOGENERATED using the codama library. +//! Please DO NOT EDIT THIS FILE, instead use visitors +//! to add features, then rerun codama to update it. +//! +//! +//! + +pub mod extra_metas_account; +pub mod guard; + +pub use self::extra_metas_account::*; +pub use self::guard::*; diff --git a/e2e/dummy/idl.json b/e2e/dummy/idl.json index b81b84d..f2e0f71 100644 --- a/e2e/dummy/idl.json +++ b/e2e/dummy/idl.json @@ -2,7 +2,44 @@ "kind": "rootNode", "program": { "kind": "programNode", - "pdas": [], + "pdas": [ + { + "kind": "pdaNode", + "name": "derivedAccount", + "seeds": [ + { + "kind": "constantPdaSeedNode", + "type": { "kind": "stringTypeNode", "encoding": "utf8" }, + "value": { "kind": "stringValueNode", "string": "derived" } + }, + { + "kind": "variablePdaSeedNode", + "name": "mint", + "type": { "kind": "publicKeyTypeNode" }, + "docs": [] + }, + { + "kind": "variablePdaSeedNode", + "name": "tokenProgram", + "type": { "kind": "publicKeyTypeNode" }, + "docs": [] + } + ], + "docs": [] + }, + { + "kind": "pdaNode", + "name": "globalConfig", + "seeds": [ + { + "kind": "constantPdaSeedNode", + "type": { "kind": "stringTypeNode", "encoding": "utf8" }, + "value": { "kind": "stringValueNode", "string": "global_config" } + } + ], + "docs": ["A PDA with only constant seeds — address is deterministic."] + } + ], "accounts": [], "instructions": [ { @@ -133,6 +170,88 @@ } ], "arguments": [] + }, + { + "kind": "instructionNode", + "name": "instruction8", + "optionalAccountStrategy": "programId", + "docs": ["Testing pdaLinkNode auto-derivation with upstream defaulted seed account"], + "accounts": [ + { + "kind": "instructionAccountNode", + "name": "mint", + "isWritable": false, + "isSigner": false, + "isOptional": false, + "docs": [] + }, + { + "kind": "instructionAccountNode", + "name": "tokenProgram", + "isWritable": false, + "isSigner": false, + "isOptional": false, + "docs": [], + "defaultValue": { + "kind": "publicKeyValueNode", + "publicKey": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA" + } + }, + { + "kind": "instructionAccountNode", + "name": "derivedAccount", + "isWritable": true, + "isSigner": false, + "isOptional": false, + "docs": [], + "defaultValue": { + "kind": "pdaValueNode", + "pda": { + "kind": "pdaLinkNode", + "name": "derivedAccount" + }, + "seeds": [ + { + "kind": "pdaSeedValueNode", + "name": "mint", + "value": { "kind": "accountValueNode", "name": "mint" } + }, + { + "kind": "pdaSeedValueNode", + "name": "tokenProgram", + "value": { "kind": "accountValueNode", "name": "tokenProgram" } + } + ] + } + } + ], + "arguments": [], + "remainingAccounts": [] + }, + { + "kind": "instructionNode", + "name": "instruction9", + "optionalAccountStrategy": "programId", + "docs": ["Testing precomputed PDA constant for zero-variable-seed linked PDA"], + "accounts": [ + { + "kind": "instructionAccountNode", + "name": "globalConfig", + "isWritable": false, + "isSigner": false, + "isOptional": false, + "docs": [], + "defaultValue": { + "kind": "pdaValueNode", + "pda": { + "kind": "pdaLinkNode", + "name": "globalConfig" + }, + "seeds": [] + } + } + ], + "arguments": [] } ], "definedTypes": [], diff --git a/e2e/dummy/src/generated/instructions/instruction8.rs b/e2e/dummy/src/generated/instructions/instruction8.rs new file mode 100644 index 0000000..03d5eb9 --- /dev/null +++ b/e2e/dummy/src/generated/instructions/instruction8.rs @@ -0,0 +1,355 @@ +//! This code was AUTOGENERATED using the codama library. +//! Please DO NOT EDIT THIS FILE, instead use visitors +//! to add features, then rerun codama to update it. +//! +//! +//! + +use borsh::BorshDeserialize; +use borsh::BorshSerialize; + +/// Accounts. +#[derive(Debug)] +pub struct Instruction8 { + pub mint: solana_address::Address, + + pub token_program: solana_address::Address, + + pub derived_account: solana_address::Address, +} + +impl Instruction8 { + pub fn instruction(&self) -> solana_instruction::Instruction { + self.instruction_with_remaining_accounts(&[]) + } + #[allow(clippy::arithmetic_side_effects)] + #[allow(clippy::vec_init_then_push)] + pub fn instruction_with_remaining_accounts( + &self, + remaining_accounts: &[solana_instruction::AccountMeta], + ) -> solana_instruction::Instruction { + let mut accounts = Vec::with_capacity(3 + remaining_accounts.len()); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.mint, false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.token_program, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + self.derived_account, + false, + )); + accounts.extend_from_slice(remaining_accounts); + let data = Instruction8InstructionData::new().try_to_vec().unwrap(); + + solana_instruction::Instruction { + program_id: crate::DUMMY_ID, + accounts, + data, + } + } +} + +#[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] +pub struct Instruction8InstructionData {} + +impl Instruction8InstructionData { + pub fn new() -> Self { + Self {} + } + + pub(crate) fn try_to_vec(&self) -> Result, std::io::Error> { + borsh::to_vec(self) + } +} + +impl Default for Instruction8InstructionData { + fn default() -> Self { + Self::new() + } +} + +/// Instruction builder for `Instruction8`. +/// +/// ### Accounts: +/// +/// 0. `[]` mint +/// 1. `[optional]` token_program (default to `TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA`) +/// 2. `[writable, optional]` derived_account (default to PDA derived from 'derivedAccount') +#[derive(Clone, Debug, Default)] +pub struct Instruction8Builder { + mint: Option, + token_program: Option, + derived_account: Option, + __remaining_accounts: Vec, +} + +impl Instruction8Builder { + pub fn new() -> Self { + Self::default() + } + #[inline(always)] + pub fn mint(&mut self, mint: solana_address::Address) -> &mut Self { + self.mint = Some(mint); + self + } + /// `[optional account, default to 'TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA']` + #[inline(always)] + pub fn token_program(&mut self, token_program: solana_address::Address) -> &mut Self { + self.token_program = Some(token_program); + self + } + /// `[optional account, default to PDA derived from 'derivedAccount']` + #[inline(always)] + pub fn derived_account(&mut self, derived_account: solana_address::Address) -> &mut Self { + self.derived_account = Some(derived_account); + self + } + /// Add an additional account to the instruction. + #[inline(always)] + pub fn add_remaining_account(&mut self, account: solana_instruction::AccountMeta) -> &mut Self { + self.__remaining_accounts.push(account); + self + } + /// Add additional accounts to the instruction. + #[inline(always)] + pub fn add_remaining_accounts( + &mut self, + accounts: &[solana_instruction::AccountMeta], + ) -> &mut Self { + self.__remaining_accounts.extend_from_slice(accounts); + self + } + #[allow(clippy::clone_on_copy)] + pub fn instruction(&self) -> solana_instruction::Instruction { + let derived_account = self.derived_account.unwrap_or_else(|| { + crate::pdas::find_derived_account_pda( + &self.mint.expect("mint is needed for derived_account PDA"), + &self.token_program.unwrap_or(solana_address::address!( + "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA" + )), + ) + .0 + }); + let accounts = Instruction8 { + mint: self.mint.expect("mint is not set"), + token_program: self.token_program.unwrap_or(solana_address::address!( + "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA" + )), + derived_account, + }; + + accounts.instruction_with_remaining_accounts(&self.__remaining_accounts) + } +} + +/// `instruction8` CPI accounts. +pub struct Instruction8CpiAccounts<'a, 'b> { + pub mint: &'b solana_account_info::AccountInfo<'a>, + + pub token_program: &'b solana_account_info::AccountInfo<'a>, + + pub derived_account: &'b solana_account_info::AccountInfo<'a>, +} + +/// `instruction8` CPI instruction. +pub struct Instruction8Cpi<'a, 'b> { + /// The program to invoke. + pub __program: &'b solana_account_info::AccountInfo<'a>, + + pub mint: &'b solana_account_info::AccountInfo<'a>, + + pub token_program: &'b solana_account_info::AccountInfo<'a>, + + pub derived_account: &'b solana_account_info::AccountInfo<'a>, +} + +impl<'a, 'b> Instruction8Cpi<'a, 'b> { + pub fn new( + program: &'b solana_account_info::AccountInfo<'a>, + accounts: Instruction8CpiAccounts<'a, 'b>, + ) -> Self { + Self { + __program: program, + mint: accounts.mint, + token_program: accounts.token_program, + derived_account: accounts.derived_account, + } + } + #[inline(always)] + pub fn invoke(&self) -> solana_program_error::ProgramResult { + self.invoke_signed_with_remaining_accounts(&[], &[]) + } + #[inline(always)] + pub fn invoke_with_remaining_accounts( + &self, + remaining_accounts: &[(&'b solana_account_info::AccountInfo<'a>, bool, bool)], + ) -> solana_program_error::ProgramResult { + self.invoke_signed_with_remaining_accounts(&[], remaining_accounts) + } + #[inline(always)] + pub fn invoke_signed(&self, signers_seeds: &[&[&[u8]]]) -> solana_program_error::ProgramResult { + self.invoke_signed_with_remaining_accounts(signers_seeds, &[]) + } + #[allow(clippy::arithmetic_side_effects)] + #[allow(clippy::clone_on_copy)] + #[allow(clippy::vec_init_then_push)] + pub fn invoke_signed_with_remaining_accounts( + &self, + signers_seeds: &[&[&[u8]]], + remaining_accounts: &[(&'b solana_account_info::AccountInfo<'a>, bool, bool)], + ) -> solana_program_error::ProgramResult { + let mut accounts = Vec::with_capacity(3 + remaining_accounts.len()); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.mint.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.token_program.key, + false, + )); + accounts.push(solana_instruction::AccountMeta::new( + *self.derived_account.key, + false, + )); + remaining_accounts.iter().for_each(|remaining_account| { + accounts.push(solana_instruction::AccountMeta { + pubkey: *remaining_account.0.key, + is_signer: remaining_account.1, + is_writable: remaining_account.2, + }) + }); + let data = Instruction8InstructionData::new().try_to_vec().unwrap(); + + let instruction = solana_instruction::Instruction { + program_id: crate::DUMMY_ID, + accounts, + data, + }; + let mut account_infos = Vec::with_capacity(4 + remaining_accounts.len()); + account_infos.push(self.__program.clone()); + account_infos.push(self.mint.clone()); + account_infos.push(self.token_program.clone()); + account_infos.push(self.derived_account.clone()); + remaining_accounts + .iter() + .for_each(|remaining_account| account_infos.push(remaining_account.0.clone())); + + if signers_seeds.is_empty() { + solana_cpi::invoke(&instruction, &account_infos) + } else { + solana_cpi::invoke_signed(&instruction, &account_infos, signers_seeds) + } + } +} + +/// Instruction builder for `Instruction8` via CPI. +/// +/// ### Accounts: +/// +/// 0. `[]` mint +/// 1. `[]` token_program +/// 2. `[writable]` derived_account +#[derive(Clone, Debug)] +pub struct Instruction8CpiBuilder<'a, 'b> { + instruction: Box>, +} + +impl<'a, 'b> Instruction8CpiBuilder<'a, 'b> { + pub fn new(program: &'b solana_account_info::AccountInfo<'a>) -> Self { + let instruction = Box::new(Instruction8CpiBuilderInstruction { + __program: program, + mint: None, + token_program: None, + derived_account: None, + __remaining_accounts: Vec::new(), + }); + Self { instruction } + } + #[inline(always)] + pub fn mint(&mut self, mint: &'b solana_account_info::AccountInfo<'a>) -> &mut Self { + self.instruction.mint = Some(mint); + self + } + #[inline(always)] + pub fn token_program( + &mut self, + token_program: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.token_program = Some(token_program); + self + } + #[inline(always)] + pub fn derived_account( + &mut self, + derived_account: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.derived_account = Some(derived_account); + self + } + /// Add an additional account to the instruction. + #[inline(always)] + pub fn add_remaining_account( + &mut self, + account: &'b solana_account_info::AccountInfo<'a>, + is_writable: bool, + is_signer: bool, + ) -> &mut Self { + self.instruction + .__remaining_accounts + .push((account, is_writable, is_signer)); + self + } + /// Add additional accounts to the instruction. + /// + /// Each account is represented by a tuple of the `AccountInfo`, a `bool` indicating whether the account is writable or not, + /// and a `bool` indicating whether the account is a signer or not. + #[inline(always)] + pub fn add_remaining_accounts( + &mut self, + accounts: &[(&'b solana_account_info::AccountInfo<'a>, bool, bool)], + ) -> &mut Self { + self.instruction + .__remaining_accounts + .extend_from_slice(accounts); + self + } + #[inline(always)] + pub fn invoke(&self) -> solana_program_error::ProgramResult { + self.invoke_signed(&[]) + } + #[allow(clippy::clone_on_copy)] + #[allow(clippy::vec_init_then_push)] + pub fn invoke_signed(&self, signers_seeds: &[&[&[u8]]]) -> solana_program_error::ProgramResult { + let instruction = Instruction8Cpi { + __program: self.instruction.__program, + + mint: self.instruction.mint.expect("mint is not set"), + + token_program: self + .instruction + .token_program + .expect("token_program is not set"), + + derived_account: self + .instruction + .derived_account + .expect("derived_account is not set"), + }; + instruction.invoke_signed_with_remaining_accounts( + signers_seeds, + &self.instruction.__remaining_accounts, + ) + } +} + +#[derive(Clone, Debug)] +struct Instruction8CpiBuilderInstruction<'a, 'b> { + __program: &'b solana_account_info::AccountInfo<'a>, + mint: Option<&'b solana_account_info::AccountInfo<'a>>, + token_program: Option<&'b solana_account_info::AccountInfo<'a>>, + derived_account: Option<&'b solana_account_info::AccountInfo<'a>>, + /// Additional instruction accounts `(AccountInfo, is_writable, is_signer)`. + __remaining_accounts: Vec<(&'b solana_account_info::AccountInfo<'a>, bool, bool)>, +} diff --git a/e2e/dummy/src/generated/instructions/instruction9.rs b/e2e/dummy/src/generated/instructions/instruction9.rs new file mode 100644 index 0000000..95e628a --- /dev/null +++ b/e2e/dummy/src/generated/instructions/instruction9.rs @@ -0,0 +1,271 @@ +//! This code was AUTOGENERATED using the codama library. +//! Please DO NOT EDIT THIS FILE, instead use visitors +//! to add features, then rerun codama to update it. +//! +//! +//! + +use borsh::BorshDeserialize; +use borsh::BorshSerialize; + +/// Accounts. +#[derive(Debug)] +pub struct Instruction9 { + pub global_config: solana_address::Address, +} + +impl Instruction9 { + pub fn instruction(&self) -> solana_instruction::Instruction { + self.instruction_with_remaining_accounts(&[]) + } + #[allow(clippy::arithmetic_side_effects)] + #[allow(clippy::vec_init_then_push)] + pub fn instruction_with_remaining_accounts( + &self, + remaining_accounts: &[solana_instruction::AccountMeta], + ) -> solana_instruction::Instruction { + let mut accounts = Vec::with_capacity(1 + remaining_accounts.len()); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.global_config, + false, + )); + accounts.extend_from_slice(remaining_accounts); + let data = Instruction9InstructionData::new().try_to_vec().unwrap(); + + solana_instruction::Instruction { + program_id: crate::DUMMY_ID, + accounts, + data, + } + } +} + +#[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] +pub struct Instruction9InstructionData {} + +impl Instruction9InstructionData { + pub fn new() -> Self { + Self {} + } + + pub(crate) fn try_to_vec(&self) -> Result, std::io::Error> { + borsh::to_vec(self) + } +} + +impl Default for Instruction9InstructionData { + fn default() -> Self { + Self::new() + } +} + +/// Instruction builder for `Instruction9`. +/// +/// ### Accounts: +/// +/// 0. `[optional]` global_config (default to PDA derived from 'globalConfig') +#[derive(Clone, Debug, Default)] +pub struct Instruction9Builder { + global_config: Option, + __remaining_accounts: Vec, +} + +impl Instruction9Builder { + pub fn new() -> Self { + Self::default() + } + /// `[optional account, default to PDA derived from 'globalConfig']` + #[inline(always)] + pub fn global_config(&mut self, global_config: solana_address::Address) -> &mut Self { + self.global_config = Some(global_config); + self + } + /// Add an additional account to the instruction. + #[inline(always)] + pub fn add_remaining_account(&mut self, account: solana_instruction::AccountMeta) -> &mut Self { + self.__remaining_accounts.push(account); + self + } + /// Add additional accounts to the instruction. + #[inline(always)] + pub fn add_remaining_accounts( + &mut self, + accounts: &[solana_instruction::AccountMeta], + ) -> &mut Self { + self.__remaining_accounts.extend_from_slice(accounts); + self + } + #[allow(clippy::clone_on_copy)] + pub fn instruction(&self) -> solana_instruction::Instruction { + let global_config = self + .global_config + .unwrap_or(crate::pdas::GLOBAL_CONFIG_ADDRESS); + let accounts = Instruction9 { global_config }; + + accounts.instruction_with_remaining_accounts(&self.__remaining_accounts) + } +} + +/// `instruction9` CPI accounts. +pub struct Instruction9CpiAccounts<'a, 'b> { + pub global_config: &'b solana_account_info::AccountInfo<'a>, +} + +/// `instruction9` CPI instruction. +pub struct Instruction9Cpi<'a, 'b> { + /// The program to invoke. + pub __program: &'b solana_account_info::AccountInfo<'a>, + + pub global_config: &'b solana_account_info::AccountInfo<'a>, +} + +impl<'a, 'b> Instruction9Cpi<'a, 'b> { + pub fn new( + program: &'b solana_account_info::AccountInfo<'a>, + accounts: Instruction9CpiAccounts<'a, 'b>, + ) -> Self { + Self { + __program: program, + global_config: accounts.global_config, + } + } + #[inline(always)] + pub fn invoke(&self) -> solana_program_error::ProgramResult { + self.invoke_signed_with_remaining_accounts(&[], &[]) + } + #[inline(always)] + pub fn invoke_with_remaining_accounts( + &self, + remaining_accounts: &[(&'b solana_account_info::AccountInfo<'a>, bool, bool)], + ) -> solana_program_error::ProgramResult { + self.invoke_signed_with_remaining_accounts(&[], remaining_accounts) + } + #[inline(always)] + pub fn invoke_signed(&self, signers_seeds: &[&[&[u8]]]) -> solana_program_error::ProgramResult { + self.invoke_signed_with_remaining_accounts(signers_seeds, &[]) + } + #[allow(clippy::arithmetic_side_effects)] + #[allow(clippy::clone_on_copy)] + #[allow(clippy::vec_init_then_push)] + pub fn invoke_signed_with_remaining_accounts( + &self, + signers_seeds: &[&[&[u8]]], + remaining_accounts: &[(&'b solana_account_info::AccountInfo<'a>, bool, bool)], + ) -> solana_program_error::ProgramResult { + let mut accounts = Vec::with_capacity(1 + remaining_accounts.len()); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.global_config.key, + false, + )); + remaining_accounts.iter().for_each(|remaining_account| { + accounts.push(solana_instruction::AccountMeta { + pubkey: *remaining_account.0.key, + is_signer: remaining_account.1, + is_writable: remaining_account.2, + }) + }); + let data = Instruction9InstructionData::new().try_to_vec().unwrap(); + + let instruction = solana_instruction::Instruction { + program_id: crate::DUMMY_ID, + accounts, + data, + }; + let mut account_infos = Vec::with_capacity(2 + remaining_accounts.len()); + account_infos.push(self.__program.clone()); + account_infos.push(self.global_config.clone()); + remaining_accounts + .iter() + .for_each(|remaining_account| account_infos.push(remaining_account.0.clone())); + + if signers_seeds.is_empty() { + solana_cpi::invoke(&instruction, &account_infos) + } else { + solana_cpi::invoke_signed(&instruction, &account_infos, signers_seeds) + } + } +} + +/// Instruction builder for `Instruction9` via CPI. +/// +/// ### Accounts: +/// +/// 0. `[]` global_config +#[derive(Clone, Debug)] +pub struct Instruction9CpiBuilder<'a, 'b> { + instruction: Box>, +} + +impl<'a, 'b> Instruction9CpiBuilder<'a, 'b> { + pub fn new(program: &'b solana_account_info::AccountInfo<'a>) -> Self { + let instruction = Box::new(Instruction9CpiBuilderInstruction { + __program: program, + global_config: None, + __remaining_accounts: Vec::new(), + }); + Self { instruction } + } + #[inline(always)] + pub fn global_config( + &mut self, + global_config: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.global_config = Some(global_config); + self + } + /// Add an additional account to the instruction. + #[inline(always)] + pub fn add_remaining_account( + &mut self, + account: &'b solana_account_info::AccountInfo<'a>, + is_writable: bool, + is_signer: bool, + ) -> &mut Self { + self.instruction + .__remaining_accounts + .push((account, is_writable, is_signer)); + self + } + /// Add additional accounts to the instruction. + /// + /// Each account is represented by a tuple of the `AccountInfo`, a `bool` indicating whether the account is writable or not, + /// and a `bool` indicating whether the account is a signer or not. + #[inline(always)] + pub fn add_remaining_accounts( + &mut self, + accounts: &[(&'b solana_account_info::AccountInfo<'a>, bool, bool)], + ) -> &mut Self { + self.instruction + .__remaining_accounts + .extend_from_slice(accounts); + self + } + #[inline(always)] + pub fn invoke(&self) -> solana_program_error::ProgramResult { + self.invoke_signed(&[]) + } + #[allow(clippy::clone_on_copy)] + #[allow(clippy::vec_init_then_push)] + pub fn invoke_signed(&self, signers_seeds: &[&[&[u8]]]) -> solana_program_error::ProgramResult { + let instruction = Instruction9Cpi { + __program: self.instruction.__program, + + global_config: self + .instruction + .global_config + .expect("global_config is not set"), + }; + instruction.invoke_signed_with_remaining_accounts( + signers_seeds, + &self.instruction.__remaining_accounts, + ) + } +} + +#[derive(Clone, Debug)] +struct Instruction9CpiBuilderInstruction<'a, 'b> { + __program: &'b solana_account_info::AccountInfo<'a>, + global_config: Option<&'b solana_account_info::AccountInfo<'a>>, + /// Additional instruction accounts `(AccountInfo, is_writable, is_signer)`. + __remaining_accounts: Vec<(&'b solana_account_info::AccountInfo<'a>, bool, bool)>, +} diff --git a/e2e/dummy/src/generated/instructions/mod.rs b/e2e/dummy/src/generated/instructions/mod.rs index a0205b0..5f90c99 100644 --- a/e2e/dummy/src/generated/instructions/mod.rs +++ b/e2e/dummy/src/generated/instructions/mod.rs @@ -12,6 +12,8 @@ pub(crate) mod r#instruction4; pub(crate) mod r#instruction5; pub(crate) mod r#instruction6; pub(crate) mod r#instruction7; +pub(crate) mod r#instruction8; +pub(crate) mod r#instruction9; pub use self::r#instruction1::*; pub use self::r#instruction2::*; @@ -20,3 +22,5 @@ pub use self::r#instruction4::*; pub use self::r#instruction5::*; pub use self::r#instruction6::*; pub use self::r#instruction7::*; +pub use self::r#instruction8::*; +pub use self::r#instruction9::*; diff --git a/e2e/dummy/src/generated/mod.rs b/e2e/dummy/src/generated/mod.rs index 9c64a4b..374b603 100644 --- a/e2e/dummy/src/generated/mod.rs +++ b/e2e/dummy/src/generated/mod.rs @@ -7,6 +7,7 @@ pub mod errors; pub mod instructions; +pub mod pdas; pub mod programs; pub(crate) use programs::*; diff --git a/e2e/dummy/src/generated/pdas/derived_account.rs b/e2e/dummy/src/generated/pdas/derived_account.rs new file mode 100644 index 0000000..1061621 --- /dev/null +++ b/e2e/dummy/src/generated/pdas/derived_account.rs @@ -0,0 +1,36 @@ +//! This code was AUTOGENERATED using the codama library. +//! Please DO NOT EDIT THIS FILE, instead use visitors +//! to add features, then rerun codama to update it. +//! +//! +//! + +use solana_address::Address; + +use crate::DUMMY_ID; + +pub const DERIVED_ACCOUNT_SEED: &'static [u8] = b"derived"; +pub fn create_derived_account_pda( + mint: Address, + token_program: Address, + bump: u8, +) -> Result { + solana_address::Address::create_program_address( + &[ + DERIVED_ACCOUNT_SEED, + mint.as_ref(), + token_program.as_ref(), + &[bump], + ], + &DUMMY_ID, + ) +} +pub fn find_derived_account_pda( + mint: &Address, + token_program: &Address, +) -> (solana_address::Address, u8) { + solana_address::Address::find_program_address( + &[DERIVED_ACCOUNT_SEED, mint.as_ref(), token_program.as_ref()], + &DUMMY_ID, + ) +} diff --git a/e2e/dummy/src/generated/pdas/global_config.rs b/e2e/dummy/src/generated/pdas/global_config.rs new file mode 100644 index 0000000..bcca593 --- /dev/null +++ b/e2e/dummy/src/generated/pdas/global_config.rs @@ -0,0 +1,23 @@ +//! This code was AUTOGENERATED using the codama library. +//! Please DO NOT EDIT THIS FILE, instead use visitors +//! to add features, then rerun codama to update it. +//! +//! +//! + +use crate::DUMMY_ID; + +pub const GLOBAL_CONFIG_SEED: &'static [u8] = b"global_config"; + +pub const GLOBAL_CONFIG_ADDRESS: solana_address::Address = + solana_address::address!("9gM2qHs9cK8n6DoWe2HsoVjhJzsW9jt4je7r6NNtgRsG"); +/// A PDA with only constant seeds — address is deterministic. +pub fn create_global_config_pda( + bump: u8, +) -> Result { + solana_address::Address::create_program_address(&[GLOBAL_CONFIG_SEED, &[bump]], &DUMMY_ID) +} +/// A PDA with only constant seeds — address is deterministic. +pub fn find_global_config_pda() -> (solana_address::Address, u8) { + solana_address::Address::find_program_address(&[GLOBAL_CONFIG_SEED], &DUMMY_ID) +} diff --git a/e2e/dummy/src/generated/pdas/mod.rs b/e2e/dummy/src/generated/pdas/mod.rs new file mode 100644 index 0000000..9729cc3 --- /dev/null +++ b/e2e/dummy/src/generated/pdas/mod.rs @@ -0,0 +1,12 @@ +//! This code was AUTOGENERATED using the codama library. +//! Please DO NOT EDIT THIS FILE, instead use visitors +//! to add features, then rerun codama to update it. +//! +//! +//! + +pub mod derived_account; +pub mod global_config; + +pub use self::derived_account::*; +pub use self::global_config::*; diff --git a/e2e/governance/src/generated/accounts/governance_v1.rs b/e2e/governance/src/generated/accounts/governance_v1.rs index 755fde5..50a6f99 100644 --- a/e2e/governance/src/generated/accounts/governance_v1.rs +++ b/e2e/governance/src/generated/accounts/governance_v1.rs @@ -28,7 +28,7 @@ impl GovernanceV1 { /// 0. `GovernanceV1::PREFIX` /// 1. realm (`Address`) /// 2. seed (`Address`) - pub const PREFIX: &'static [u8] = "account-governance".as_bytes(); + pub const PREFIX: &'static [u8] = b"account-governance"; pub fn create_pda( realm: Address, @@ -37,7 +37,7 @@ impl GovernanceV1 { ) -> Result { solana_address::Address::create_program_address( &[ - "account-governance".as_bytes(), + b"account-governance", realm.as_ref(), seed.as_ref(), &[bump], @@ -48,11 +48,7 @@ impl GovernanceV1 { pub fn find_pda(realm: &Address, seed: &Address) -> (solana_address::Address, u8) { solana_address::Address::find_program_address( - &[ - "account-governance".as_bytes(), - realm.as_ref(), - seed.as_ref(), - ], + &[b"account-governance", realm.as_ref(), seed.as_ref()], &crate::SPL_GOVERNANCE_ID, ) } diff --git a/e2e/governance/src/generated/accounts/governance_v2.rs b/e2e/governance/src/generated/accounts/governance_v2.rs index d85b261..344834d 100644 --- a/e2e/governance/src/generated/accounts/governance_v2.rs +++ b/e2e/governance/src/generated/accounts/governance_v2.rs @@ -32,7 +32,7 @@ impl GovernanceV2 { /// 0. `GovernanceV2::PREFIX` /// 1. realm (`Address`) /// 2. seed (`Address`) - pub const PREFIX: &'static [u8] = "account-governance".as_bytes(); + pub const PREFIX: &'static [u8] = b"account-governance"; pub fn create_pda( realm: Address, @@ -41,7 +41,7 @@ impl GovernanceV2 { ) -> Result { solana_address::Address::create_program_address( &[ - "account-governance".as_bytes(), + b"account-governance", realm.as_ref(), seed.as_ref(), &[bump], @@ -52,11 +52,7 @@ impl GovernanceV2 { pub fn find_pda(realm: &Address, seed: &Address) -> (solana_address::Address, u8) { solana_address::Address::find_program_address( - &[ - "account-governance".as_bytes(), - realm.as_ref(), - seed.as_ref(), - ], + &[b"account-governance", realm.as_ref(), seed.as_ref()], &crate::SPL_GOVERNANCE_ID, ) } diff --git a/e2e/governance/src/generated/accounts/legacy_token_owner_record.rs b/e2e/governance/src/generated/accounts/legacy_token_owner_record.rs index 7d67b53..c6cab3d 100644 --- a/e2e/governance/src/generated/accounts/legacy_token_owner_record.rs +++ b/e2e/governance/src/generated/accounts/legacy_token_owner_record.rs @@ -34,7 +34,7 @@ impl LegacyTokenOwnerRecord { /// 1. realm (`Address`) /// 2. governing_token_mint (`Address`) /// 3. governing_token_owner (`Address`) - pub const PREFIX: &'static [u8] = "governance".as_bytes(); + pub const PREFIX: &'static [u8] = b"governance"; pub fn create_pda( realm: Address, @@ -44,7 +44,7 @@ impl LegacyTokenOwnerRecord { ) -> Result { solana_address::Address::create_program_address( &[ - "governance".as_bytes(), + b"governance", realm.as_ref(), governing_token_mint.as_ref(), governing_token_owner.as_ref(), @@ -61,7 +61,7 @@ impl LegacyTokenOwnerRecord { ) -> (solana_address::Address, u8) { solana_address::Address::find_program_address( &[ - "governance".as_bytes(), + b"governance", realm.as_ref(), governing_token_mint.as_ref(), governing_token_owner.as_ref(), diff --git a/e2e/governance/src/generated/accounts/proposal_deposit.rs b/e2e/governance/src/generated/accounts/proposal_deposit.rs index e608fba..05f31df 100644 --- a/e2e/governance/src/generated/accounts/proposal_deposit.rs +++ b/e2e/governance/src/generated/accounts/proposal_deposit.rs @@ -26,7 +26,7 @@ impl ProposalDeposit { /// 0. `ProposalDeposit::PREFIX` /// 1. proposal (`Address`) /// 2. deposit_payer (`Address`) - pub const PREFIX: &'static [u8] = "proposal-deposit".as_bytes(); + pub const PREFIX: &'static [u8] = b"proposal-deposit"; pub fn create_pda( proposal: Address, @@ -35,7 +35,7 @@ impl ProposalDeposit { ) -> Result { solana_address::Address::create_program_address( &[ - "proposal-deposit".as_bytes(), + b"proposal-deposit", proposal.as_ref(), deposit_payer.as_ref(), &[bump], @@ -47,7 +47,7 @@ impl ProposalDeposit { pub fn find_pda(proposal: &Address, deposit_payer: &Address) -> (solana_address::Address, u8) { solana_address::Address::find_program_address( &[ - "proposal-deposit".as_bytes(), + b"proposal-deposit", proposal.as_ref(), deposit_payer.as_ref(), ], diff --git a/e2e/governance/src/generated/accounts/proposal_instruction_v1.rs b/e2e/governance/src/generated/accounts/proposal_instruction_v1.rs index a1ccf2e..105eb50 100644 --- a/e2e/governance/src/generated/accounts/proposal_instruction_v1.rs +++ b/e2e/governance/src/generated/accounts/proposal_instruction_v1.rs @@ -33,7 +33,7 @@ impl ProposalInstructionV1 { /// 1. proposal (`Address`) /// 2. option_index (`u8`) /// 3. index (`u16`) - pub const PREFIX: &'static [u8] = "governance".as_bytes(); + pub const PREFIX: &'static [u8] = b"governance"; pub fn create_pda( proposal: Address, @@ -43,7 +43,7 @@ impl ProposalInstructionV1 { ) -> Result { solana_address::Address::create_program_address( &[ - "governance".as_bytes(), + b"governance", proposal.as_ref(), option_index.to_string().as_ref(), index.to_string().as_ref(), @@ -60,7 +60,7 @@ impl ProposalInstructionV1 { ) -> (solana_address::Address, u8) { solana_address::Address::find_program_address( &[ - "governance".as_bytes(), + b"governance", proposal.as_ref(), option_index.to_string().as_ref(), index.to_string().as_ref(), diff --git a/e2e/governance/src/generated/accounts/proposal_transaction_v2.rs b/e2e/governance/src/generated/accounts/proposal_transaction_v2.rs index 16fe28a..e1b5c2b 100644 --- a/e2e/governance/src/generated/accounts/proposal_transaction_v2.rs +++ b/e2e/governance/src/generated/accounts/proposal_transaction_v2.rs @@ -35,7 +35,7 @@ impl ProposalTransactionV2 { /// 1. proposal (`Address`) /// 2. option_index (`u8`) /// 3. index (`u16`) - pub const PREFIX: &'static [u8] = "governance".as_bytes(); + pub const PREFIX: &'static [u8] = b"governance"; pub fn create_pda( proposal: Address, @@ -45,7 +45,7 @@ impl ProposalTransactionV2 { ) -> Result { solana_address::Address::create_program_address( &[ - "governance".as_bytes(), + b"governance", proposal.as_ref(), option_index.to_string().as_ref(), index.to_string().as_ref(), @@ -62,7 +62,7 @@ impl ProposalTransactionV2 { ) -> (solana_address::Address, u8) { solana_address::Address::find_program_address( &[ - "governance".as_bytes(), + b"governance", proposal.as_ref(), option_index.to_string().as_ref(), index.to_string().as_ref(), diff --git a/e2e/governance/src/generated/accounts/proposal_v1.rs b/e2e/governance/src/generated/accounts/proposal_v1.rs index 0173a81..bc51e95 100644 --- a/e2e/governance/src/generated/accounts/proposal_v1.rs +++ b/e2e/governance/src/generated/accounts/proposal_v1.rs @@ -52,7 +52,7 @@ impl ProposalV1 { /// 1. governance (`Address`) /// 2. governing_token_mint (`Address`) /// 3. proposal_seed (`Address`) - pub const PREFIX: &'static [u8] = "governance".as_bytes(); + pub const PREFIX: &'static [u8] = b"governance"; pub fn create_pda( governance: Address, @@ -62,7 +62,7 @@ impl ProposalV1 { ) -> Result { solana_address::Address::create_program_address( &[ - "governance".as_bytes(), + b"governance", governance.as_ref(), governing_token_mint.as_ref(), proposal_seed.as_ref(), @@ -79,7 +79,7 @@ impl ProposalV1 { ) -> (solana_address::Address, u8) { solana_address::Address::find_program_address( &[ - "governance".as_bytes(), + b"governance", governance.as_ref(), governing_token_mint.as_ref(), proposal_seed.as_ref(), diff --git a/e2e/governance/src/generated/accounts/proposal_v2.rs b/e2e/governance/src/generated/accounts/proposal_v2.rs index 376ee88..10cecc8 100644 --- a/e2e/governance/src/generated/accounts/proposal_v2.rs +++ b/e2e/governance/src/generated/accounts/proposal_v2.rs @@ -58,7 +58,7 @@ impl ProposalV2 { /// 1. governance (`Address`) /// 2. governing_token_mint (`Address`) /// 3. proposal_seed (`Address`) - pub const PREFIX: &'static [u8] = "governance".as_bytes(); + pub const PREFIX: &'static [u8] = b"governance"; pub fn create_pda( governance: Address, @@ -68,7 +68,7 @@ impl ProposalV2 { ) -> Result { solana_address::Address::create_program_address( &[ - "governance".as_bytes(), + b"governance", governance.as_ref(), governing_token_mint.as_ref(), proposal_seed.as_ref(), @@ -85,7 +85,7 @@ impl ProposalV2 { ) -> (solana_address::Address, u8) { solana_address::Address::find_program_address( &[ - "governance".as_bytes(), + b"governance", governance.as_ref(), governing_token_mint.as_ref(), proposal_seed.as_ref(), diff --git a/e2e/governance/src/generated/accounts/realm_config_account.rs b/e2e/governance/src/generated/accounts/realm_config_account.rs index d5e0fb2..f5194b3 100644 --- a/e2e/governance/src/generated/accounts/realm_config_account.rs +++ b/e2e/governance/src/generated/accounts/realm_config_account.rs @@ -28,21 +28,21 @@ impl RealmConfigAccount { /// /// 0. `RealmConfigAccount::PREFIX` /// 1. realm (`Address`) - pub const PREFIX: &'static [u8] = "realm-config".as_bytes(); + pub const PREFIX: &'static [u8] = b"realm-config"; pub fn create_pda( realm: Address, bump: u8, ) -> Result { solana_address::Address::create_program_address( - &["realm-config".as_bytes(), realm.as_ref(), &[bump]], + &[b"realm-config", realm.as_ref(), &[bump]], &crate::SPL_GOVERNANCE_ID, ) } pub fn find_pda(realm: &Address) -> (solana_address::Address, u8) { solana_address::Address::find_program_address( - &["realm-config".as_bytes(), realm.as_ref()], + &[b"realm-config", realm.as_ref()], &crate::SPL_GOVERNANCE_ID, ) } diff --git a/e2e/governance/src/generated/accounts/realm_v1.rs b/e2e/governance/src/generated/accounts/realm_v1.rs index 68774cf..7cb0e90 100644 --- a/e2e/governance/src/generated/accounts/realm_v1.rs +++ b/e2e/governance/src/generated/accounts/realm_v1.rs @@ -30,21 +30,21 @@ impl RealmV1 { /// /// 0. `RealmV1::PREFIX` /// 1. name (`TrailingStr`) - pub const PREFIX: &'static [u8] = "governance".as_bytes(); + pub const PREFIX: &'static [u8] = b"governance"; pub fn create_pda( name: TrailingStr, bump: u8, ) -> Result { solana_address::Address::create_program_address( - &["governance".as_bytes(), name.to_string().as_ref(), &[bump]], + &[b"governance", name.to_string().as_ref(), &[bump]], &crate::SPL_GOVERNANCE_ID, ) } pub fn find_pda(name: TrailingStr) -> (solana_address::Address, u8) { solana_address::Address::find_program_address( - &["governance".as_bytes(), name.to_string().as_ref()], + &[b"governance", name.to_string().as_ref()], &crate::SPL_GOVERNANCE_ID, ) } diff --git a/e2e/governance/src/generated/accounts/realm_v2.rs b/e2e/governance/src/generated/accounts/realm_v2.rs index cda3432..5d5d98a 100644 --- a/e2e/governance/src/generated/accounts/realm_v2.rs +++ b/e2e/governance/src/generated/accounts/realm_v2.rs @@ -31,21 +31,21 @@ impl RealmV2 { /// /// 0. `RealmV2::PREFIX` /// 1. name (`TrailingStr`) - pub const PREFIX: &'static [u8] = "governance".as_bytes(); + pub const PREFIX: &'static [u8] = b"governance"; pub fn create_pda( name: TrailingStr, bump: u8, ) -> Result { solana_address::Address::create_program_address( - &["governance".as_bytes(), name.to_string().as_ref(), &[bump]], + &[b"governance", name.to_string().as_ref(), &[bump]], &crate::SPL_GOVERNANCE_ID, ) } pub fn find_pda(name: TrailingStr) -> (solana_address::Address, u8) { solana_address::Address::find_program_address( - &["governance".as_bytes(), name.to_string().as_ref()], + &[b"governance", name.to_string().as_ref()], &crate::SPL_GOVERNANCE_ID, ) } diff --git a/e2e/governance/src/generated/accounts/required_signatory.rs b/e2e/governance/src/generated/accounts/required_signatory.rs index 223f6b6..449361b 100644 --- a/e2e/governance/src/generated/accounts/required_signatory.rs +++ b/e2e/governance/src/generated/accounts/required_signatory.rs @@ -26,7 +26,7 @@ impl RequiredSignatory { /// 0. `RequiredSignatory::PREFIX` /// 1. governance (`Address`) /// 2. signatory (`Address`) - pub const PREFIX: &'static [u8] = "required-signatory".as_bytes(); + pub const PREFIX: &'static [u8] = b"required-signatory"; pub fn create_pda( governance: Address, @@ -35,7 +35,7 @@ impl RequiredSignatory { ) -> Result { solana_address::Address::create_program_address( &[ - "required-signatory".as_bytes(), + b"required-signatory", governance.as_ref(), signatory.as_ref(), &[bump], @@ -47,7 +47,7 @@ impl RequiredSignatory { pub fn find_pda(governance: &Address, signatory: &Address) -> (solana_address::Address, u8) { solana_address::Address::find_program_address( &[ - "required-signatory".as_bytes(), + b"required-signatory", governance.as_ref(), signatory.as_ref(), ], diff --git a/e2e/governance/src/generated/accounts/signatory_record_v1.rs b/e2e/governance/src/generated/accounts/signatory_record_v1.rs index 285afc2..c31a660 100644 --- a/e2e/governance/src/generated/accounts/signatory_record_v1.rs +++ b/e2e/governance/src/generated/accounts/signatory_record_v1.rs @@ -26,7 +26,7 @@ impl SignatoryRecordV1 { /// 0. `SignatoryRecordV1::PREFIX` /// 1. proposal (`Address`) /// 2. signatory (`Address`) - pub const PREFIX: &'static [u8] = "governance".as_bytes(); + pub const PREFIX: &'static [u8] = b"governance"; pub fn create_pda( proposal: Address, @@ -35,7 +35,7 @@ impl SignatoryRecordV1 { ) -> Result { solana_address::Address::create_program_address( &[ - "governance".as_bytes(), + b"governance", proposal.as_ref(), signatory.as_ref(), &[bump], @@ -46,11 +46,7 @@ impl SignatoryRecordV1 { pub fn find_pda(proposal: &Address, signatory: &Address) -> (solana_address::Address, u8) { solana_address::Address::find_program_address( - &[ - "governance".as_bytes(), - proposal.as_ref(), - signatory.as_ref(), - ], + &[b"governance", proposal.as_ref(), signatory.as_ref()], &crate::SPL_GOVERNANCE_ID, ) } diff --git a/e2e/governance/src/generated/accounts/signatory_record_v2.rs b/e2e/governance/src/generated/accounts/signatory_record_v2.rs index e0fe51c..e931463 100644 --- a/e2e/governance/src/generated/accounts/signatory_record_v2.rs +++ b/e2e/governance/src/generated/accounts/signatory_record_v2.rs @@ -27,7 +27,7 @@ impl SignatoryRecordV2 { /// 0. `SignatoryRecordV2::PREFIX` /// 1. proposal (`Address`) /// 2. signatory (`Address`) - pub const PREFIX: &'static [u8] = "governance".as_bytes(); + pub const PREFIX: &'static [u8] = b"governance"; pub fn create_pda( proposal: Address, @@ -36,7 +36,7 @@ impl SignatoryRecordV2 { ) -> Result { solana_address::Address::create_program_address( &[ - "governance".as_bytes(), + b"governance", proposal.as_ref(), signatory.as_ref(), &[bump], @@ -47,11 +47,7 @@ impl SignatoryRecordV2 { pub fn find_pda(proposal: &Address, signatory: &Address) -> (solana_address::Address, u8) { solana_address::Address::find_program_address( - &[ - "governance".as_bytes(), - proposal.as_ref(), - signatory.as_ref(), - ], + &[b"governance", proposal.as_ref(), signatory.as_ref()], &crate::SPL_GOVERNANCE_ID, ) } diff --git a/e2e/governance/src/generated/accounts/token_owner_record_v1.rs b/e2e/governance/src/generated/accounts/token_owner_record_v1.rs index 17144f9..ee065c4 100644 --- a/e2e/governance/src/generated/accounts/token_owner_record_v1.rs +++ b/e2e/governance/src/generated/accounts/token_owner_record_v1.rs @@ -33,7 +33,7 @@ impl TokenOwnerRecordV1 { /// 1. realm (`Address`) /// 2. governing_token_mint (`Address`) /// 3. governing_token_owner (`Address`) - pub const PREFIX: &'static [u8] = "governance".as_bytes(); + pub const PREFIX: &'static [u8] = b"governance"; pub fn create_pda( realm: Address, @@ -43,7 +43,7 @@ impl TokenOwnerRecordV1 { ) -> Result { solana_address::Address::create_program_address( &[ - "governance".as_bytes(), + b"governance", realm.as_ref(), governing_token_mint.as_ref(), governing_token_owner.as_ref(), @@ -60,7 +60,7 @@ impl TokenOwnerRecordV1 { ) -> (solana_address::Address, u8) { solana_address::Address::find_program_address( &[ - "governance".as_bytes(), + b"governance", realm.as_ref(), governing_token_mint.as_ref(), governing_token_owner.as_ref(), diff --git a/e2e/governance/src/generated/accounts/token_owner_record_v2.rs b/e2e/governance/src/generated/accounts/token_owner_record_v2.rs index 7af6964..4dd9188 100644 --- a/e2e/governance/src/generated/accounts/token_owner_record_v2.rs +++ b/e2e/governance/src/generated/accounts/token_owner_record_v2.rs @@ -34,7 +34,7 @@ impl TokenOwnerRecordV2 { /// 1. realm (`Address`) /// 2. governing_token_mint (`Address`) /// 3. governing_token_owner (`Address`) - pub const PREFIX: &'static [u8] = "governance".as_bytes(); + pub const PREFIX: &'static [u8] = b"governance"; pub fn create_pda( realm: Address, @@ -44,7 +44,7 @@ impl TokenOwnerRecordV2 { ) -> Result { solana_address::Address::create_program_address( &[ - "governance".as_bytes(), + b"governance", realm.as_ref(), governing_token_mint.as_ref(), governing_token_owner.as_ref(), @@ -61,7 +61,7 @@ impl TokenOwnerRecordV2 { ) -> (solana_address::Address, u8) { solana_address::Address::find_program_address( &[ - "governance".as_bytes(), + b"governance", realm.as_ref(), governing_token_mint.as_ref(), governing_token_owner.as_ref(), diff --git a/e2e/governance/src/generated/accounts/vote_record_v1.rs b/e2e/governance/src/generated/accounts/vote_record_v1.rs index 58f796e..09cf1df 100644 --- a/e2e/governance/src/generated/accounts/vote_record_v1.rs +++ b/e2e/governance/src/generated/accounts/vote_record_v1.rs @@ -28,7 +28,7 @@ impl VoteRecordV1 { /// 0. `VoteRecordV1::PREFIX` /// 1. proposal (`Address`) /// 2. token_owner_record (`Address`) - pub const PREFIX: &'static [u8] = "governance".as_bytes(); + pub const PREFIX: &'static [u8] = b"governance"; pub fn create_pda( proposal: Address, @@ -37,7 +37,7 @@ impl VoteRecordV1 { ) -> Result { solana_address::Address::create_program_address( &[ - "governance".as_bytes(), + b"governance", proposal.as_ref(), token_owner_record.as_ref(), &[bump], @@ -52,7 +52,7 @@ impl VoteRecordV1 { ) -> (solana_address::Address, u8) { solana_address::Address::find_program_address( &[ - "governance".as_bytes(), + b"governance", proposal.as_ref(), token_owner_record.as_ref(), ], diff --git a/e2e/governance/src/generated/accounts/vote_record_v2.rs b/e2e/governance/src/generated/accounts/vote_record_v2.rs index 329a09d..ea096e0 100644 --- a/e2e/governance/src/generated/accounts/vote_record_v2.rs +++ b/e2e/governance/src/generated/accounts/vote_record_v2.rs @@ -30,7 +30,7 @@ impl VoteRecordV2 { /// 0. `VoteRecordV2::PREFIX` /// 1. proposal (`Address`) /// 2. token_owner_record (`Address`) - pub const PREFIX: &'static [u8] = "governance".as_bytes(); + pub const PREFIX: &'static [u8] = b"governance"; pub fn create_pda( proposal: Address, @@ -39,7 +39,7 @@ impl VoteRecordV2 { ) -> Result { solana_address::Address::create_program_address( &[ - "governance".as_bytes(), + b"governance", proposal.as_ref(), token_owner_record.as_ref(), &[bump], @@ -54,7 +54,7 @@ impl VoteRecordV2 { ) -> (solana_address::Address, u8) { solana_address::Address::find_program_address( &[ - "governance".as_bytes(), + b"governance", proposal.as_ref(), token_owner_record.as_ref(), ], diff --git a/e2e/governance/src/generated/instructions/create_token_owner_record.rs b/e2e/governance/src/generated/instructions/create_token_owner_record.rs index 441dc4d..92fb4b7 100644 --- a/e2e/governance/src/generated/instructions/create_token_owner_record.rs +++ b/e2e/governance/src/generated/instructions/create_token_owner_record.rs @@ -100,7 +100,7 @@ impl Default for CreateTokenOwnerRecordInstructionData { /// /// 0. `[]` realm_account /// 1. `[]` governing_token_owner_account -/// 2. `[writable]` token_owner_record +/// 2. `[writable, optional]` token_owner_record (default to PDA derived from 'tokenOwnerRecord') /// 3. `[]` governing_token_mint /// 4. `[signer]` payer /// 5. `[optional]` system_program (default to `11111111111111111111111111111111`) @@ -132,6 +132,7 @@ impl CreateTokenOwnerRecordBuilder { self.governing_token_owner_account = Some(governing_token_owner_account); self } + /// `[optional account, default to PDA derived from 'tokenOwnerRecord']` /// seeds=['governance', realm, governing_token_mint, governing_token_owner] #[inline(always)] pub fn token_owner_record(&mut self, token_owner_record: solana_address::Address) -> &mut Self { @@ -174,14 +175,26 @@ impl CreateTokenOwnerRecordBuilder { } #[allow(clippy::clone_on_copy)] pub fn instruction(&self) -> solana_instruction::Instruction { + let token_owner_record = self.token_owner_record.unwrap_or_else(|| { + crate::pdas::find_token_owner_record_pda( + &self + .realm_account + .expect("realm_account is needed for token_owner_record PDA"), + &self + .governing_token_mint + .expect("governing_token_mint is needed for token_owner_record PDA"), + &self + .governing_token_owner_account + .expect("governing_token_owner_account is needed for token_owner_record PDA"), + ) + .0 + }); let accounts = CreateTokenOwnerRecord { realm_account: self.realm_account.expect("realm_account is not set"), governing_token_owner_account: self .governing_token_owner_account .expect("governing_token_owner_account is not set"), - token_owner_record: self - .token_owner_record - .expect("token_owner_record is not set"), + token_owner_record, governing_token_mint: self .governing_token_mint .expect("governing_token_mint is not set"), diff --git a/e2e/governance/src/generated/pdas/mod.rs b/e2e/governance/src/generated/pdas/mod.rs index 2fb9d5c..b9faaa2 100644 --- a/e2e/governance/src/generated/pdas/mod.rs +++ b/e2e/governance/src/generated/pdas/mod.rs @@ -1,3 +1,10 @@ +//! This code was AUTOGENERATED using the codama library. +//! Please DO NOT EDIT THIS FILE, instead use visitors +//! to add features, then rerun codama to update it. +//! +//! +//! + pub mod community_token_holding; pub mod council_token_holding; pub mod governance; diff --git a/package.json b/package.json index 1fa2972..8cfa46f 100644 --- a/package.json +++ b/package.json @@ -46,6 +46,7 @@ "@codama/renderers-core": "^1.3.5", "@codama/visitors-core": "^1.5.0", "@iarna/toml": "^2.2.5", + "@noble/curves": "^2.0.1", "@solana/codecs-strings": "^6.0.0", "nunjucks": "^3.2.4", "semver": "^7.7.3" @@ -53,7 +54,7 @@ "devDependencies": { "@changesets/changelog-github": "^0.5.1", "@changesets/cli": "^2.29.7", - "@codama/nodes-from-anchor": "^1.3.6", + "@codama/nodes-from-anchor": "^1.4.0", "@solana/eslint-config-solana": "^5.0.0", "@solana/prettier-config-solana": "0.0.5", "@types/node": "^25", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 0146059..823f696 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -10,22 +10,25 @@ importers: dependencies: '@codama/errors': specifier: ^1.5.0 - version: 1.5.0 + version: 1.5.1 '@codama/nodes': specifier: ^1.5.0 - version: 1.5.0 + version: 1.5.1 '@codama/renderers-core': specifier: ^1.3.5 - version: 1.3.5 + version: 1.3.6 '@codama/visitors-core': specifier: ^1.5.0 - version: 1.5.0 + version: 1.5.1 '@iarna/toml': specifier: ^2.2.5 version: 2.2.5 + '@noble/curves': + specifier: ^2.0.1 + version: 2.0.1 '@solana/codecs-strings': specifier: ^6.0.0 - version: 6.0.1(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) + version: 6.5.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) nunjucks: specifier: ^3.2.4 version: 3.2.4 @@ -40,8 +43,8 @@ importers: specifier: ^2.29.7 version: 2.29.8(@types/node@25.2.3) '@codama/nodes-from-anchor': - specifier: ^1.3.6 - version: 1.3.6(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) + specifier: ^1.4.0 + version: 1.4.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) '@solana/eslint-config-solana': specifier: ^5.0.0 version: 5.0.0(@eslint/js@9.39.1)(@types/eslint__js@8.42.3)(eslint-plugin-jest@29.0.1(@typescript-eslint/eslint-plugin@8.43.0(@typescript-eslint/parser@8.43.0(eslint@9.39.1)(typescript@5.9.3))(eslint@9.39.1)(typescript@5.9.3))(eslint@9.39.1)(jest@30.1.3(@types/node@25.2.3))(typescript@5.9.3))(eslint-plugin-react-hooks@5.2.0(eslint@9.39.1))(eslint-plugin-simple-import-sort@12.1.1(eslint@9.39.1))(eslint-plugin-sort-keys-fix@1.1.2)(eslint-plugin-typescript-sort-keys@3.3.0(@typescript-eslint/parser@8.43.0(eslint@9.39.1)(typescript@5.9.3))(eslint@9.39.1)(typescript@5.9.3))(eslint@9.39.1)(globals@14.0.0)(jest@30.1.3(@types/node@25.2.3))(typescript-eslint@8.43.0(eslint@9.39.1)(typescript@5.9.3))(typescript@5.9.3) @@ -84,42 +87,42 @@ importers: packages: - '@babel/code-frame@7.27.1': - resolution: {integrity: sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==} + '@babel/code-frame@7.29.0': + resolution: {integrity: sha512-9NhCeYjq9+3uxgdtp20LSiJXJvN0FeCtNGpJxuMFZ1Kv3cWUNb6DOhJwUvcVCzKGR66cw4njwM6hrJLqgOwbcw==} engines: {node: '>=6.9.0'} - '@babel/compat-data@7.28.5': - resolution: {integrity: sha512-6uFXyCayocRbqhZOB+6XcuZbkMNimwfVGFji8CTZnCzOHVGvDqzvitu1re2AU5LROliz7eQPhB8CpAMvnx9EjA==} + '@babel/compat-data@7.29.0': + resolution: {integrity: sha512-T1NCJqT/j9+cn8fvkt7jtwbLBfLC/1y1c7NtCeXFRgzGTsafi68MRv8yzkYSapBnFA6L3U2VSc02ciDzoAJhJg==} engines: {node: '>=6.9.0'} - '@babel/core@7.28.5': - resolution: {integrity: sha512-e7jT4DxYvIDLk1ZHmU/m/mB19rex9sv0c2ftBtjSBv+kVM/902eh0fINUzD7UwLLNR+jU585GxUJ8/EBfAM5fw==} + '@babel/core@7.29.0': + resolution: {integrity: sha512-CGOfOJqWjg2qW/Mb6zNsDm+u5vFQ8DxXfbM09z69p5Z6+mE1ikP2jUXw+j42Pf1XTYED2Rni5f95npYeuwMDQA==} engines: {node: '>=6.9.0'} - '@babel/generator@7.28.5': - resolution: {integrity: sha512-3EwLFhZ38J4VyIP6WNtt2kUdW9dokXA9Cr4IVIFHuCpZ3H8/YFOl5JjZHisrn1fATPBmKKqXzDFvh9fUwHz6CQ==} + '@babel/generator@7.29.1': + resolution: {integrity: sha512-qsaF+9Qcm2Qv8SRIMMscAvG4O3lJ0F1GuMo5HR/Bp02LopNgnZBC/EkbevHFeGs4ls/oPz9v+Bsmzbkbe+0dUw==} engines: {node: '>=6.9.0'} - '@babel/helper-compilation-targets@7.27.2': - resolution: {integrity: sha512-2+1thGUUWWjLTYTHZWK1n8Yga0ijBz1XAhUXcKy81rd5g6yh7hGqMp45v7cadSbEHc9G3OTv45SyneRN3ps4DQ==} + '@babel/helper-compilation-targets@7.28.6': + resolution: {integrity: sha512-JYtls3hqi15fcx5GaSNL7SCTJ2MNmjrkHXg4FSpOA/grxK8KwyZ5bubHsCq8FXCkua6xhuaaBit+3b7+VZRfcA==} engines: {node: '>=6.9.0'} '@babel/helper-globals@7.28.0': resolution: {integrity: sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==} engines: {node: '>=6.9.0'} - '@babel/helper-module-imports@7.27.1': - resolution: {integrity: sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w==} + '@babel/helper-module-imports@7.28.6': + resolution: {integrity: sha512-l5XkZK7r7wa9LucGw9LwZyyCUscb4x37JWTPz7swwFE/0FMQAGpiWUZn8u9DzkSBWEcK25jmvubfpw2dnAMdbw==} engines: {node: '>=6.9.0'} - '@babel/helper-module-transforms@7.28.3': - resolution: {integrity: sha512-gytXUbs8k2sXS9PnQptz5o0QnpLL51SwASIORY6XaBKF88nsOT0Zw9szLqlSGQDP/4TljBAD5y98p2U1fqkdsw==} + '@babel/helper-module-transforms@7.28.6': + resolution: {integrity: sha512-67oXFAYr2cDLDVGLXTEABjdBJZ6drElUSI7WKp70NrpyISso3plG9SAGEF6y7zbha/wOzUByWWTJvEDVNIUGcA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0 - '@babel/helper-plugin-utils@7.27.1': - resolution: {integrity: sha512-1gn1Up5YXka3YYAHGKpbideQ5Yjf1tDa9qYcgysz+cNCXukyLl6DjPXhD3VRwSb8c0J9tA4b2+rHEZtc6R0tlw==} + '@babel/helper-plugin-utils@7.28.6': + resolution: {integrity: sha512-S9gzZ/bz83GRysI7gAD4wPT/AI3uCnY+9xn+Mx/KPs2JwHJIz1W8PZkg2cqyt3RNOBM8ejcXhV6y8Og7ly/Dug==} engines: {node: '>=6.9.0'} '@babel/helper-string-parser@7.27.1': @@ -134,12 +137,12 @@ packages: resolution: {integrity: sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==} engines: {node: '>=6.9.0'} - '@babel/helpers@7.28.4': - resolution: {integrity: sha512-HFN59MmQXGHVyYadKLVumYsA9dBFun/ldYxipEjzA4196jpLZd8UjEEBLkbEkvfYreDqJhZxYAWFPtrfhNpj4w==} + '@babel/helpers@7.29.2': + resolution: {integrity: sha512-HoGuUs4sCZNezVEKdVcwqmZN8GoHirLUcLaYVNBK2J0DadGtdcqgr3BCbvH8+XUo4NGjNl3VOtSjEKNzqfFgKw==} engines: {node: '>=6.9.0'} - '@babel/parser@7.28.5': - resolution: {integrity: sha512-KKBU1VGYR7ORr3At5HAtUQ+TV3SzRCXmA/8OdDZiLDBIZxVyzXuztPjfLd3BV1PRAQGCMWWSHYhL0F8d5uHBDQ==} + '@babel/parser@7.29.2': + resolution: {integrity: sha512-4GgRzy/+fsBa72/RZVJmGKPmZu9Byn8o4MoLpmNe1m8ZfYnz5emHLQz3U4gLud6Zwl0RZIcgiLD7Uq7ySFuDLA==} engines: {node: '>=6.0.0'} hasBin: true @@ -164,8 +167,8 @@ packages: peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-syntax-import-attributes@7.27.1': - resolution: {integrity: sha512-oFT0FrKHgF53f4vOsZGi2Hh3I35PfSmVs4IBFLFj4dnafP+hIWDLg3VyKmUHfLoLHlyxY4C7DGtmHuJgn+IGww==} + '@babel/plugin-syntax-import-attributes@7.28.6': + resolution: {integrity: sha512-jiLC0ma9XkQT3TKJ9uYvlakm66Pamywo+qwL+oL8HJOvc6TWdZXVfhqJr8CCzbSGUAbDOzlGHJC1U+vRfLQDvw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 @@ -180,8 +183,8 @@ packages: peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-syntax-jsx@7.27.1': - resolution: {integrity: sha512-y8YTNIeKoyhGd9O0Jiyzyyqk8gdjnumGTQPsz0xOZOQ2RmkVJeZ1vmmfIvFEKqucBG6axJGBZDE/7iI5suUI/w==} + '@babel/plugin-syntax-jsx@7.28.6': + resolution: {integrity: sha512-wgEmr06G6sIpqr8YDwA2dSRTE3bJ+V0IfpzfSY3Lfgd7YWOaAdlykvJi13ZKBt8cZHfgH1IXN+CL656W3uUa4w==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 @@ -228,8 +231,8 @@ packages: peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-syntax-typescript@7.27.1': - resolution: {integrity: sha512-xfYCBMxveHrRMnAWl1ZlPXOZjzkN82THFvLhQhFXFt81Z5HnN+EtUkZhv/zcKpmT3fzmWZB0ywiBrbC3vogbwQ==} + '@babel/plugin-syntax-typescript@7.28.6': + resolution: {integrity: sha512-+nDNmQye7nlnuuHDboPbGm00Vqg3oO8niRRL27/4LYHUsHYh0zJ1xWOz0uRwNFmM1Avzk8wZbc6rdiYhomzv/A==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 @@ -238,16 +241,16 @@ packages: resolution: {integrity: sha512-Q/N6JNWvIvPnLDvjlE1OUBLPQHH6l3CltCEsHIujp45zQUSSh8K+gHnaEX45yAT1nyngnINhvWtzN+Nb9D8RAQ==} engines: {node: '>=6.9.0'} - '@babel/template@7.27.2': - resolution: {integrity: sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==} + '@babel/template@7.28.6': + resolution: {integrity: sha512-YA6Ma2KsCdGb+WC6UpBVFJGXL58MDA6oyONbjyF/+5sBgxY/dwkhLogbMT2GXXyU84/IhRw/2D1Os1B/giz+BQ==} engines: {node: '>=6.9.0'} - '@babel/traverse@7.28.5': - resolution: {integrity: sha512-TCCj4t55U90khlYkVV/0TfkJkAkUg3jZFA3Neb7unZT8CPok7iiRfaX0F+WnqWqt7OxhOn0uBKXCw4lbL8W0aQ==} + '@babel/traverse@7.29.0': + resolution: {integrity: sha512-4HPiQr0X7+waHfyXPZpWPfWL/J7dcN1mx9gL6WdQVMbPnF3+ZhSMs8tCxN7oHddJE9fhNE7+lxdnlyemKfJRuA==} engines: {node: '>=6.9.0'} - '@babel/types@7.28.5': - resolution: {integrity: sha512-qQ5m48eI/MFLQ5PxQj4PFaprjyCTLI37ElWMmNs0K8Lk3dVeOdNpB3ks8jc7yM5CDmVC73eMVk/trk3fgmrUpA==} + '@babel/types@7.29.0': + resolution: {integrity: sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==} engines: {node: '>=6.9.0'} '@bcoe/v8-coverage@0.2.3': @@ -314,49 +317,36 @@ packages: '@changesets/write@0.4.0': resolution: {integrity: sha512-CdTLvIOPiCNuH71pyDu3rA+Q0n65cmAbXnwWH84rKGiFumFzkmHNT8KHTMEchcxN+Kl8I54xGUhJ7l3E7X396Q==} - '@codama/errors@1.4.4': - resolution: {integrity: sha512-XC86H5X+zGTi0cSRKLc+wFkeXNsvnh+ttOgVnVHIljmXOJWbUt9wXhKding3UftipLWwlHPuoswERJ0vS0mO2A==} + '@codama/errors@1.5.1': + resolution: {integrity: sha512-kdLk/OSLBt03DoViRU1Xr0M7NZ7J/CSqaXV8fooF9qMRGPRJdgUeW2VkCGlLXDQSaIALrls3HkHmKRKbqqjSOA==} hasBin: true - '@codama/errors@1.5.0': - resolution: {integrity: sha512-i4cS+S7JaZXhofQHFY3cwzt8rqxUVPNaeJND5VOyKUbtcOi933YXJXk52gDG4mc+CpGqHJijsJjfSpr1lJGxzg==} - hasBin: true - - '@codama/node-types@1.4.4': - resolution: {integrity: sha512-uUeIz34Id/TTAMi4k5OVl9FByM/PawnlNIIVqgpooH9AS0UlniICZ+KJ/mdHZidJs/AGo6bSRoOPS1BLtMajyw==} - - '@codama/node-types@1.5.0': - resolution: {integrity: sha512-Ebz2vOUukmNaFXWdkni1ZihXkAIUnPYtqIMXYxKXOxjMP+TGz2q0lGtRo7sqw1pc2ksFBIkfBp5pZsl5p6gwXA==} + '@codama/node-types@1.5.1': + resolution: {integrity: sha512-jMGz93MSszb1iXAAyWWa0i7RQbLxGihLKRZ+zr9aBsjaFFmhXhONfTFeSXzbEfc05cajpd/gW2QI7xmQHlUDKQ==} - '@codama/nodes-from-anchor@1.3.6': - resolution: {integrity: sha512-614DZS9H5gW16Rkeu0ES8BHnDvbd8M9FLqPWnp9QUE0b+wCvWB36yZiRylJ4fw8gRDSc+FR7C2i3NXKycpvBEg==} + '@codama/nodes-from-anchor@1.4.0': + resolution: {integrity: sha512-RAn2I1SI8LPvFOFFOeG5AK4wtXc/olcGa7tebHH30zeY3t0cYbi2Y86hDck4pFC57KQWmKQFAOwvdCj5zAVaEA==} - '@codama/nodes@1.4.4': - resolution: {integrity: sha512-JzlY5qLk3rhsnu0nerC/Vkc9/2HjdsLtEpBtST0dxC1j9kpfHvIc2uyIj+5hlB1YIBRJIDNo+UOHGla8hidkaA==} + '@codama/nodes@1.5.1': + resolution: {integrity: sha512-6fIoH5Cfa5dFUE1fRxymZloeNg02klOT4fHsWwQavkkRWkoySgiti//w0j1itiZj6j5O+usujrwsZUJqSFjnhQ==} - '@codama/nodes@1.5.0': - resolution: {integrity: sha512-yg+xmorWiMNjS3n19CGIt/FZ/ZCuDIu+HEY45bq6gHu1MN3RtJZY+Q3v0ErnBPA60D8mNWkvkKoeSZXfzcAvfw==} + '@codama/renderers-core@1.3.6': + resolution: {integrity: sha512-m3yAmhrObnagyC7d8g9bZxyLC5YMpttLagRE0aAKD4zlDDh23o3zV7TxSYCh2nRCg5ObceflgvXdauIHUm/6Xg==} - '@codama/renderers-core@1.3.5': - resolution: {integrity: sha512-MuZLU+3LZPQb1HuZffwZl+v5JHQDe5LYHGhA1wTMNlwRedYIysSxBjogHNciNIHsKP3JjmqyYmLO5LCEp3hjaQ==} + '@codama/visitors-core@1.5.1': + resolution: {integrity: sha512-JotrDJLI7OfPNHulu4KtPfUDF/FYMC3RgEnv9lu47Fiiy0upbGAw1NorgBuoreyJ9Uj0GZyHt7Q5rjrCoa1U0g==} - '@codama/visitors-core@1.4.4': - resolution: {integrity: sha512-vk/4tczViAUHa7c8PF7FxN+JWbuTcDB0pIdrDbbO6eBPKDPQGZCUCEp6rXIYBVxfO129jWrNf2+CuyYre/c/vA==} + '@codama/visitors@1.5.1': + resolution: {integrity: sha512-8WcGP1tJKtqBfZ4mJsBRPjZ/H6+SPLWmiUoDTXRrVePQE4X4Yb04o6BoX2Uc3heZbfEc0rXdM1w8HTFvXBX4/A==} - '@codama/visitors-core@1.5.0': - resolution: {integrity: sha512-3PIAlBX0a06hIxzyPtQMfQcqWGFBgfbwysSwcXBbvHUYbemwhD6xwlBKJuqTwm9DyFj3faStp5fpvcp03Rjxtw==} + '@emnapi/core@1.9.1': + resolution: {integrity: sha512-mukuNALVsoix/w1BJwFzwXBN/dHeejQtuVzcDsfOEsdpCumXb/E9j8w11h5S54tT1xhifGfbbSm/ICrObRb3KA==} - '@codama/visitors@1.4.4': - resolution: {integrity: sha512-3w2aRNvGV6/rXTfRDynXR82zoAqX0P4tlfQ/zT4I4Bby4xTobKgDZLyAstodmA0D878eKW7sMg4Gb1m1R5dOig==} + '@emnapi/runtime@1.9.1': + resolution: {integrity: sha512-VYi5+ZVLhpgK4hQ0TAjiQiZ6ol0oe4mBx7mVv7IflsiEp0OWoVsp/+f9Vc1hOhE0TtkORVrI1GvzyreqpgWtkA==} - '@emnapi/core@1.7.1': - resolution: {integrity: sha512-o1uhUASyo921r2XtHYOHy7gdkGLge8ghBEQHMWmyJFoXlpU58kIrhhN3w26lpQb6dspetweapMn2CSNwQ8I4wg==} - - '@emnapi/runtime@1.7.1': - resolution: {integrity: sha512-PVtJr5CmLwYAU9PZDMITZoR5iAOShYREoR45EyyLrbntV50mdePTgUn4AmOw90Ifcj+x2kRjdzr1HP3RrNiHGA==} - - '@emnapi/wasi-threads@1.1.0': - resolution: {integrity: sha512-WI0DdZ8xFSbgMjR1sFsKABJ/C5OnRrjT06JXbZKexJGrDuPTzZdDYfFlsgcCXCyf+suG5QU2e/y1Wo2V/OapLQ==} + '@emnapi/wasi-threads@1.2.0': + resolution: {integrity: sha512-N10dEJNSsUx41Z6pZsXU8FjPjpBEplgH24sfkmITrBED1/U2Esum9F3lfLrMjKHHjmi557zQn7kR9R+XWXu5Rg==} '@esbuild/aix-ppc64@0.25.12': resolution: {integrity: sha512-Hhmwd6CInZ3dwpuGTF8fJG6yoWmsToE+vYgD4nytZVxcu1ulHpUQRAB1UJ8+N1Am3Mz4+xOByoQoSZf4D+CpkA==} @@ -676,6 +666,12 @@ packages: peerDependencies: eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 + '@eslint-community/eslint-utils@4.9.1': + resolution: {integrity: sha512-phrYmNiYppR7znFEdqgfWHXR6NCkZEK7hwWDHZUjit/2/U0r6XvkDl0SYnoM51Hq7FhCGdLDT6zxCCOY1hexsQ==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 + '@eslint-community/regexpp@4.12.2': resolution: {integrity: sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==} engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} @@ -863,6 +859,10 @@ packages: '@napi-rs/wasm-runtime@0.2.12': resolution: {integrity: sha512-ZVWUcfwY4E/yPitQJl481FjFo3K22D6qF0DuFH6Y/nbnE11GY5uguDxZMGXPQ8WQ0128MXQD7TnfHyK4oWoIJQ==} + '@noble/curves@2.0.1': + resolution: {integrity: sha512-vs1Az2OOTBiP4q0pwjW5aF0xp9n4MxVrmkFBxc6EKZc6ddYx5gaZiAsZoq0uRRXWbi3AT/sBqn05eRPtn1JCPw==} + engines: {node: '>= 20.19.0'} + '@noble/hashes@2.0.1': resolution: {integrity: sha512-XlOlEbQcE9fmuXxrVTXCTlG2nlRXa9Rj3rr5Ue/+tX+nmkgbX720YHh0VR3hBF9xDvwnb8D2shVGOwNx+ulArw==} engines: {node: '>= 20.19.0'} @@ -1116,8 +1116,8 @@ packages: cpu: [x64] os: [win32] - '@sinclair/typebox@0.34.41': - resolution: {integrity: sha512-6gS8pZzSXdyRHTIqoqSVknxolr1kzfy4/CeDnrzsVz8TTIWUbOBr6gnzOmTYJ3eXQNh4IYHIGi5aIL7sOZ2G/g==} + '@sinclair/typebox@0.34.48': + resolution: {integrity: sha512-kKJTNuK3AQOrgjjotVxMrCn1sUJwM76wMszfq1kdU4uYVJjvEWuFQ6HgvLt4Xz3fSmZlTOxJ/Ie13KnIcWQXFA==} '@sinonjs/commons@3.0.1': resolution: {integrity: sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==} @@ -1125,14 +1125,17 @@ packages: '@sinonjs/fake-timers@13.0.5': resolution: {integrity: sha512-36/hTbH2uaWuGVERyC6da9YwGWnzUZXuPro/F2LfsdOsLnCojz/iSH8MxUt/FD2S5XBSVPhmArFUXcpCQ2Hkiw==} - '@solana/codecs-core@5.0.0': - resolution: {integrity: sha512-rCG2d8OaamVF2/J//YyCgDqNJpUytVVltw9C8mJtEz5c6Se/LR6BFuG8g4xeJswq/ab4RFk5/HFdgbvNjKgQjA==} + '@solana/codecs-core@5.5.1': + resolution: {integrity: sha512-TgBt//bbKBct0t6/MpA8ElaOA3sa8eYVvR7LGslCZ84WiAwwjCY0lW/lOYsFHJQzwREMdUyuEyy5YWBKtdh8Rw==} engines: {node: '>=20.18.0'} peerDependencies: - typescript: '>=5.3.3' + typescript: ^5.0.0 + peerDependenciesMeta: + typescript: + optional: true - '@solana/codecs-core@6.0.1': - resolution: {integrity: sha512-OnUQk94qfvfE0nVveZ638aNUL3tyRJoorUFiAG0ICTGUo3c6fkYb8vH23o/5O2qmuSmYND1sn+UCaldNMVkFpg==} + '@solana/codecs-core@6.5.0': + resolution: {integrity: sha512-Wb+YUj7vUKz5CxqZkrkugtQjxOP2fkMKnffySRlAmVAkpRnQvBY/2eP3VJAKTgDD4ru9xHSIQSpDu09hC/cQZg==} engines: {node: '>=20.18.0'} peerDependencies: typescript: ^5.0.0 @@ -1140,20 +1143,26 @@ packages: typescript: optional: true - '@solana/codecs-data-structures@5.0.0': - resolution: {integrity: sha512-y503Pqmv0LHcfcf0vQJGaxDvydQJbyCo8nK3nxn56EhFj5lBQ1NWb3WvTd83epigwuZurW2MhJARrpikfhQglQ==} + '@solana/codecs-data-structures@5.5.1': + resolution: {integrity: sha512-97bJWGyUY9WvBz3mX1UV3YPWGDTez6btCfD0ip3UVEXJbItVuUiOkzcO5iFDUtQT5riKT6xC+Mzl+0nO76gd0w==} engines: {node: '>=20.18.0'} peerDependencies: - typescript: '>=5.3.3' + typescript: ^5.0.0 + peerDependenciesMeta: + typescript: + optional: true - '@solana/codecs-numbers@5.0.0': - resolution: {integrity: sha512-a2+skRLuUK02f/XFe4L0e1+wHCyfK25PkyseFps1v1l4pvevukFwth/EhSyrs6w5CsTJRVoR7MuE3E00PM4egw==} + '@solana/codecs-numbers@5.5.1': + resolution: {integrity: sha512-rllMIZAHqmtvC0HO/dc/21wDuWaD0B8Ryv8o+YtsICQBuiL/0U4AGwH7Pi5GNFySYk0/crSuwfIqQFtmxNSPFw==} engines: {node: '>=20.18.0'} peerDependencies: - typescript: '>=5.3.3' + typescript: ^5.0.0 + peerDependenciesMeta: + typescript: + optional: true - '@solana/codecs-numbers@6.0.1': - resolution: {integrity: sha512-ZrI1NjUsf4I+Klue/2rlQbZLcGRom/G2E4VB/8x4IEHGOeFLQhXcxmnib8kdgomQRYOzF1BjVDmCYxvZr+6AWA==} + '@solana/codecs-numbers@6.5.0': + resolution: {integrity: sha512-gU/7eYqD+zl2Kwzo7ctt7YHaxF+c3RX164F+iU4X02dwq8DGVcypp+kmEF1QaO6OiShtdryTxhL+JJmEBjhdfA==} engines: {node: '>=20.18.0'} peerDependencies: typescript: ^5.0.0 @@ -1161,15 +1170,20 @@ packages: typescript: optional: true - '@solana/codecs-strings@5.0.0': - resolution: {integrity: sha512-ALkRwpV8bGR6qjAYw0YXZwp2YI4wzvKOJGmx04Ut8gMdbaUx7qOcJkhEQKI6ZVC3lAWSIS1N1wGccUZDwvfKxw==} + '@solana/codecs-strings@5.5.1': + resolution: {integrity: sha512-7klX4AhfHYA+uKKC/nxRGP2MntbYQCR3N6+v7bk1W/rSxYuhNmt+FN8aoThSZtWIKwN6BEyR1167ka8Co1+E7A==} engines: {node: '>=20.18.0'} peerDependencies: fastestsmallesttextencoderdecoder: ^1.0.22 - typescript: '>=5.3.3' + typescript: ^5.0.0 + peerDependenciesMeta: + fastestsmallesttextencoderdecoder: + optional: true + typescript: + optional: true - '@solana/codecs-strings@6.0.1': - resolution: {integrity: sha512-OmMIfMFbbJVIxveBeATKCj9DsmZ8l4vJPnOLHUop0hLWRiYHTQ1qokMqfk/X8PCmUjXmbXnlp63BikGtdKN3/g==} + '@solana/codecs-strings@6.5.0': + resolution: {integrity: sha512-9TuQQxumA9gWJeJzbv1GUg0+o0nZp204EijX3efR+lgBOKbkU7W0UWp33ygAZ+RvWE+kTs48ePoYoJ7UHpyxkQ==} engines: {node: '>=20.18.0'} peerDependencies: fastestsmallesttextencoderdecoder: ^1.0.22 @@ -1180,21 +1194,27 @@ packages: typescript: optional: true - '@solana/codecs@5.0.0': - resolution: {integrity: sha512-KOw0gFUSBxIMDWLJ3AkVFkEci91dw0Rpx3C6y83Our7fSW+SEP8vRZklCElieYR85LHVB1QIEhoeHR7rc+Ifkw==} + '@solana/codecs@5.5.1': + resolution: {integrity: sha512-Vea29nJub/bXjfzEV7ZZQ/PWr1pYLZo3z0qW0LQL37uKKVzVFRQlwetd7INk3YtTD3xm9WUYr7bCvYUk3uKy2g==} engines: {node: '>=20.18.0'} peerDependencies: - typescript: '>=5.3.3' + typescript: ^5.0.0 + peerDependenciesMeta: + typescript: + optional: true - '@solana/errors@5.0.0': - resolution: {integrity: sha512-gTuhzO6E+ydfAAzqmqdPcvFyJwAzFKKIrqtnZPpgAuomcPYu+HSo0tuwSM/cTX0djmHt+GoOsf/julph+nvs2w==} + '@solana/errors@5.5.1': + resolution: {integrity: sha512-vFO3p+S7HoyyrcAectnXbdsMfwUzY2zYFUc2DEe5BwpiE9J1IAxPBGjOWO6hL1bbYdBrlmjNx8DXCslqS+Kcmg==} engines: {node: '>=20.18.0'} hasBin: true peerDependencies: - typescript: '>=5.3.3' + typescript: ^5.0.0 + peerDependenciesMeta: + typescript: + optional: true - '@solana/errors@6.0.1': - resolution: {integrity: sha512-sMe5GCsXto8F1KDeq9GbZR0+m841SqEYep3NAcYlC0lqF2RG4giaaPQHgrWI5DJR/L7yc8FzUIQfTxnaN7bwOQ==} + '@solana/errors@6.5.0': + resolution: {integrity: sha512-XPc0I8Ck6vgx8Uu+LVLewx/1RWDkXkY3lU+1aN1kmbrPAQWbX4Txk7GPmuIIFpyys8o5aKocYfNxJOPKvfaQhg==} engines: {node: '>=20.18.0'} hasBin: true peerDependencies: @@ -1219,11 +1239,14 @@ packages: typescript: ^5.6 typescript-eslint: ^8.11.0 - '@solana/options@5.0.0': - resolution: {integrity: sha512-ezHVBFb9FXVSn8LUVRD2tLb6fejU0x8KtGEYyCYh0J0pQuXSITV0IQCjcEopvu/ZxWdXOJyzjvmymnhz90on5A==} + '@solana/options@5.5.1': + resolution: {integrity: sha512-eo971c9iLNLmk+yOFyo7yKIJzJ/zou6uKpy6mBuyb/thKtS/haiKIc3VLhyTXty3OH2PW8yOlORJnv4DexJB8A==} engines: {node: '>=20.18.0'} peerDependencies: - typescript: '>=5.3.3' + typescript: ^5.0.0 + peerDependenciesMeta: + typescript: + optional: true '@solana/prettier-config-solana@0.0.5': resolution: {integrity: sha512-igtLH1QaX5xzSLlqteexRIg9X1QKA03xKYQc2qY1TrMDDhxKXoRZOStQPWdita2FVJzxTGz/tdMGC1vS0biRcg==} @@ -1284,6 +1307,9 @@ packages: '@types/node@25.2.3': resolution: {integrity: sha512-m0jEgYlYz+mDJZ2+F4v8D1AyQb+QzsNqRuI7xg1VQX/KlKS0qT9r1Mo16yo5F/MtifXFgaofIFsdFMox2SxIbQ==} + '@types/node@25.5.0': + resolution: {integrity: sha512-jp2P3tQMSxWugkCUKLRPVUpGaL5MVFwF8RDuSRztfwgN1wmqJeMSbKlnEtQqU8UrhTmzEmZdu2I6v2dpp7XIxw==} + '@types/nunjucks@3.2.6': resolution: {integrity: sha512-pHiGtf83na1nCzliuAdq8GowYiXvH5l931xZ0YEHaLMNFgynpEqx+IPStlu7UaDkehfvl01e4x/9Tpwhy7Ue3w==} @@ -1329,8 +1355,8 @@ packages: peerDependencies: typescript: '>=4.8.4 <6.0.0' - '@typescript-eslint/project-service@8.48.1': - resolution: {integrity: sha512-HQWSicah4s9z2/HifRPQ6b6R7G+SBx64JlFQpgSSHWPKdvCZX57XCbszg/bapbRsOEv42q5tayTYcEFpACcX1w==} + '@typescript-eslint/project-service@8.57.2': + resolution: {integrity: sha512-FuH0wipFywXRTHf+bTTjNyuNQQsQC3qh/dYzaM4I4W0jrCqjCVuUh99+xd9KamUfmCGPvbO8NDngo/vsnNVqgw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: typescript: '>=4.8.4 <6.0.0' @@ -1343,8 +1369,8 @@ packages: resolution: {integrity: sha512-daSWlQ87ZhsjrbMLvpuuMAt3y4ba57AuvadcR7f3nl8eS3BjRc8L9VLxFLk92RL5xdXOg6IQ+qKjjqNEimGuAg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@typescript-eslint/scope-manager@8.48.1': - resolution: {integrity: sha512-rj4vWQsytQbLxC5Bf4XwZ0/CKd362DkWMUkviT7DCS057SK64D5lH74sSGzhI6PDD2HCEq02xAP9cX68dYyg1w==} + '@typescript-eslint/scope-manager@8.57.2': + resolution: {integrity: sha512-snZKH+W4WbWkrBqj4gUNRIGb/jipDW3qMqVJ4C9rzdFc+wLwruxk+2a5D+uoFcKPAqyqEnSb4l2ULuZf95eSkw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} '@typescript-eslint/tsconfig-utils@8.43.0': @@ -1353,8 +1379,8 @@ packages: peerDependencies: typescript: '>=4.8.4 <6.0.0' - '@typescript-eslint/tsconfig-utils@8.48.1': - resolution: {integrity: sha512-k0Jhs4CpEffIBm6wPaCXBAD7jxBtrHjrSgtfCjUvPp9AZ78lXKdTR8fxyZO5y4vWNlOvYXRtngSZNSn+H53Jkw==} + '@typescript-eslint/tsconfig-utils@8.57.2': + resolution: {integrity: sha512-3Lm5DSM+DCowsUOJC+YqHHnKEfFh5CoGkj5Z31NQSNF4l5wdOwqGn99wmwN/LImhfY3KJnmordBq/4+VDe2eKw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: typescript: '>=4.8.4 <6.0.0' @@ -1374,8 +1400,8 @@ packages: resolution: {integrity: sha512-vQ2FZaxJpydjSZJKiSW/LJsabFFvV7KgLC5DiLhkBcykhQj8iK9BOaDmQt74nnKdLvceM5xmhaTF+pLekrxEkw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@typescript-eslint/types@8.48.1': - resolution: {integrity: sha512-+fZ3LZNeiELGmimrujsDCT4CRIbq5oXdHe7chLiW8qzqyPMnn1puNstCrMNVAqwcl2FdIxkuJ4tOs/RFDBVc/Q==} + '@typescript-eslint/types@8.57.2': + resolution: {integrity: sha512-/iZM6FnM4tnx9csuTxspMW4BOSegshwX5oBDznJ7S4WggL7Vczz5d2W11ecc4vRrQMQHXRSxzrCsyG5EsPPTbA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} '@typescript-eslint/typescript-estree@5.62.0': @@ -1393,8 +1419,8 @@ packages: peerDependencies: typescript: '>=4.8.4 <6.0.0' - '@typescript-eslint/typescript-estree@8.48.1': - resolution: {integrity: sha512-/9wQ4PqaefTK6POVTjJaYS0bynCgzh6ClJHGSBj06XEHjkfylzB+A3qvyaXnErEZSaxhIo4YdyBgq6j4RysxDg==} + '@typescript-eslint/typescript-estree@8.57.2': + resolution: {integrity: sha512-2MKM+I6g8tJxfSmFKOnHv2t8Sk3T6rF20A1Puk0svLK+uVapDZB/4pfAeB7nE83uAZrU6OxW+HmOd5wHVdXwXA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: typescript: '>=4.8.4 <6.0.0' @@ -1412,11 +1438,11 @@ packages: eslint: ^8.57.0 || ^9.0.0 typescript: '>=4.8.4 <6.0.0' - '@typescript-eslint/utils@8.48.1': - resolution: {integrity: sha512-fAnhLrDjiVfey5wwFRwrweyRlCmdz5ZxXz2G/4cLn0YDLjTapmN4gcCsTBR1N2rWnZSDeWpYtgLDsJt+FpmcwA==} + '@typescript-eslint/utils@8.57.2': + resolution: {integrity: sha512-krRIbvPK1ju1WBKIefiX+bngPs+odIQUtR7kymzPfo1POVw3jlF+nLkmexdSSd4UCbDcQn+wMBATOOmpBbqgKg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: - eslint: ^8.57.0 || ^9.0.0 + eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 typescript: '>=4.8.4 <6.0.0' '@typescript-eslint/visitor-keys@5.62.0': @@ -1427,8 +1453,8 @@ packages: resolution: {integrity: sha512-T+S1KqRD4sg/bHfLwrpF/K3gQLBM1n7Rp7OjjikjTEssI2YJzQpi5WXoynOaQ93ERIuq3O8RBTOUYDKszUCEHw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@typescript-eslint/visitor-keys@8.48.1': - resolution: {integrity: sha512-BmxxndzEWhE4TIEEMBs8lP3MBWN3jFPs/p6gPm/wkv02o41hI6cq9AuSmGAaTTHPtA1FTi2jBre4A9rm5ZmX+Q==} + '@typescript-eslint/visitor-keys@8.57.2': + resolution: {integrity: sha512-zhahknjobV2FiD6Ee9iLbS7OV9zi10rG26odsQdfBO/hjSzUQbkIYgda+iNKK1zNiW2ey+Lf8MU5btN17V3dUw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} '@ungap/structured-clone@1.3.0': @@ -1663,8 +1689,13 @@ packages: balanced-match@1.0.2: resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} - baseline-browser-mapping@2.8.32: - resolution: {integrity: sha512-OPz5aBThlyLFgxyhdwf/s2+8ab3OvT7AdTNvKHBwpXomIYeXqpUUuT8LrdtxZSsWJ4R4CU1un4XGh5Ez3nlTpw==} + balanced-match@4.0.4: + resolution: {integrity: sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==} + engines: {node: 18 || 20 || >=22} + + baseline-browser-mapping@2.10.10: + resolution: {integrity: sha512-sUoJ3IMxx4AyRqO4MLeHlnGDkyXRoUG0/AI9fjK+vS72ekpV0yWVY7O0BVjmBcRtkNcsAO2QDZ4tdKKGoI6YaQ==} + engines: {node: '>=6.0.0'} hasBin: true better-path-resolve@1.0.0: @@ -1677,12 +1708,16 @@ packages: brace-expansion@2.0.2: resolution: {integrity: sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==} + brace-expansion@5.0.4: + resolution: {integrity: sha512-h+DEnpVvxmfVefa4jFbCf5HdH5YMDXRsmKflpf1pILZWRFlTbJpxeU55nJl4Smt5HQaGzg1o6RHFPJaOqnmBDg==} + engines: {node: 18 || 20 || >=22} + braces@3.0.3: resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} engines: {node: '>=8'} - browserslist@4.28.0: - resolution: {integrity: sha512-tbydkR/CxfMwelN0vwdP/pLkDwyAASZ+VfWm4EOwlB6SWhx1sYnWLqo8N5j0rAzPfzfRaxt0mM/4wPU/Su84RQ==} + browserslist@4.28.1: + resolution: {integrity: sha512-ZC5Bd0LgJXgwGqUknZY/vkUQ04r8NXnJZ3yYi4vDmSiZmC/pdSN0NbNRPxZpbtO4uAfDUAFffO8IZoM3Gj8IkA==} engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} hasBin: true @@ -1726,8 +1761,8 @@ packages: resolution: {integrity: sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==} engines: {node: '>=10'} - caniuse-lite@1.0.30001757: - resolution: {integrity: sha512-r0nnL/I28Zi/yjk1el6ilj27tKcdjLsNqAOZr0yVjWPrSQyHgKI2INaEWw21bAQSv2LXRt1XuCS/GomNpWOxsQ==} + caniuse-lite@1.0.30001781: + resolution: {integrity: sha512-RdwNCyMsNBftLjW6w01z8bKEvT6e/5tpPVEgtn22TiLGlstHOVecsX2KHFkD5e/vRnIE4EGzpuIODb3mtswtkw==} chai@6.2.1: resolution: {integrity: sha512-p4Z49OGG5W/WBCPSS/dH3jQ73kD6tiMmUM+bckNK6Jr5JHMG3k9bg/BvKR8lKmtVBKmOiuVaV2ws8s9oSbwysg==} @@ -1756,12 +1791,12 @@ packages: resolution: {integrity: sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==} engines: {node: '>=8'} - ci-info@4.3.1: - resolution: {integrity: sha512-Wdy2Igu8OcBpI2pZePZ5oWjPC38tmDVx5WKUXKwlLYkA0ozo85sLsLvkBbBn/sZaSCMFOGZJ14fvW9t5/d7kdA==} + ci-info@4.4.0: + resolution: {integrity: sha512-77PSwercCZU2Fc4sX94eF8k8Pxte6JAwL4/ICZLFjJLqegs7kCuAsqqj/70NQF6TvDpgFjkubQB2FW2ZZddvQg==} engines: {node: '>=8'} - cjs-module-lexer@2.1.1: - resolution: {integrity: sha512-+CmxIZ/L2vNcEfvNtLdU0ZQ6mbq3FZnwAP2PPTiKP+1QOoKwlKlPgb8UKV0Dds7QVaMnHm+FwSft2VB0s/SLjQ==} + cjs-module-lexer@2.2.0: + resolution: {integrity: sha512-4bHTS2YuzUvtoLjdy+98ykbNB5jS0+07EvFNXerqZQJ89F7DI6ET7OQo/HJuW6K0aVsKA9hj9/RVb2kQVOrPDQ==} cliui@8.0.1: resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==} @@ -1781,10 +1816,6 @@ packages: color-name@1.1.4: resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} - commander@14.0.1: - resolution: {integrity: sha512-2JkV3gUZUVrbNA+1sjBOYLsMZ5cEEl8GTFP2a4AVz5hvasAMCQ1D2l2le/cX+pV4N6ZU17zjUahLpIXRrnWL8A==} - engines: {node: '>=20'} - commander@14.0.2: resolution: {integrity: sha512-TywoWNNRbhoD0BXs1P3ZEScW8W5iKrnbithIl0YH+uCmBd0QpPOA8yc82DS3BIE5Ma6FnBVUsJ7wVUDz4dvOWQ==} engines: {node: '>=20'} @@ -1830,8 +1861,8 @@ packages: supports-color: optional: true - dedent@1.7.0: - resolution: {integrity: sha512-HGFtf8yhuhGhqO07SV79tRp+br4MnbdjeVxotpn1QBl30pcLLCQjX5b2295ll0fv8RKDKsmWYrl05usHM9CewQ==} + dedent@1.7.2: + resolution: {integrity: sha512-WzMx3mW98SN+zn3hgemf4OzdmyNhhhKz5Ay0pUfQiMQ3e1g+xmTJWp/pKdwKVXhdSkAEGIIzqeuWrL3mV/AXbA==} peerDependencies: babel-plugin-macros: ^3.1.0 peerDependenciesMeta: @@ -1872,8 +1903,8 @@ packages: eastasianwidth@0.2.0: resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} - electron-to-chromium@1.5.263: - resolution: {integrity: sha512-DrqJ11Knd+lo+dv+lltvfMDLU27g14LMdH2b0O3Pio4uk0x+z7OR+JrmyacTPN2M8w3BrZ7/RTwG3R9B7irPlg==} + electron-to-chromium@1.5.322: + resolution: {integrity: sha512-vFU34OcrvMcH66T+dYC3G4nURmgfDVewMIu6Q2urXpumAPSMmzvcn04KVVV8Opikq8Vs5nUbO/8laNhNRqSzYw==} emittery@0.13.1: resolution: {integrity: sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==} @@ -1985,6 +2016,10 @@ packages: resolution: {integrity: sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + eslint-visitor-keys@5.0.1: + resolution: {integrity: sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA==} + engines: {node: ^20.19.0 || ^22.13.0 || >=24} + eslint@9.39.1: resolution: {integrity: sha512-BhHmn2yNOFA9H9JmmIVKJmd288g9hrVRDkdoIgRCRuSySRUHH7r/DI6aAXW9T1WwUuY3DFgrcaqB+deURBLR5g==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} @@ -2579,13 +2614,24 @@ packages: resolution: {integrity: sha512-enIvLvRAFZYXJzkCYG5RKmPfrFArdLv+R+lbQ53BmIMLIry74bjKzX6iHAm8WYamJkhSSEabrWN5D97XnKObjQ==} engines: {node: 20 || >=22} + minimatch@10.2.4: + resolution: {integrity: sha512-oRjTw/97aTBN0RHbYCdtF1MQfvusSIBQM0IZEgzl6426+8jSC0nF1a/GmnVLpfB9yyr6g6FTqWqiZVbxrtaCIg==} + engines: {node: 18 || 20 || >=22} + minimatch@3.1.2: resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} + minimatch@3.1.5: + resolution: {integrity: sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==} + minimatch@9.0.5: resolution: {integrity: sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==} engines: {node: '>=16 || 14 >=14.17'} + minimatch@9.0.9: + resolution: {integrity: sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg==} + engines: {node: '>=16 || 14 >=14.17'} + minipass@7.1.2: resolution: {integrity: sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==} engines: {node: '>=16 || 14 >=14.17'} @@ -2631,8 +2677,8 @@ packages: node-int64@0.4.0: resolution: {integrity: sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==} - node-releases@2.0.27: - resolution: {integrity: sha512-nmh3lCkYZ3grZvqcCH+fjmQ7X+H0OeZgP40OierEaAptX4XofMh5kwNbWh7lBduUzCcV/8kZ+NDLCwm2iorIlA==} + node-releases@2.0.36: + resolution: {integrity: sha512-TdC8FSgHz8Mwtw9g5L4gR/Sh9XhSP/0DEkQxfEFXOpiul5IiHgHan2VhYYb6agDSfp4KuvltmGApc8HMgUrIkA==} normalize-path@3.0.0: resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} @@ -2753,10 +2799,18 @@ packages: resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} engines: {node: '>=8.6'} + picomatch@2.3.2: + resolution: {integrity: sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==} + engines: {node: '>=8.6'} + picomatch@4.0.3: resolution: {integrity: sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==} engines: {node: '>=12'} + picomatch@4.0.4: + resolution: {integrity: sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==} + engines: {node: '>=12'} + pify@4.0.1: resolution: {integrity: sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==} engines: {node: '>=6'} @@ -2895,6 +2949,11 @@ packages: engines: {node: '>=10'} hasBin: true + semver@7.7.4: + resolution: {integrity: sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==} + engines: {node: '>=10'} + hasBin: true + set-function-length@1.2.2: resolution: {integrity: sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==} engines: {node: '>= 0.4'} @@ -3001,8 +3060,8 @@ packages: resolution: {integrity: sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==} engines: {node: '>=10'} - synckit@0.11.11: - resolution: {integrity: sha512-MeQTA1r0litLUf0Rp/iisCaL8761lKAZHaimlbGK4j0HysC4PLfqygQj9srcs0m2RdtDYnF8UuYyKpbjHYp7Jw==} + synckit@0.11.12: + resolution: {integrity: sha512-Bh7QjT8/SuKUIfObSXNHNSK6WHo6J1tHCqJsuaFDP7gP0fkzSfTxI8y85JrppZ0h8l0maIgc2tfuZQ6/t3GtnQ==} engines: {node: ^14.18.0 || >=16.0.0} term-size@2.2.1: @@ -3048,8 +3107,8 @@ packages: resolution: {integrity: sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==} hasBin: true - ts-api-utils@2.1.0: - resolution: {integrity: sha512-CUgTZL1irw8u29bzrOD/nH85jqyc74D6SshFgujOIA7osm2Rz7dYH77agkx7H4FBNxDq7Cjf+IjaX/8zwFW+ZQ==} + ts-api-utils@2.5.0: + resolution: {integrity: sha512-OJ/ibxhPlqrMM0UiNHJ/0CKQkoKF243/AEmplt3qpRgkW8VG7IfOS41h7V8TjITqdByHzrjcS/2si+y4lIh8NA==} engines: {node: '>=18.12'} peerDependencies: typescript: '>=4.8.4' @@ -3121,6 +3180,9 @@ packages: undici-types@7.16.0: resolution: {integrity: sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==} + undici-types@7.18.2: + resolution: {integrity: sha512-AsuCzffGHJybSaRrmr5eHr81mwJU3kjw6M+uprWvCXiNeN9SOGwQ3Jn8jb8m3Z6izVgknn1R0FTCEAP2QrLY/w==} + universalify@0.1.2: resolution: {integrity: sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==} engines: {node: '>= 4.0.0'} @@ -3128,8 +3190,8 @@ packages: unrs-resolver@1.11.1: resolution: {integrity: sha512-bSjt9pjaEBnNiGgc9rUiHGKv5l4/TGzDmYw3RhnkJGtLhbnnA/5qJj7x3dNDCRx/PJxu774LlH8lCOlB4hEfKg==} - update-browserslist-db@1.1.4: - resolution: {integrity: sha512-q0SPT4xyU84saUX+tomz1WLkxUbuaJnR1xWt17M7fJtEJigJeWUNGUqrauFXsHnqev9y9JTRGwk13tFBuKby4A==} + update-browserslist-db@1.2.3: + resolution: {integrity: sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==} hasBin: true peerDependencies: browserslist: '>= 4.21.0' @@ -3278,25 +3340,25 @@ packages: snapshots: - '@babel/code-frame@7.27.1': + '@babel/code-frame@7.29.0': dependencies: '@babel/helper-validator-identifier': 7.28.5 js-tokens: 4.0.0 picocolors: 1.1.1 - '@babel/compat-data@7.28.5': {} + '@babel/compat-data@7.29.0': {} - '@babel/core@7.28.5': + '@babel/core@7.29.0': dependencies: - '@babel/code-frame': 7.27.1 - '@babel/generator': 7.28.5 - '@babel/helper-compilation-targets': 7.27.2 - '@babel/helper-module-transforms': 7.28.3(@babel/core@7.28.5) - '@babel/helpers': 7.28.4 - '@babel/parser': 7.28.5 - '@babel/template': 7.27.2 - '@babel/traverse': 7.28.5 - '@babel/types': 7.28.5 + '@babel/code-frame': 7.29.0 + '@babel/generator': 7.29.1 + '@babel/helper-compilation-targets': 7.28.6 + '@babel/helper-module-transforms': 7.28.6(@babel/core@7.29.0) + '@babel/helpers': 7.29.2 + '@babel/parser': 7.29.2 + '@babel/template': 7.28.6 + '@babel/traverse': 7.29.0 + '@babel/types': 7.29.0 '@jridgewell/remapping': 2.3.5 convert-source-map: 2.0.0 debug: 4.4.3 @@ -3306,41 +3368,41 @@ snapshots: transitivePeerDependencies: - supports-color - '@babel/generator@7.28.5': + '@babel/generator@7.29.1': dependencies: - '@babel/parser': 7.28.5 - '@babel/types': 7.28.5 + '@babel/parser': 7.29.2 + '@babel/types': 7.29.0 '@jridgewell/gen-mapping': 0.3.13 '@jridgewell/trace-mapping': 0.3.31 jsesc: 3.1.0 - '@babel/helper-compilation-targets@7.27.2': + '@babel/helper-compilation-targets@7.28.6': dependencies: - '@babel/compat-data': 7.28.5 + '@babel/compat-data': 7.29.0 '@babel/helper-validator-option': 7.27.1 - browserslist: 4.28.0 + browserslist: 4.28.1 lru-cache: 5.1.1 semver: 6.3.1 '@babel/helper-globals@7.28.0': {} - '@babel/helper-module-imports@7.27.1': + '@babel/helper-module-imports@7.28.6': dependencies: - '@babel/traverse': 7.28.5 - '@babel/types': 7.28.5 + '@babel/traverse': 7.29.0 + '@babel/types': 7.29.0 transitivePeerDependencies: - supports-color - '@babel/helper-module-transforms@7.28.3(@babel/core@7.28.5)': + '@babel/helper-module-transforms@7.28.6(@babel/core@7.29.0)': dependencies: - '@babel/core': 7.28.5 - '@babel/helper-module-imports': 7.27.1 + '@babel/core': 7.29.0 + '@babel/helper-module-imports': 7.28.6 '@babel/helper-validator-identifier': 7.28.5 - '@babel/traverse': 7.28.5 + '@babel/traverse': 7.29.0 transitivePeerDependencies: - supports-color - '@babel/helper-plugin-utils@7.27.1': {} + '@babel/helper-plugin-utils@7.28.6': {} '@babel/helper-string-parser@7.27.1': {} @@ -3348,121 +3410,121 @@ snapshots: '@babel/helper-validator-option@7.27.1': {} - '@babel/helpers@7.28.4': + '@babel/helpers@7.29.2': dependencies: - '@babel/template': 7.27.2 - '@babel/types': 7.28.5 + '@babel/template': 7.28.6 + '@babel/types': 7.29.0 - '@babel/parser@7.28.5': + '@babel/parser@7.29.2': dependencies: - '@babel/types': 7.28.5 + '@babel/types': 7.29.0 - '@babel/plugin-syntax-async-generators@7.8.4(@babel/core@7.28.5)': + '@babel/plugin-syntax-async-generators@7.8.4(@babel/core@7.29.0)': dependencies: - '@babel/core': 7.28.5 - '@babel/helper-plugin-utils': 7.27.1 + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 - '@babel/plugin-syntax-bigint@7.8.3(@babel/core@7.28.5)': + '@babel/plugin-syntax-bigint@7.8.3(@babel/core@7.29.0)': dependencies: - '@babel/core': 7.28.5 - '@babel/helper-plugin-utils': 7.27.1 + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 - '@babel/plugin-syntax-class-properties@7.12.13(@babel/core@7.28.5)': + '@babel/plugin-syntax-class-properties@7.12.13(@babel/core@7.29.0)': dependencies: - '@babel/core': 7.28.5 - '@babel/helper-plugin-utils': 7.27.1 + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 - '@babel/plugin-syntax-class-static-block@7.14.5(@babel/core@7.28.5)': + '@babel/plugin-syntax-class-static-block@7.14.5(@babel/core@7.29.0)': dependencies: - '@babel/core': 7.28.5 - '@babel/helper-plugin-utils': 7.27.1 + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 - '@babel/plugin-syntax-import-attributes@7.27.1(@babel/core@7.28.5)': + '@babel/plugin-syntax-import-attributes@7.28.6(@babel/core@7.29.0)': dependencies: - '@babel/core': 7.28.5 - '@babel/helper-plugin-utils': 7.27.1 + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 - '@babel/plugin-syntax-import-meta@7.10.4(@babel/core@7.28.5)': + '@babel/plugin-syntax-import-meta@7.10.4(@babel/core@7.29.0)': dependencies: - '@babel/core': 7.28.5 - '@babel/helper-plugin-utils': 7.27.1 + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 - '@babel/plugin-syntax-json-strings@7.8.3(@babel/core@7.28.5)': + '@babel/plugin-syntax-json-strings@7.8.3(@babel/core@7.29.0)': dependencies: - '@babel/core': 7.28.5 - '@babel/helper-plugin-utils': 7.27.1 + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 - '@babel/plugin-syntax-jsx@7.27.1(@babel/core@7.28.5)': + '@babel/plugin-syntax-jsx@7.28.6(@babel/core@7.29.0)': dependencies: - '@babel/core': 7.28.5 - '@babel/helper-plugin-utils': 7.27.1 + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 - '@babel/plugin-syntax-logical-assignment-operators@7.10.4(@babel/core@7.28.5)': + '@babel/plugin-syntax-logical-assignment-operators@7.10.4(@babel/core@7.29.0)': dependencies: - '@babel/core': 7.28.5 - '@babel/helper-plugin-utils': 7.27.1 + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 - '@babel/plugin-syntax-nullish-coalescing-operator@7.8.3(@babel/core@7.28.5)': + '@babel/plugin-syntax-nullish-coalescing-operator@7.8.3(@babel/core@7.29.0)': dependencies: - '@babel/core': 7.28.5 - '@babel/helper-plugin-utils': 7.27.1 + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 - '@babel/plugin-syntax-numeric-separator@7.10.4(@babel/core@7.28.5)': + '@babel/plugin-syntax-numeric-separator@7.10.4(@babel/core@7.29.0)': dependencies: - '@babel/core': 7.28.5 - '@babel/helper-plugin-utils': 7.27.1 + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 - '@babel/plugin-syntax-object-rest-spread@7.8.3(@babel/core@7.28.5)': + '@babel/plugin-syntax-object-rest-spread@7.8.3(@babel/core@7.29.0)': dependencies: - '@babel/core': 7.28.5 - '@babel/helper-plugin-utils': 7.27.1 + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 - '@babel/plugin-syntax-optional-catch-binding@7.8.3(@babel/core@7.28.5)': + '@babel/plugin-syntax-optional-catch-binding@7.8.3(@babel/core@7.29.0)': dependencies: - '@babel/core': 7.28.5 - '@babel/helper-plugin-utils': 7.27.1 + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 - '@babel/plugin-syntax-optional-chaining@7.8.3(@babel/core@7.28.5)': + '@babel/plugin-syntax-optional-chaining@7.8.3(@babel/core@7.29.0)': dependencies: - '@babel/core': 7.28.5 - '@babel/helper-plugin-utils': 7.27.1 + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 - '@babel/plugin-syntax-private-property-in-object@7.14.5(@babel/core@7.28.5)': + '@babel/plugin-syntax-private-property-in-object@7.14.5(@babel/core@7.29.0)': dependencies: - '@babel/core': 7.28.5 - '@babel/helper-plugin-utils': 7.27.1 + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 - '@babel/plugin-syntax-top-level-await@7.14.5(@babel/core@7.28.5)': + '@babel/plugin-syntax-top-level-await@7.14.5(@babel/core@7.29.0)': dependencies: - '@babel/core': 7.28.5 - '@babel/helper-plugin-utils': 7.27.1 + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 - '@babel/plugin-syntax-typescript@7.27.1(@babel/core@7.28.5)': + '@babel/plugin-syntax-typescript@7.28.6(@babel/core@7.29.0)': dependencies: - '@babel/core': 7.28.5 - '@babel/helper-plugin-utils': 7.27.1 + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 '@babel/runtime@7.28.4': {} - '@babel/template@7.27.2': + '@babel/template@7.28.6': dependencies: - '@babel/code-frame': 7.27.1 - '@babel/parser': 7.28.5 - '@babel/types': 7.28.5 + '@babel/code-frame': 7.29.0 + '@babel/parser': 7.29.2 + '@babel/types': 7.29.0 - '@babel/traverse@7.28.5': + '@babel/traverse@7.29.0': dependencies: - '@babel/code-frame': 7.27.1 - '@babel/generator': 7.28.5 + '@babel/code-frame': 7.29.0 + '@babel/generator': 7.29.1 '@babel/helper-globals': 7.28.0 - '@babel/parser': 7.28.5 - '@babel/template': 7.27.2 - '@babel/types': 7.28.5 + '@babel/parser': 7.29.2 + '@babel/template': 7.28.6 + '@babel/types': 7.29.0 debug: 4.4.3 transitivePeerDependencies: - supports-color - '@babel/types@7.28.5': + '@babel/types@7.29.0': dependencies: '@babel/helper-string-parser': 7.27.1 '@babel/helper-validator-identifier': 7.28.5 @@ -3628,79 +3690,60 @@ snapshots: human-id: 4.1.3 prettier: 2.8.8 - '@codama/errors@1.4.4': - dependencies: - '@codama/node-types': 1.4.4 - commander: 14.0.2 - picocolors: 1.1.1 - - '@codama/errors@1.5.0': + '@codama/errors@1.5.1': dependencies: - '@codama/node-types': 1.5.0 - commander: 14.0.2 + '@codama/node-types': 1.5.1 + commander: 14.0.3 picocolors: 1.1.1 - '@codama/node-types@1.4.4': {} + '@codama/node-types@1.5.1': {} - '@codama/node-types@1.5.0': {} - - '@codama/nodes-from-anchor@1.3.6(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)': + '@codama/nodes-from-anchor@1.4.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)': dependencies: - '@codama/errors': 1.4.4 - '@codama/nodes': 1.4.4 - '@codama/visitors': 1.4.4 + '@codama/errors': 1.5.1 + '@codama/nodes': 1.5.1 + '@codama/visitors': 1.5.1 '@noble/hashes': 2.0.1 - '@solana/codecs': 5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) + '@solana/codecs': 5.5.1(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) transitivePeerDependencies: - fastestsmallesttextencoderdecoder - typescript - '@codama/nodes@1.4.4': - dependencies: - '@codama/errors': 1.4.4 - '@codama/node-types': 1.4.4 - - '@codama/nodes@1.5.0': + '@codama/nodes@1.5.1': dependencies: - '@codama/errors': 1.5.0 - '@codama/node-types': 1.5.0 + '@codama/errors': 1.5.1 + '@codama/node-types': 1.5.1 - '@codama/renderers-core@1.3.5': + '@codama/renderers-core@1.3.6': dependencies: - '@codama/errors': 1.5.0 - '@codama/nodes': 1.5.0 - '@codama/visitors-core': 1.5.0 + '@codama/errors': 1.5.1 + '@codama/nodes': 1.5.1 + '@codama/visitors-core': 1.5.1 - '@codama/visitors-core@1.4.4': + '@codama/visitors-core@1.5.1': dependencies: - '@codama/errors': 1.4.4 - '@codama/nodes': 1.4.4 + '@codama/errors': 1.5.1 + '@codama/nodes': 1.5.1 json-stable-stringify: 1.3.0 - '@codama/visitors-core@1.5.0': + '@codama/visitors@1.5.1': dependencies: - '@codama/errors': 1.5.0 - '@codama/nodes': 1.5.0 - json-stable-stringify: 1.3.0 - - '@codama/visitors@1.4.4': - dependencies: - '@codama/errors': 1.4.4 - '@codama/nodes': 1.4.4 - '@codama/visitors-core': 1.4.4 + '@codama/errors': 1.5.1 + '@codama/nodes': 1.5.1 + '@codama/visitors-core': 1.5.1 - '@emnapi/core@1.7.1': + '@emnapi/core@1.9.1': dependencies: - '@emnapi/wasi-threads': 1.1.0 + '@emnapi/wasi-threads': 1.2.0 tslib: 2.8.1 optional: true - '@emnapi/runtime@1.7.1': + '@emnapi/runtime@1.9.1': dependencies: tslib: 2.8.1 optional: true - '@emnapi/wasi-threads@1.1.0': + '@emnapi/wasi-threads@1.2.0': dependencies: tslib: 2.8.1 optional: true @@ -3866,6 +3909,11 @@ snapshots: eslint: 9.39.1 eslint-visitor-keys: 3.4.3 + '@eslint-community/eslint-utils@4.9.1(eslint@9.39.1)': + dependencies: + eslint: 9.39.1 + eslint-visitor-keys: 3.4.3 + '@eslint-community/regexpp@4.12.2': {} '@eslint/config-array@0.21.1': @@ -3955,7 +4003,7 @@ snapshots: '@jest/console@30.1.2': dependencies: '@jest/types': 30.0.5 - '@types/node': 25.2.3 + '@types/node': 25.5.0 chalk: 4.1.2 jest-message-util: 30.1.0 jest-util: 30.0.5 @@ -3969,14 +4017,14 @@ snapshots: '@jest/test-result': 30.1.3 '@jest/transform': 30.1.2 '@jest/types': 30.0.5 - '@types/node': 25.2.3 + '@types/node': 25.5.0 ansi-escapes: 4.3.2 chalk: 4.1.2 - ci-info: 4.3.1 + ci-info: 4.4.0 exit-x: 0.2.2 graceful-fs: 4.2.11 jest-changed-files: 30.0.5 - jest-config: 30.1.3(@types/node@25.2.3) + jest-config: 30.1.3(@types/node@25.5.0) jest-haste-map: 30.1.0 jest-message-util: 30.1.0 jest-regex-util: 30.0.1 @@ -4003,7 +4051,7 @@ snapshots: dependencies: '@jest/fake-timers': 30.1.2 '@jest/types': 30.0.5 - '@types/node': 25.2.3 + '@types/node': 25.5.0 jest-mock: 30.0.5 '@jest/expect-utils@30.1.2': @@ -4021,7 +4069,7 @@ snapshots: dependencies: '@jest/types': 30.0.5 '@sinonjs/fake-timers': 13.0.5 - '@types/node': 25.2.3 + '@types/node': 25.5.0 jest-message-util: 30.1.0 jest-mock: 30.0.5 jest-util: 30.0.5 @@ -4039,7 +4087,7 @@ snapshots: '@jest/pattern@30.0.1': dependencies: - '@types/node': 25.2.3 + '@types/node': 25.5.0 jest-regex-util: 30.0.1 '@jest/reporters@30.1.3': @@ -4050,7 +4098,7 @@ snapshots: '@jest/transform': 30.1.2 '@jest/types': 30.0.5 '@jridgewell/trace-mapping': 0.3.31 - '@types/node': 25.2.3 + '@types/node': 25.5.0 chalk: 4.1.2 collect-v8-coverage: 1.0.3 exit-x: 0.2.2 @@ -4072,7 +4120,7 @@ snapshots: '@jest/schemas@30.0.5': dependencies: - '@sinclair/typebox': 0.34.41 + '@sinclair/typebox': 0.34.48 '@jest/snapshot-utils@30.1.2': dependencies: @@ -4103,7 +4151,7 @@ snapshots: '@jest/transform@30.1.2': dependencies: - '@babel/core': 7.28.5 + '@babel/core': 7.29.0 '@jest/types': 30.0.5 '@jridgewell/trace-mapping': 0.3.31 babel-plugin-istanbul: 7.0.1 @@ -4127,7 +4175,7 @@ snapshots: '@jest/schemas': 30.0.5 '@types/istanbul-lib-coverage': 2.0.6 '@types/istanbul-reports': 3.0.4 - '@types/node': 25.2.3 + '@types/node': 25.5.0 '@types/yargs': 17.0.35 chalk: 4.1.2 @@ -4168,11 +4216,15 @@ snapshots: '@napi-rs/wasm-runtime@0.2.12': dependencies: - '@emnapi/core': 1.7.1 - '@emnapi/runtime': 1.7.1 + '@emnapi/core': 1.9.1 + '@emnapi/runtime': 1.9.1 '@tybys/wasm-util': 0.10.1 optional: true + '@noble/curves@2.0.1': + dependencies: + '@noble/hashes': 2.0.1 + '@noble/hashes@2.0.1': {} '@nodelib/fs.scandir@2.1.5': @@ -4328,7 +4380,7 @@ snapshots: '@rollup/rollup-win32-x64-msvc@4.53.3': optional: true - '@sinclair/typebox@0.34.41': {} + '@sinclair/typebox@0.34.48': {} '@sinonjs/commons@3.0.1': dependencies: @@ -4338,72 +4390,78 @@ snapshots: dependencies: '@sinonjs/commons': 3.0.1 - '@solana/codecs-core@5.0.0(typescript@5.9.3)': + '@solana/codecs-core@5.5.1(typescript@5.9.3)': dependencies: - '@solana/errors': 5.0.0(typescript@5.9.3) + '@solana/errors': 5.5.1(typescript@5.9.3) + optionalDependencies: typescript: 5.9.3 - '@solana/codecs-core@6.0.1(typescript@5.9.3)': + '@solana/codecs-core@6.5.0(typescript@5.9.3)': dependencies: - '@solana/errors': 6.0.1(typescript@5.9.3) + '@solana/errors': 6.5.0(typescript@5.9.3) optionalDependencies: typescript: 5.9.3 - '@solana/codecs-data-structures@5.0.0(typescript@5.9.3)': + '@solana/codecs-data-structures@5.5.1(typescript@5.9.3)': dependencies: - '@solana/codecs-core': 5.0.0(typescript@5.9.3) - '@solana/codecs-numbers': 5.0.0(typescript@5.9.3) - '@solana/errors': 5.0.0(typescript@5.9.3) + '@solana/codecs-core': 5.5.1(typescript@5.9.3) + '@solana/codecs-numbers': 5.5.1(typescript@5.9.3) + '@solana/errors': 5.5.1(typescript@5.9.3) + optionalDependencies: typescript: 5.9.3 - '@solana/codecs-numbers@5.0.0(typescript@5.9.3)': + '@solana/codecs-numbers@5.5.1(typescript@5.9.3)': dependencies: - '@solana/codecs-core': 5.0.0(typescript@5.9.3) - '@solana/errors': 5.0.0(typescript@5.9.3) + '@solana/codecs-core': 5.5.1(typescript@5.9.3) + '@solana/errors': 5.5.1(typescript@5.9.3) + optionalDependencies: typescript: 5.9.3 - '@solana/codecs-numbers@6.0.1(typescript@5.9.3)': + '@solana/codecs-numbers@6.5.0(typescript@5.9.3)': dependencies: - '@solana/codecs-core': 6.0.1(typescript@5.9.3) - '@solana/errors': 6.0.1(typescript@5.9.3) + '@solana/codecs-core': 6.5.0(typescript@5.9.3) + '@solana/errors': 6.5.0(typescript@5.9.3) optionalDependencies: typescript: 5.9.3 - '@solana/codecs-strings@5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)': + '@solana/codecs-strings@5.5.1(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)': dependencies: - '@solana/codecs-core': 5.0.0(typescript@5.9.3) - '@solana/codecs-numbers': 5.0.0(typescript@5.9.3) - '@solana/errors': 5.0.0(typescript@5.9.3) + '@solana/codecs-core': 5.5.1(typescript@5.9.3) + '@solana/codecs-numbers': 5.5.1(typescript@5.9.3) + '@solana/errors': 5.5.1(typescript@5.9.3) + optionalDependencies: fastestsmallesttextencoderdecoder: 1.0.22 typescript: 5.9.3 - '@solana/codecs-strings@6.0.1(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)': + '@solana/codecs-strings@6.5.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)': dependencies: - '@solana/codecs-core': 6.0.1(typescript@5.9.3) - '@solana/codecs-numbers': 6.0.1(typescript@5.9.3) - '@solana/errors': 6.0.1(typescript@5.9.3) + '@solana/codecs-core': 6.5.0(typescript@5.9.3) + '@solana/codecs-numbers': 6.5.0(typescript@5.9.3) + '@solana/errors': 6.5.0(typescript@5.9.3) optionalDependencies: fastestsmallesttextencoderdecoder: 1.0.22 typescript: 5.9.3 - '@solana/codecs@5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)': + '@solana/codecs@5.5.1(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)': dependencies: - '@solana/codecs-core': 5.0.0(typescript@5.9.3) - '@solana/codecs-data-structures': 5.0.0(typescript@5.9.3) - '@solana/codecs-numbers': 5.0.0(typescript@5.9.3) - '@solana/codecs-strings': 5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) - '@solana/options': 5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) + '@solana/codecs-core': 5.5.1(typescript@5.9.3) + '@solana/codecs-data-structures': 5.5.1(typescript@5.9.3) + '@solana/codecs-numbers': 5.5.1(typescript@5.9.3) + '@solana/codecs-strings': 5.5.1(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) + '@solana/options': 5.5.1(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) + optionalDependencies: typescript: 5.9.3 transitivePeerDependencies: - fastestsmallesttextencoderdecoder - '@solana/errors@5.0.0(typescript@5.9.3)': + '@solana/errors@5.5.1(typescript@5.9.3)': dependencies: chalk: 5.6.2 - commander: 14.0.1 + commander: 14.0.2 + optionalDependencies: typescript: 5.9.3 - '@solana/errors@6.0.1(typescript@5.9.3)': + '@solana/errors@6.5.0(typescript@5.9.3)': dependencies: chalk: 5.6.2 commander: 14.0.3 @@ -4425,13 +4483,14 @@ snapshots: typescript: 5.9.3 typescript-eslint: 8.43.0(eslint@9.39.1)(typescript@5.9.3) - '@solana/options@5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)': + '@solana/options@5.5.1(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)': dependencies: - '@solana/codecs-core': 5.0.0(typescript@5.9.3) - '@solana/codecs-data-structures': 5.0.0(typescript@5.9.3) - '@solana/codecs-numbers': 5.0.0(typescript@5.9.3) - '@solana/codecs-strings': 5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) - '@solana/errors': 5.0.0(typescript@5.9.3) + '@solana/codecs-core': 5.5.1(typescript@5.9.3) + '@solana/codecs-data-structures': 5.5.1(typescript@5.9.3) + '@solana/codecs-numbers': 5.5.1(typescript@5.9.3) + '@solana/codecs-strings': 5.5.1(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) + '@solana/errors': 5.5.1(typescript@5.9.3) + optionalDependencies: typescript: 5.9.3 transitivePeerDependencies: - fastestsmallesttextencoderdecoder @@ -4449,24 +4508,24 @@ snapshots: '@types/babel__core@7.20.5': dependencies: - '@babel/parser': 7.28.5 - '@babel/types': 7.28.5 + '@babel/parser': 7.29.2 + '@babel/types': 7.29.0 '@types/babel__generator': 7.27.0 '@types/babel__template': 7.4.4 '@types/babel__traverse': 7.28.0 '@types/babel__generator@7.27.0': dependencies: - '@babel/types': 7.28.5 + '@babel/types': 7.29.0 '@types/babel__template@7.4.4': dependencies: - '@babel/parser': 7.28.5 - '@babel/types': 7.28.5 + '@babel/parser': 7.29.2 + '@babel/types': 7.29.0 '@types/babel__traverse@7.28.0': dependencies: - '@babel/types': 7.28.5 + '@babel/types': 7.29.0 '@types/chai@5.2.3': dependencies: @@ -4508,6 +4567,10 @@ snapshots: dependencies: undici-types: 7.16.0 + '@types/node@25.5.0': + dependencies: + undici-types: 7.18.2 + '@types/nunjucks@3.2.6': {} '@types/semver@7.7.1': {} @@ -4534,7 +4597,7 @@ snapshots: graphemer: 1.4.0 ignore: 7.0.5 natural-compare: 1.4.0 - ts-api-utils: 2.1.0(typescript@5.9.3) + ts-api-utils: 2.5.0(typescript@5.9.3) typescript: 5.9.3 transitivePeerDependencies: - supports-color @@ -4561,17 +4624,17 @@ snapshots: '@typescript-eslint/project-service@8.43.0(typescript@5.9.3)': dependencies: - '@typescript-eslint/tsconfig-utils': 8.48.1(typescript@5.9.3) - '@typescript-eslint/types': 8.48.1 + '@typescript-eslint/tsconfig-utils': 8.57.2(typescript@5.9.3) + '@typescript-eslint/types': 8.57.2 debug: 4.4.3 typescript: 5.9.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/project-service@8.48.1(typescript@5.9.3)': + '@typescript-eslint/project-service@8.57.2(typescript@5.9.3)': dependencies: - '@typescript-eslint/tsconfig-utils': 8.48.1(typescript@5.9.3) - '@typescript-eslint/types': 8.48.1 + '@typescript-eslint/tsconfig-utils': 8.57.2(typescript@5.9.3) + '@typescript-eslint/types': 8.57.2 debug: 4.4.3 typescript: 5.9.3 transitivePeerDependencies: @@ -4587,16 +4650,16 @@ snapshots: '@typescript-eslint/types': 8.43.0 '@typescript-eslint/visitor-keys': 8.43.0 - '@typescript-eslint/scope-manager@8.48.1': + '@typescript-eslint/scope-manager@8.57.2': dependencies: - '@typescript-eslint/types': 8.48.1 - '@typescript-eslint/visitor-keys': 8.48.1 + '@typescript-eslint/types': 8.57.2 + '@typescript-eslint/visitor-keys': 8.57.2 '@typescript-eslint/tsconfig-utils@8.43.0(typescript@5.9.3)': dependencies: typescript: 5.9.3 - '@typescript-eslint/tsconfig-utils@8.48.1(typescript@5.9.3)': + '@typescript-eslint/tsconfig-utils@8.57.2(typescript@5.9.3)': dependencies: typescript: 5.9.3 @@ -4607,7 +4670,7 @@ snapshots: '@typescript-eslint/utils': 8.43.0(eslint@9.39.1)(typescript@5.9.3) debug: 4.4.3 eslint: 9.39.1 - ts-api-utils: 2.1.0(typescript@5.9.3) + ts-api-utils: 2.5.0(typescript@5.9.3) typescript: 5.9.3 transitivePeerDependencies: - supports-color @@ -4616,7 +4679,7 @@ snapshots: '@typescript-eslint/types@8.43.0': {} - '@typescript-eslint/types@8.48.1': {} + '@typescript-eslint/types@8.57.2': {} '@typescript-eslint/typescript-estree@5.62.0(typescript@5.9.3)': dependencies: @@ -4625,7 +4688,7 @@ snapshots: debug: 4.4.3 globby: 11.1.0 is-glob: 4.0.3 - semver: 7.7.3 + semver: 7.7.4 tsutils: 3.21.0(typescript@5.9.3) optionalDependencies: typescript: 5.9.3 @@ -4641,31 +4704,31 @@ snapshots: debug: 4.4.3 fast-glob: 3.3.3 is-glob: 4.0.3 - minimatch: 9.0.5 - semver: 7.7.3 - ts-api-utils: 2.1.0(typescript@5.9.3) + minimatch: 9.0.9 + semver: 7.7.4 + ts-api-utils: 2.5.0(typescript@5.9.3) typescript: 5.9.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/typescript-estree@8.48.1(typescript@5.9.3)': + '@typescript-eslint/typescript-estree@8.57.2(typescript@5.9.3)': dependencies: - '@typescript-eslint/project-service': 8.48.1(typescript@5.9.3) - '@typescript-eslint/tsconfig-utils': 8.48.1(typescript@5.9.3) - '@typescript-eslint/types': 8.48.1 - '@typescript-eslint/visitor-keys': 8.48.1 + '@typescript-eslint/project-service': 8.57.2(typescript@5.9.3) + '@typescript-eslint/tsconfig-utils': 8.57.2(typescript@5.9.3) + '@typescript-eslint/types': 8.57.2 + '@typescript-eslint/visitor-keys': 8.57.2 debug: 4.4.3 - minimatch: 9.0.5 - semver: 7.7.3 + minimatch: 10.2.4 + semver: 7.7.4 tinyglobby: 0.2.15 - ts-api-utils: 2.1.0(typescript@5.9.3) + ts-api-utils: 2.5.0(typescript@5.9.3) typescript: 5.9.3 transitivePeerDependencies: - supports-color '@typescript-eslint/utils@5.62.0(eslint@9.39.1)(typescript@5.9.3)': dependencies: - '@eslint-community/eslint-utils': 4.9.0(eslint@9.39.1) + '@eslint-community/eslint-utils': 4.9.1(eslint@9.39.1) '@types/json-schema': 7.0.15 '@types/semver': 7.7.1 '@typescript-eslint/scope-manager': 5.62.0 @@ -4673,14 +4736,14 @@ snapshots: '@typescript-eslint/typescript-estree': 5.62.0(typescript@5.9.3) eslint: 9.39.1 eslint-scope: 5.1.1 - semver: 7.7.3 + semver: 7.7.4 transitivePeerDependencies: - supports-color - typescript '@typescript-eslint/utils@8.43.0(eslint@9.39.1)(typescript@5.9.3)': dependencies: - '@eslint-community/eslint-utils': 4.9.0(eslint@9.39.1) + '@eslint-community/eslint-utils': 4.9.1(eslint@9.39.1) '@typescript-eslint/scope-manager': 8.43.0 '@typescript-eslint/types': 8.43.0 '@typescript-eslint/typescript-estree': 8.43.0(typescript@5.9.3) @@ -4689,12 +4752,12 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/utils@8.48.1(eslint@9.39.1)(typescript@5.9.3)': + '@typescript-eslint/utils@8.57.2(eslint@9.39.1)(typescript@5.9.3)': dependencies: - '@eslint-community/eslint-utils': 4.9.0(eslint@9.39.1) - '@typescript-eslint/scope-manager': 8.48.1 - '@typescript-eslint/types': 8.48.1 - '@typescript-eslint/typescript-estree': 8.48.1(typescript@5.9.3) + '@eslint-community/eslint-utils': 4.9.1(eslint@9.39.1) + '@typescript-eslint/scope-manager': 8.57.2 + '@typescript-eslint/types': 8.57.2 + '@typescript-eslint/typescript-estree': 8.57.2(typescript@5.9.3) eslint: 9.39.1 typescript: 5.9.3 transitivePeerDependencies: @@ -4710,10 +4773,10 @@ snapshots: '@typescript-eslint/types': 8.43.0 eslint-visitor-keys: 4.2.1 - '@typescript-eslint/visitor-keys@8.48.1': + '@typescript-eslint/visitor-keys@8.57.2': dependencies: - '@typescript-eslint/types': 8.48.1 - eslint-visitor-keys: 4.2.1 + '@typescript-eslint/types': 8.57.2 + eslint-visitor-keys: 5.0.1 '@ungap/structured-clone@1.3.0': {} @@ -4865,7 +4928,7 @@ snapshots: anymatch@3.1.3: dependencies: normalize-path: 3.0.0 - picomatch: 2.3.1 + picomatch: 2.3.2 argparse@1.0.10: dependencies: @@ -4879,13 +4942,13 @@ snapshots: assertion-error@2.0.1: {} - babel-jest@30.1.2(@babel/core@7.28.5): + babel-jest@30.1.2(@babel/core@7.29.0): dependencies: - '@babel/core': 7.28.5 + '@babel/core': 7.29.0 '@jest/transform': 30.1.2 '@types/babel__core': 7.20.5 babel-plugin-istanbul: 7.0.1 - babel-preset-jest: 30.0.1(@babel/core@7.28.5) + babel-preset-jest: 30.0.1(@babel/core@7.29.0) chalk: 4.1.2 graceful-fs: 4.2.11 slash: 3.0.0 @@ -4894,7 +4957,7 @@ snapshots: babel-plugin-istanbul@7.0.1: dependencies: - '@babel/helper-plugin-utils': 7.27.1 + '@babel/helper-plugin-utils': 7.28.6 '@istanbuljs/load-nyc-config': 1.1.0 '@istanbuljs/schema': 0.1.3 istanbul-lib-instrument: 6.0.3 @@ -4904,38 +4967,40 @@ snapshots: babel-plugin-jest-hoist@30.0.1: dependencies: - '@babel/template': 7.27.2 - '@babel/types': 7.28.5 + '@babel/template': 7.28.6 + '@babel/types': 7.29.0 '@types/babel__core': 7.20.5 - babel-preset-current-node-syntax@1.2.0(@babel/core@7.28.5): - dependencies: - '@babel/core': 7.28.5 - '@babel/plugin-syntax-async-generators': 7.8.4(@babel/core@7.28.5) - '@babel/plugin-syntax-bigint': 7.8.3(@babel/core@7.28.5) - '@babel/plugin-syntax-class-properties': 7.12.13(@babel/core@7.28.5) - '@babel/plugin-syntax-class-static-block': 7.14.5(@babel/core@7.28.5) - '@babel/plugin-syntax-import-attributes': 7.27.1(@babel/core@7.28.5) - '@babel/plugin-syntax-import-meta': 7.10.4(@babel/core@7.28.5) - '@babel/plugin-syntax-json-strings': 7.8.3(@babel/core@7.28.5) - '@babel/plugin-syntax-logical-assignment-operators': 7.10.4(@babel/core@7.28.5) - '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3(@babel/core@7.28.5) - '@babel/plugin-syntax-numeric-separator': 7.10.4(@babel/core@7.28.5) - '@babel/plugin-syntax-object-rest-spread': 7.8.3(@babel/core@7.28.5) - '@babel/plugin-syntax-optional-catch-binding': 7.8.3(@babel/core@7.28.5) - '@babel/plugin-syntax-optional-chaining': 7.8.3(@babel/core@7.28.5) - '@babel/plugin-syntax-private-property-in-object': 7.14.5(@babel/core@7.28.5) - '@babel/plugin-syntax-top-level-await': 7.14.5(@babel/core@7.28.5) - - babel-preset-jest@30.0.1(@babel/core@7.28.5): - dependencies: - '@babel/core': 7.28.5 + babel-preset-current-node-syntax@1.2.0(@babel/core@7.29.0): + dependencies: + '@babel/core': 7.29.0 + '@babel/plugin-syntax-async-generators': 7.8.4(@babel/core@7.29.0) + '@babel/plugin-syntax-bigint': 7.8.3(@babel/core@7.29.0) + '@babel/plugin-syntax-class-properties': 7.12.13(@babel/core@7.29.0) + '@babel/plugin-syntax-class-static-block': 7.14.5(@babel/core@7.29.0) + '@babel/plugin-syntax-import-attributes': 7.28.6(@babel/core@7.29.0) + '@babel/plugin-syntax-import-meta': 7.10.4(@babel/core@7.29.0) + '@babel/plugin-syntax-json-strings': 7.8.3(@babel/core@7.29.0) + '@babel/plugin-syntax-logical-assignment-operators': 7.10.4(@babel/core@7.29.0) + '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3(@babel/core@7.29.0) + '@babel/plugin-syntax-numeric-separator': 7.10.4(@babel/core@7.29.0) + '@babel/plugin-syntax-object-rest-spread': 7.8.3(@babel/core@7.29.0) + '@babel/plugin-syntax-optional-catch-binding': 7.8.3(@babel/core@7.29.0) + '@babel/plugin-syntax-optional-chaining': 7.8.3(@babel/core@7.29.0) + '@babel/plugin-syntax-private-property-in-object': 7.14.5(@babel/core@7.29.0) + '@babel/plugin-syntax-top-level-await': 7.14.5(@babel/core@7.29.0) + + babel-preset-jest@30.0.1(@babel/core@7.29.0): + dependencies: + '@babel/core': 7.29.0 babel-plugin-jest-hoist: 30.0.1 - babel-preset-current-node-syntax: 1.2.0(@babel/core@7.28.5) + babel-preset-current-node-syntax: 1.2.0(@babel/core@7.29.0) balanced-match@1.0.2: {} - baseline-browser-mapping@2.8.32: {} + balanced-match@4.0.4: {} + + baseline-browser-mapping@2.10.10: {} better-path-resolve@1.0.0: dependencies: @@ -4950,17 +5015,21 @@ snapshots: dependencies: balanced-match: 1.0.2 + brace-expansion@5.0.4: + dependencies: + balanced-match: 4.0.4 + braces@3.0.3: dependencies: fill-range: 7.1.1 - browserslist@4.28.0: + browserslist@4.28.1: dependencies: - baseline-browser-mapping: 2.8.32 - caniuse-lite: 1.0.30001757 - electron-to-chromium: 1.5.263 - node-releases: 2.0.27 - update-browserslist-db: 1.1.4(browserslist@4.28.0) + baseline-browser-mapping: 2.10.10 + caniuse-lite: 1.0.30001781 + electron-to-chromium: 1.5.322 + node-releases: 2.0.36 + update-browserslist-db: 1.2.3(browserslist@4.28.1) bser@2.1.1: dependencies: @@ -4998,7 +5067,7 @@ snapshots: camelcase@6.3.0: {} - caniuse-lite@1.0.30001757: {} + caniuse-lite@1.0.30001781: {} chai@6.2.1: {} @@ -5019,9 +5088,9 @@ snapshots: ci-info@3.9.0: {} - ci-info@4.3.1: {} + ci-info@4.4.0: {} - cjs-module-lexer@2.1.1: {} + cjs-module-lexer@2.2.0: {} cliui@8.0.1: dependencies: @@ -5039,8 +5108,6 @@ snapshots: color-name@1.1.4: {} - commander@14.0.1: {} - commander@14.0.2: {} commander@14.0.3: {} @@ -5069,7 +5136,7 @@ snapshots: dependencies: ms: 2.1.3 - dedent@1.7.0: {} + dedent@1.7.2: {} deep-is@0.1.4: {} @@ -5099,7 +5166,7 @@ snapshots: eastasianwidth@0.2.0: {} - electron-to-chromium@1.5.263: {} + electron-to-chromium@1.5.322: {} emittery@0.13.1: {} @@ -5192,7 +5259,7 @@ snapshots: eslint-plugin-jest@29.0.1(@typescript-eslint/eslint-plugin@8.43.0(@typescript-eslint/parser@8.43.0(eslint@9.39.1)(typescript@5.9.3))(eslint@9.39.1)(typescript@5.9.3))(eslint@9.39.1)(jest@30.1.3(@types/node@25.2.3))(typescript@5.9.3): dependencies: - '@typescript-eslint/utils': 8.48.1(eslint@9.39.1)(typescript@5.9.3) + '@typescript-eslint/utils': 8.57.2(eslint@9.39.1)(typescript@5.9.3) eslint: 9.39.1 optionalDependencies: '@typescript-eslint/eslint-plugin': 8.43.0(@typescript-eslint/parser@8.43.0(eslint@9.39.1)(typescript@5.9.3))(eslint@9.39.1)(typescript@5.9.3) @@ -5243,6 +5310,8 @@ snapshots: eslint-visitor-keys@4.2.1: {} + eslint-visitor-keys@5.0.1: {} + eslint@9.39.1: dependencies: '@eslint-community/eslint-utils': 4.9.0(eslint@9.39.1) @@ -5355,7 +5424,8 @@ snapshots: fast-levenshtein@2.0.6: {} - fastestsmallesttextencoderdecoder@1.0.22: {} + fastestsmallesttextencoderdecoder@1.0.22: + optional: true fastq@1.19.1: dependencies: @@ -5478,7 +5548,7 @@ snapshots: fs.realpath: 1.0.0 inflight: 1.0.6 inherits: 2.0.4 - minimatch: 3.1.2 + minimatch: 3.1.5 once: 1.4.0 path-is-absolute: 1.0.1 @@ -5580,11 +5650,11 @@ snapshots: istanbul-lib-instrument@6.0.3: dependencies: - '@babel/core': 7.28.5 - '@babel/parser': 7.28.5 + '@babel/core': 7.29.0 + '@babel/parser': 7.29.2 '@istanbuljs/schema': 0.1.3 istanbul-lib-coverage: 3.2.2 - semver: 7.7.3 + semver: 7.7.4 transitivePeerDependencies: - supports-color @@ -5625,10 +5695,10 @@ snapshots: '@jest/expect': 30.1.2 '@jest/test-result': 30.1.3 '@jest/types': 30.0.5 - '@types/node': 25.2.3 + '@types/node': 25.5.0 chalk: 4.1.2 co: 4.6.0 - dedent: 1.7.0 + dedent: 1.7.2 is-generator-fn: 2.1.0 jest-each: 30.1.0 jest-matcher-utils: 30.1.2 @@ -5666,14 +5736,14 @@ snapshots: jest-config@30.1.3(@types/node@25.2.3): dependencies: - '@babel/core': 7.28.5 + '@babel/core': 7.29.0 '@jest/get-type': 30.1.0 '@jest/pattern': 30.0.1 '@jest/test-sequencer': 30.1.3 '@jest/types': 30.0.5 - babel-jest: 30.1.2(@babel/core@7.28.5) + babel-jest: 30.1.2(@babel/core@7.29.0) chalk: 4.1.2 - ci-info: 4.3.1 + ci-info: 4.4.0 deepmerge: 4.3.1 glob: 10.5.0 graceful-fs: 4.2.11 @@ -5696,6 +5766,38 @@ snapshots: - babel-plugin-macros - supports-color + jest-config@30.1.3(@types/node@25.5.0): + dependencies: + '@babel/core': 7.29.0 + '@jest/get-type': 30.1.0 + '@jest/pattern': 30.0.1 + '@jest/test-sequencer': 30.1.3 + '@jest/types': 30.0.5 + babel-jest: 30.1.2(@babel/core@7.29.0) + chalk: 4.1.2 + ci-info: 4.4.0 + deepmerge: 4.3.1 + glob: 10.5.0 + graceful-fs: 4.2.11 + jest-circus: 30.1.3 + jest-docblock: 30.0.1 + jest-environment-node: 30.1.2 + jest-regex-util: 30.0.1 + jest-resolve: 30.1.3 + jest-runner: 30.1.3 + jest-util: 30.0.5 + jest-validate: 30.1.0 + micromatch: 4.0.8 + parse-json: 5.2.0 + pretty-format: 30.0.5 + slash: 3.0.0 + strip-json-comments: 3.1.1 + optionalDependencies: + '@types/node': 25.5.0 + transitivePeerDependencies: + - babel-plugin-macros + - supports-color + jest-diff@30.1.2: dependencies: '@jest/diff-sequences': 30.0.1 @@ -5720,7 +5822,7 @@ snapshots: '@jest/environment': 30.1.2 '@jest/fake-timers': 30.1.2 '@jest/types': 30.0.5 - '@types/node': 25.2.3 + '@types/node': 25.5.0 jest-mock: 30.0.5 jest-util: 30.0.5 jest-validate: 30.1.0 @@ -5728,7 +5830,7 @@ snapshots: jest-haste-map@30.1.0: dependencies: '@jest/types': 30.0.5 - '@types/node': 25.2.3 + '@types/node': 25.5.0 anymatch: 3.1.3 fb-watchman: 2.0.2 graceful-fs: 4.2.11 @@ -5754,7 +5856,7 @@ snapshots: jest-message-util@30.1.0: dependencies: - '@babel/code-frame': 7.27.1 + '@babel/code-frame': 7.29.0 '@jest/types': 30.0.5 '@types/stack-utils': 2.0.3 chalk: 4.1.2 @@ -5767,7 +5869,7 @@ snapshots: jest-mock@30.0.5: dependencies: '@jest/types': 30.0.5 - '@types/node': 25.2.3 + '@types/node': 25.5.0 jest-util: 30.0.5 jest-pnp-resolver@1.2.3(jest-resolve@30.1.3): @@ -5801,7 +5903,7 @@ snapshots: '@jest/test-result': 30.1.3 '@jest/transform': 30.1.2 '@jest/types': 30.0.5 - '@types/node': 25.2.3 + '@types/node': 25.5.0 chalk: 4.1.2 emittery: 0.13.1 exit-x: 0.2.2 @@ -5830,9 +5932,9 @@ snapshots: '@jest/test-result': 30.1.3 '@jest/transform': 30.1.2 '@jest/types': 30.0.5 - '@types/node': 25.2.3 + '@types/node': 25.5.0 chalk: 4.1.2 - cjs-module-lexer: 2.1.1 + cjs-module-lexer: 2.2.0 collect-v8-coverage: 1.0.3 glob: 10.5.0 graceful-fs: 4.2.11 @@ -5850,17 +5952,17 @@ snapshots: jest-snapshot@30.1.2: dependencies: - '@babel/core': 7.28.5 - '@babel/generator': 7.28.5 - '@babel/plugin-syntax-jsx': 7.27.1(@babel/core@7.28.5) - '@babel/plugin-syntax-typescript': 7.27.1(@babel/core@7.28.5) - '@babel/types': 7.28.5 + '@babel/core': 7.29.0 + '@babel/generator': 7.29.1 + '@babel/plugin-syntax-jsx': 7.28.6(@babel/core@7.29.0) + '@babel/plugin-syntax-typescript': 7.28.6(@babel/core@7.29.0) + '@babel/types': 7.29.0 '@jest/expect-utils': 30.1.2 '@jest/get-type': 30.1.0 '@jest/snapshot-utils': 30.1.2 '@jest/transform': 30.1.2 '@jest/types': 30.0.5 - babel-preset-current-node-syntax: 1.2.0(@babel/core@7.28.5) + babel-preset-current-node-syntax: 1.2.0(@babel/core@7.29.0) chalk: 4.1.2 expect: 30.1.2 graceful-fs: 4.2.11 @@ -5869,19 +5971,19 @@ snapshots: jest-message-util: 30.1.0 jest-util: 30.0.5 pretty-format: 30.0.5 - semver: 7.7.3 - synckit: 0.11.11 + semver: 7.7.4 + synckit: 0.11.12 transitivePeerDependencies: - supports-color jest-util@30.0.5: dependencies: '@jest/types': 30.0.5 - '@types/node': 25.2.3 + '@types/node': 25.5.0 chalk: 4.1.2 - ci-info: 4.3.1 + ci-info: 4.4.0 graceful-fs: 4.2.11 - picomatch: 4.0.3 + picomatch: 4.0.4 jest-validate@30.1.0: dependencies: @@ -5896,7 +5998,7 @@ snapshots: dependencies: '@jest/test-result': 30.1.3 '@jest/types': 30.0.5 - '@types/node': 25.2.3 + '@types/node': 25.5.0 ansi-escapes: 4.3.2 chalk: 4.1.2 emittery: 0.13.1 @@ -5905,7 +6007,7 @@ snapshots: jest-worker@30.1.0: dependencies: - '@types/node': 25.2.3 + '@types/node': 25.5.0 '@ungap/structured-clone': 1.3.0 jest-util: 30.0.5 merge-stream: 2.0.0 @@ -6012,7 +6114,7 @@ snapshots: make-dir@4.0.0: dependencies: - semver: 7.7.3 + semver: 7.7.4 makeerror@1.0.12: dependencies: @@ -6035,14 +6137,26 @@ snapshots: dependencies: '@isaacs/brace-expansion': 5.0.0 + minimatch@10.2.4: + dependencies: + brace-expansion: 5.0.4 + minimatch@3.1.2: dependencies: brace-expansion: 1.1.12 + minimatch@3.1.5: + dependencies: + brace-expansion: 1.1.12 + minimatch@9.0.5: dependencies: brace-expansion: 2.0.2 + minimatch@9.0.9: + dependencies: + brace-expansion: 2.0.2 + minipass@7.1.2: {} mlly@1.8.0: @@ -6076,7 +6190,7 @@ snapshots: node-int64@0.4.0: {} - node-releases@2.0.27: {} + node-releases@2.0.36: {} normalize-path@3.0.0: {} @@ -6151,7 +6265,7 @@ snapshots: parse-json@5.2.0: dependencies: - '@babel/code-frame': 7.27.1 + '@babel/code-frame': 7.29.0 error-ex: 1.3.4 json-parse-even-better-errors: 2.3.1 lines-and-columns: 1.2.4 @@ -6180,8 +6294,12 @@ snapshots: picomatch@2.3.1: {} + picomatch@2.3.2: {} + picomatch@4.0.3: {} + picomatch@4.0.4: {} + pify@4.0.1: {} pirates@4.0.7: {} @@ -6328,6 +6446,8 @@ snapshots: semver@7.7.3: {} + semver@7.7.4: {} + set-function-length@1.2.2: dependencies: define-data-property: 1.1.4 @@ -6428,7 +6548,7 @@ snapshots: dependencies: has-flag: 4.0.0 - synckit@0.11.11: + synckit@0.11.12: dependencies: '@pkgr/core': 0.2.9 @@ -6438,7 +6558,7 @@ snapshots: dependencies: '@istanbuljs/schema': 0.1.3 glob: 7.2.3 - minimatch: 3.1.2 + minimatch: 3.1.5 thenify-all@1.6.0: dependencies: @@ -6469,7 +6589,7 @@ snapshots: tree-kill@1.2.2: {} - ts-api-utils@2.1.0(typescript@5.9.3): + ts-api-utils@2.5.0(typescript@5.9.3): dependencies: typescript: 5.9.3 @@ -6540,6 +6660,8 @@ snapshots: undici-types@7.16.0: {} + undici-types@7.18.2: {} + universalify@0.1.2: {} unrs-resolver@1.11.1: @@ -6566,9 +6688,9 @@ snapshots: '@unrs/resolver-binding-win32-ia32-msvc': 1.11.1 '@unrs/resolver-binding-win32-x64-msvc': 1.11.1 - update-browserslist-db@1.1.4(browserslist@4.28.0): + update-browserslist-db@1.2.3(browserslist@4.28.1): dependencies: - browserslist: 4.28.0 + browserslist: 4.28.1 escalade: 3.2.0 picocolors: 1.1.1 diff --git a/public/templates/accountsPage.njk b/public/templates/accountsPage.njk index dd0a82d..60e29c3 100644 --- a/public/templates/accountsPage.njk +++ b/public/templates/accountsPage.njk @@ -42,11 +42,11 @@ impl {{ account.name | pascalCase }} { {% endfor %} ) = ( {% for seed in constantSeeds %} - {{ seed.valueManifest.render }}.as_bytes(), + {{ seed.seedBytesExpr }}, {% endfor %} ); {% elif constantSeeds.length === 1 %} - pub const PREFIX: &'static [u8] = {{ constantSeeds[0].valueManifest.render }}.as_bytes(); + pub const PREFIX: &'static [u8] = {{ constantSeeds[0].seedBytesExpr }}; {% endif %} {% endif %} @@ -67,7 +67,7 @@ impl {{ account.name | pascalCase }} { {% if seed.kind === 'constantPdaSeedNode' and seed.value.kind === 'programIdValueNode' %} crate::{{ program.name | snakeCase | upper }}_ID.as_ref(), {% elif seed.kind === 'constantPdaSeedNode' %} - {{ seed.valueManifest.render }}.as_bytes(), + {{ seed.seedBytesExpr }}, {% elif seed.kind == 'variablePdaSeedNode' and seed.resolvedType.kind == 'publicKeyTypeNode' %} {{ seed.name | snakeCase }}.as_ref(), {% elif seed.kind == 'variablePdaSeedNode' and seed.resolvedType.kind == 'bytesTypeNode' %} @@ -99,7 +99,7 @@ impl {{ account.name | pascalCase }} { {% if seed.kind === 'constantPdaSeedNode' and seed.value.kind === 'programIdValueNode' %} crate::{{ program.name | snakeCase | upper }}_ID.as_ref(), {% elif seed.kind === 'constantPdaSeedNode' %} - {{ seed.valueManifest.render }}.as_bytes(), + {{ seed.seedBytesExpr }}, {% elif seed.kind == 'variablePdaSeedNode' and seed.resolvedType.kind == 'publicKeyTypeNode' %} {{ seed.name | snakeCase }}.as_ref(), {% elif seed.kind == 'variablePdaSeedNode' and seed.resolvedType.kind == 'bytesTypeNode' %} diff --git a/public/templates/instructionsPageBuilder.njk b/public/templates/instructionsPageBuilder.njk index 44b3682..ac73d21 100644 --- a/public/templates/instructionsPageBuilder.njk +++ b/public/templates/instructionsPageBuilder.njk @@ -1,3 +1,9 @@ +{% set pdaResolved = [] %} +{% for account in resolvedAccounts %} + {% if account.pdaDefault %} + {% set _ = pdaResolved.push(account.name) %} + {% endif %} +{% endfor %} /// Instruction builder for `{{ instruction.name | pascalCase }}`. /// /// ### Accounts: @@ -10,11 +16,12 @@ {% if account.isSigner %} {% set modifiers = modifiers + ', signer' if modifiers.length > 0 else 'signer' %} {% endif %} - {% if account.isOptional or account.defaultValue.kind === 'publicKeyValueNode' %} + {% if account.isOptional or account.defaultValue.kind === 'publicKeyValueNode' or (account.defaultValue.kind === 'pdaValueNode' and account.name in pdaResolved) %} {% set modifiers = modifiers + ', optional' if modifiers.length > 0 else 'optional' %} {% endif %} {{ '/// ' + loop.index0 + '. `[' + modifiers + ']` ' + account.name | snakeCase }} {{- " (default to `" + account.defaultValue.publicKey + "`)" if account.defaultValue.kind === 'publicKeyValueNode' }} + {{- " (default to PDA derived from '" + account.defaultValue.pda.name + "')" if account.defaultValue.kind === 'pdaValueNode' and account.name in pdaResolved }} {% endfor %} #[derive(Clone, Debug, Default)] pub struct {{ instruction.name | pascalCase }}Builder { @@ -40,8 +47,10 @@ impl {{ instruction.name | pascalCase }}Builder { {% for account in instruction.accounts %} {% if account.isOptional %} {{ '/// `[optional account]`\n' -}} - {% else %} - {{ "/// `[optional account, default to '" + account.defaultValue.publicKey + "']`\n" if account.defaultValue.kind === 'publicKeyValueNode' -}} + {% elif account.defaultValue.kind === 'publicKeyValueNode' %} + {{ "/// `[optional account, default to '" + account.defaultValue.publicKey + "']`\n" -}} + {% elif account.defaultValue.kind === 'pdaValueNode' and account.name in pdaResolved %} + {{ "/// `[optional account, default to PDA derived from '" + account.defaultValue.pda.name + "']`\n" -}} {% endif %} {{- macros.docblock(account.docs) -}} #[inline(always)] @@ -92,14 +101,52 @@ impl {{ instruction.name | pascalCase }}Builder { } #[allow(clippy::clone_on_copy)] pub fn instruction(&self) -> solana_instruction::Instruction { + {% for account in resolvedAccounts %} + {% if account.pdaDefault %} + {% if account.pdaDefault.isLinked and not account.pdaDefault.hasVariableSeeds %} + {% if account.isSigner === 'either' %} + let {{ account.name | snakeCase }} = self.{{ account.name | snakeCase }}.map(|(k, _)| k).unwrap_or( + {% else %} + let {{ account.name | snakeCase }} = self.{{ account.name | snakeCase }}.unwrap_or( + {% endif %} + crate::pdas::{{ account.pdaDefault.linkedPdaName | snakeCase | upper }}_ADDRESS + ); + {% else %} + {% if account.isSigner === 'either' %} + let {{ account.name | snakeCase }} = self.{{ account.name | snakeCase }}.map(|(k, _)| k).unwrap_or_else(|| { + {% else %} + let {{ account.name | snakeCase }} = self.{{ account.name | snakeCase }}.unwrap_or_else(|| { + {% endif %} + {% if account.pdaDefault.isLinked %} + crate::pdas::find_{{ account.pdaDefault.linkedPdaName | snakeCase }}_pda( + {% for seed in account.pdaDefault.renderedSeeds %} + {{ seed.render }}, + {% endfor %} + ).0 + {% else %} + solana_address::Address::find_program_address( + &[ + {% for seed in account.pdaDefault.renderedSeeds %} + {{ seed.render }}, + {% endfor %} + ], + &{{ account.pdaDefault.programAddressExpr }}, + ).0 + {% endif %} + }); + {% endif %} + {% endif %} + {% endfor %} let accounts = {{ instruction.name | pascalCase }} { {% for account in instruction.accounts %} {% if account.isOptional %} {{ account.name | snakeCase }}: self.{{ account.name | snakeCase }}, {% elif account.defaultValue.kind === 'programId' %} - {{ account.name | snakeCase }}: self.{{ account.name | snakeCase }}, {# Program ID set on the instruction creation. #} + {{ account.name | snakeCase }}: self.{{ account.name | snakeCase }}, {% elif account.defaultValue.kind === 'publicKeyValueNode' %} {{ account.name | snakeCase }}: self.{{ account.name | snakeCase }}.unwrap_or(solana_address::address!("{{ account.defaultValue.publicKey }}")), + {% elif account.name in pdaResolved %} + {{ account.name | snakeCase }}, {% else %} {{ account.name | snakeCase }}: self.{{ account.name | snakeCase }}.expect("{{ account.name | snakeCase }} is not set"), {% endif %} diff --git a/public/templates/pdasMod.njk b/public/templates/pdasMod.njk index 1bfe479..51f08c6 100644 --- a/public/templates/pdasMod.njk +++ b/public/templates/pdasMod.njk @@ -1,7 +1,13 @@ +{% extends "layout.njk" %} + +{% block main %} + {% for pda in pdasToExport %} pub mod {{ pda.name | snakeCase }}; {% endfor %} {% for pda in pdasToExport %} pub use self::{{ pda.name | snakeCase }}::*; -{% endfor %} \ No newline at end of file +{% endfor %} + +{% endblock %} diff --git a/public/templates/pdasPage.njk b/public/templates/pdasPage.njk index 5295262..e385634 100644 --- a/public/templates/pdasPage.njk +++ b/public/templates/pdasPage.njk @@ -13,10 +13,15 @@ use crate::{{ program.name | snakeCase | upper }}_ID; {% set constantIndex = 0 %} {% for seed in seeds %} {% if seed.kind === 'constantPdaSeedNode' and seed.value.kind !== 'programIdValueNode' %} -pub const {{ pda.name | snakeCase | upper }}_SEED{% if constantSeeds.length > 1 %}_{{ constantIndex }}{% endif %}: &'static [u8] = b{{ seed.valueManifest.render }}; +pub const {{ pda.name | snakeCase | upper }}_SEED{% if constantSeeds.length > 1 %}_{{ constantIndex }}{% endif %}: &'static [u8] = {{ seed.seedBytesExpr }}; {% set constantIndex = constantIndex + 1 %} {% endif %} {% endfor %} +{% if precomputedAddress %} + +pub const {{ pda.name | snakeCase | upper }}_ADDRESS: solana_address::Address = + solana_address::address!("{{ precomputedAddress }}"); +{% endif %} {{- macros.docblock(pda.docs) -}} pub fn create_{{ pda.name | snakeCase }}_pda( diff --git a/src/getRenderMapVisitor.ts b/src/getRenderMapVisitor.ts index 73ba891..2d540c9 100644 --- a/src/getRenderMapVisitor.ts +++ b/src/getRenderMapVisitor.ts @@ -1,14 +1,19 @@ import { logWarn } from '@codama/errors'; import { + constantValueNode, getAllAccounts, getAllDefinedTypes, getAllInstructionsWithSubs, getAllPdas, getAllPrograms, + type InstructionAccountNode, + type InstructionArgumentNode, InstructionNode, isNode, isNodeFilter, pascalCase, + type PdaNode, + type ProgramNode, resolveNestedTypeNode, snakeCase, structTypeNodeFromInstructionArgumentNodes, @@ -32,9 +37,11 @@ import { ImportMap } from './ImportMap'; import { renderValueNode } from './renderValueNodeVisitor'; import { CargoDependencies, + computePdaAddress, Fragment, getDiscriminatorConstants, getImportFromFactory, + type GetImportFromFunction, getTraitsFromNodeFactory, LinkOverrides, render, @@ -105,10 +112,22 @@ export function getRenderMapVisitor(options: GetRenderMapOptions = {}) { return seed; } const seedManifest = visit(seed.type, typeManifestVisitor); - const valueManifest = renderValueNode(seed.value, getImportFrom, true); - seedsImports.mergeWith(valueManifest.imports); const resolvedType = resolveNestedTypeNode(seed.type); - return { ...seed, resolvedType, typeManifest: seedManifest, valueManifest }; + let seedBytesExpr: string; + if (isNode(seed.value, 'stringValueNode')) { + const m = renderValueNode(seed.value, getImportFrom, true); + seedsImports.mergeWith(m.imports); + seedBytesExpr = `b${m.render}`; + } else if (isNode(seed.value, 'bytesValueNode')) { + const m = renderValueNode(seed.value, getImportFrom, true); + seedsImports.mergeWith(m.imports); + seedBytesExpr = `&${m.render}`; + } else { + const m = renderValueNode(constantValueNode(seed.type, seed.value), getImportFrom, true); + seedsImports.mergeWith(m.imports); + seedBytesExpr = `&${m.render}`; + } + return { ...seed, resolvedType, seedBytesExpr, typeManifest: seedManifest }; }); const hasVariableSeeds = pdaSeeds.filter(isNodeFilter('variablePdaSeedNode')).length > 0; const constantSeeds = seeds @@ -249,8 +268,22 @@ export function getRenderMapVisitor(options: GetRenderMapOptions = {}) { .mergeWith(discriminatorConstants.imports) .remove(`generatedInstructions::${pascalCase(node.name)}`); + // Resolve PDA defaults and topologically sort accounts by dependency. + const resolvedAccounts = resolveInstructionPdaDefaults({ + accounts: node.accounts, + accountsAndArgsConflicts, + getImportFrom, + imports, + instructionArguments: node.arguments, + instructionName: node.name, + linkables, + program, + stack, + }); + return createRenderMap(`instructions/${snakeCase(node.name)}.rs`, { content: render('instructionsPage.njk', { + accountsAndArgsConflicts, dataTraits: dataTraits.render, discriminatorConstants: discriminatorConstants.render, hasArgs, @@ -259,6 +292,7 @@ export function getRenderMapVisitor(options: GetRenderMapOptions = {}) { instruction: node, instructionArgs, program, + resolvedAccounts, typeManifest, }), imports, @@ -285,10 +319,22 @@ export function getRenderMapVisitor(options: GetRenderMapOptions = {}) { return seed; } const seedManifest = visit(seed.type, typeManifestVisitor); - const valueManifest = renderValueNode(seed.value, getImportFrom, true); - imports.mergeWith(valueManifest.imports); const resolvedType = resolveNestedTypeNode(seed.type); - return { ...seed, resolvedType, typeManifest: seedManifest, valueManifest }; + let seedBytesExpr: string; + if (isNode(seed.value, 'stringValueNode')) { + const m = renderValueNode(seed.value, getImportFrom, true); + imports.mergeWith(m.imports); + seedBytesExpr = `b${m.render}`; + } else if (isNode(seed.value, 'bytesValueNode')) { + const m = renderValueNode(seed.value, getImportFrom, true); + imports.mergeWith(m.imports); + seedBytesExpr = `&${m.render}`; + } else { + const m = renderValueNode(constantValueNode(seed.type, seed.value), getImportFrom, true); + imports.mergeWith(m.imports); + seedBytesExpr = `&${m.render}`; + } + return { ...seed, resolvedType, seedBytesExpr, typeManifest: seedManifest }; }); const hasVariableSeeds = node.seeds.filter(isNodeFilter('variablePdaSeedNode')).length > 0; @@ -298,12 +344,25 @@ export function getRenderMapVisitor(options: GetRenderMapOptions = {}) { const programAddress = node.programId ?? program?.publicKey; + let precomputedAddress: string | undefined; + if (!hasVariableSeeds && programAddress) { + precomputedAddress = computePdaAddress(node.seeds, programAddress) ?? undefined; + } + + // Template uses fully-qualified paths for return types and static methods, + // but variable seed types use the short form from the type manifest. + // Only remove the import when there are no variable seeds. + if (!hasVariableSeeds) { + imports.remove('solana_address::Address'); + } + return createRenderMap(`pdas/${snakeCase(node.name)}.rs`, { content: render('pdasPage.njk', { constantSeeds, hasVariableSeeds, imports: imports.toString(dependencyMap), pda: node, + precomputedAddress, program, programAddress, seeds, @@ -411,3 +470,343 @@ function getConflictsForInstructionAccountsAndArgs(instruction: InstructionNode) const duplicates = allNames.filter((e, i, a) => a.indexOf(e) !== i); return [...new Set(duplicates)]; } + +type RenderedSeed = { + kind: 'accountRef' | 'argumentRef' | 'constant' | 'programId' | 'value'; + rawName?: string; + render: string; +}; + +type ResolvedPdaDefault = { + accountDeps: string[]; + hasVariableSeeds: boolean; + isLinked: boolean; + linkedPdaName?: string; + programAddressExpr?: string; + renderedSeeds: RenderedSeed[]; +}; + +type ResolvedAccount = InstructionAccountNode & { + pdaDefault: ResolvedPdaDefault | null; +}; + +function resolveInstructionPdaDefaults(ctx: { + accounts: readonly InstructionAccountNode[]; + accountsAndArgsConflicts: string[]; + getImportFrom: GetImportFromFunction; + imports: ImportMap; + instructionArguments: readonly InstructionArgumentNode[]; + instructionName: string; + linkables: LinkableDictionary; + program: ProgramNode; + stack: NodeStack; +}): ResolvedAccount[] { + const { + accounts, + accountsAndArgsConflicts, + getImportFrom, + imports, + instructionArguments, + instructionName, + linkables, + program, + stack, + } = ctx; + + // Cast to string to avoid branded CamelCaseString type. + const pdaDefaultedNames = new Set( + accounts.filter(a => a.defaultValue?.kind === 'pdaValueNode').map(a => a.name as string), + ); + + const resolvedPdas: Record = {}; + + for (const account of accounts) { + if (!account.defaultValue || !isNode(account.defaultValue, 'pdaValueNode')) { + continue; + } + const defaultValue = account.defaultValue; + + let pdaNode: PdaNode | undefined; + const isLinked = isNode(defaultValue.pda, 'pdaLinkNode'); + const linkedPdaName = isLinked ? (defaultValue.pda as { name: string }).name : undefined; + + if (isLinked) { + pdaNode = linkables.get([...stack.getPath(), defaultValue.pda]) ?? undefined; + } else if (isNode(defaultValue.pda, 'pdaNode')) { + pdaNode = defaultValue.pda; + } + + // Linked PDAs can work without pdaNode (iterate defaultValue.seeds directly). + if (!isLinked && !pdaNode) { + logWarn( + `[Rust] Could not resolve PDA node for account [${account.name}] ` + + `in instruction [${instructionName}]. The account will be treated as required.`, + ); + continue; + } + + const programAddressExpr = pdaNode?.programId + ? `solana_address::address!("${pdaNode.programId}")` + : `crate::${snakeCase(program.name).toUpperCase()}_ID`; + + // Upstream account defaults for seed resolution. + const accountDefaults: Record = {}; + const eitherSignerAccounts = new Set(); + for (const seedBinding of defaultValue.seeds) { + if (isNode(seedBinding.value, 'accountValueNode')) { + const refName = seedBinding.value.name; + const refAccount = accounts.find(a => a.name === refName); + if (refAccount?.defaultValue && isNode(refAccount.defaultValue, 'publicKeyValueNode')) { + accountDefaults[refName] = `solana_address::address!("${refAccount.defaultValue.publicKey}")`; + } else if (refAccount?.defaultValue && isNode(refAccount.defaultValue, 'programIdValueNode')) { + accountDefaults[refName] = `crate::${snakeCase(program.name).toUpperCase()}_ID`; + } + if (refAccount?.isSigner === 'either') { + eitherSignerAccounts.add(refName); + } + } + } + + const renderedSeeds: RenderedSeed[] = []; + const accountDeps: string[] = []; + let seedsComplete = true; + + // Two rendering paths because extractPdasVisitor only extracts same-program + // PDAs — cross-program derivations (e.g. ATAs via the associated-token-program) + // stay inline as pdaNode since they can't live in this program's pdas module. + // + // Linked (pdaLinkNode): call the standalone find_*_pda() with typed args. + // Inline (pdaNode): emit find_program_address() with raw byte-slice seeds. + if (isLinked) { + for (const seedBinding of defaultValue.seeds) { + const seedValue = seedBinding.value; + + if (isNode(seedValue, 'accountValueNode')) { + const refName = snakeCase(seedValue.name); + const isEither = eitherSignerAccounts.has(seedValue.name); + const eitherExtract = isEither ? '.map(|(k, _)| k)' : ''; + + if (pdaDefaultedNames.has(seedValue.name)) { + accountDeps.push(seedValue.name); + renderedSeeds.push({ kind: 'accountRef', rawName: refName, render: `&${refName}` }); + } else { + const defaultExpr = accountDefaults[seedValue.name]; + let render: string; + if (defaultExpr) { + render = `&self.${refName}${eitherExtract}.unwrap_or(${defaultExpr})`; + } else { + render = `&self.${refName}${eitherExtract}.expect("${refName} is needed for ${snakeCase(account.name)} PDA")`; + } + renderedSeeds.push({ kind: 'accountRef', rawName: refName, render }); + } + } else if (isNode(seedValue, 'argumentValueNode')) { + const argFieldName = accountsAndArgsConflicts.includes(seedValue.name) + ? `${seedValue.name}_arg` + : seedValue.name; + const fieldName = snakeCase(argFieldName); + + const arg = instructionArguments.find(a => a.name === seedValue.name); + let argDefault: { isOmitted: boolean; value: string } | null = null; + if (arg?.defaultValue && isNode(arg.defaultValue, VALUE_NODES)) { + const { render: value } = renderValueNode(arg.defaultValue, getImportFrom); + argDefault = { isOmitted: arg.defaultValueStrategy === 'omitted', value }; + } + + // Pubkey seeds need by-ref for the typed find_*_pda() signature. + let isByRef = false; + if (pdaNode) { + const pdaSeed = pdaNode.seeds.find( + s => isNode(s, 'variablePdaSeedNode') && s.name === seedBinding.name, + ); + if (pdaSeed && isNode(pdaSeed, 'variablePdaSeedNode')) { + isByRef = resolveNestedTypeNode(pdaSeed.type).kind === 'publicKeyTypeNode'; + } + } + + if (argDefault && argDefault.isOmitted) { + renderedSeeds.push({ + kind: 'argumentRef', + render: `${isByRef ? '&' : ''}${argDefault.value}`, + }); + } else { + renderedSeeds.push({ + kind: 'argumentRef', + render: `${isByRef ? '&' : ''}self.${fieldName}.clone().expect("${fieldName} is needed for ${snakeCase(account.name)} PDA")`, + }); + } + } + } + } else { + for (const seed of pdaNode!.seeds) { + if (isNode(seed, 'constantPdaSeedNode')) { + if (isNode(seed.value, 'programIdValueNode')) { + renderedSeeds.push({ + kind: 'programId', + render: `crate::${snakeCase(program.name).toUpperCase()}_ID.as_ref()`, + }); + } else { + const valueManifest = renderValueNode(seed.value, getImportFrom); + imports.mergeWith(valueManifest.imports); + renderedSeeds.push({ kind: 'constant', render: `&${valueManifest.render}` }); + } + continue; + } + + if (!isNode(seed, 'variablePdaSeedNode')) continue; + + const binding = defaultValue.seeds.find(s => s.name === seed.name); + if (!binding) { + logWarn( + `[Rust] Missing seed value for variable seed [${seed.name}] ` + + `in PDA default for account [${account.name}] ` + + `of instruction [${instructionName}]. Skipping PDA resolution.`, + ); + seedsComplete = false; + break; + } + + const resolvedType = resolveNestedTypeNode(seed.type); + const seedValue = binding.value; + + if (isNode(seedValue, 'accountValueNode')) { + const refName = snakeCase(seedValue.name); + const isEither = eitherSignerAccounts.has(seedValue.name); + const eitherExtract = isEither ? '.map(|(k, _)| k)' : ''; + const defaultExpr = accountDefaults[seedValue.name]; + + if (pdaDefaultedNames.has(seedValue.name)) { + accountDeps.push(seedValue.name); + } + + let valueExpr: string; + if (pdaDefaultedNames.has(seedValue.name)) { + valueExpr = refName; + } else if (defaultExpr) { + valueExpr = `self.${refName}${eitherExtract}.unwrap_or(${defaultExpr})`; + } else { + valueExpr = `self.${refName}${eitherExtract}.expect("${refName} is needed for ${snakeCase(account.name)} PDA")`; + } + + if (resolvedType.kind === 'publicKeyTypeNode') { + renderedSeeds.push({ kind: 'accountRef', rawName: refName, render: `${valueExpr}.as_ref()` }); + } else if (resolvedType.kind === 'bytesTypeNode') { + renderedSeeds.push({ kind: 'accountRef', rawName: refName, render: `&${valueExpr}` }); + } else { + renderedSeeds.push({ + kind: 'accountRef', + rawName: refName, + render: `${valueExpr}.to_string().as_ref()`, + }); + } + } else if (isNode(seedValue, 'argumentValueNode')) { + const argFieldName = accountsAndArgsConflicts.includes(seedValue.name) + ? `${seedValue.name}_arg` + : seedValue.name; + const fieldName = snakeCase(argFieldName); + + const arg = instructionArguments.find(a => a.name === seedValue.name); + let argDefault: { isOmitted: boolean; value: string } | null = null; + if (arg?.defaultValue && isNode(arg.defaultValue, VALUE_NODES)) { + const { render: value } = renderValueNode(arg.defaultValue, getImportFrom); + argDefault = { isOmitted: arg.defaultValueStrategy === 'omitted', value }; + } + + if (argDefault && argDefault.isOmitted) { + if (resolvedType.kind === 'publicKeyTypeNode') { + renderedSeeds.push({ kind: 'argumentRef', render: `${argDefault.value}.as_ref()` }); + } else if (resolvedType.kind === 'bytesTypeNode') { + renderedSeeds.push({ kind: 'argumentRef', render: `&${argDefault.value}` }); + } else { + renderedSeeds.push({ + kind: 'argumentRef', + render: `${argDefault.value}.to_string().as_ref()`, + }); + } + } else { + const valueExpr = `self.${fieldName}.clone().expect("${fieldName} is needed for ${snakeCase(account.name)} PDA")`; + if (resolvedType.kind === 'publicKeyTypeNode') { + renderedSeeds.push({ kind: 'argumentRef', render: `${valueExpr}.as_ref()` }); + } else if (resolvedType.kind === 'bytesTypeNode') { + renderedSeeds.push({ kind: 'argumentRef', render: `&${valueExpr}` }); + } else { + renderedSeeds.push({ + kind: 'argumentRef', + render: `${valueExpr}.to_string().as_ref()`, + }); + } + } + } else { + const valueManifest = renderValueNode(seedValue, getImportFrom, true); + imports.mergeWith(valueManifest.imports); + if (resolvedType.kind === 'publicKeyTypeNode') { + renderedSeeds.push({ kind: 'value', render: `${valueManifest.render}.as_ref()` }); + } else { + renderedSeeds.push({ kind: 'value', render: `${valueManifest.render}.as_bytes()` }); + } + } + } + } + + if (!seedsComplete) continue; + + const pdaHasVariableSeeds = pdaNode ? pdaNode.seeds.some(s => isNode(s, 'variablePdaSeedNode')) : true; + + resolvedPdas[account.name] = { + accountDeps, + hasVariableSeeds: pdaHasVariableSeeds, + isLinked, + linkedPdaName, + programAddressExpr, + renderedSeeds, + }; + } + + // DFS topological sort with cycle detection and propagation. + const accountDeps = new Map>(); + for (const account of accounts) { + const name = account.name; + accountDeps.set(name, new Set()); + const pdaInfo = resolvedPdas[name]; + if (pdaInfo) { + for (const dep of pdaInfo.accountDeps) { + accountDeps.get(name)!.add(dep); + } + } + } + + const sortedNames: string[] = []; + const visited = new Set(); + const visiting = new Set(); + + const topoVisit = (name: string): boolean => { + if (visited.has(name)) return resolvedPdas[name] !== undefined || !pdaDefaultedNames.has(name); + if (visiting.has(name)) { + logWarn( + `[Rust] Circular PDA dependency detected for account [${name}] ` + + `in instruction [${instructionName}]. Falling back to required account.`, + ); + delete resolvedPdas[name]; + return false; + } + visiting.add(name); + for (const dep of accountDeps.get(name) ?? []) { + if (accountDeps.has(dep) && !topoVisit(dep)) { + // Dependency lost its PDA resolution — remove ours too. + delete resolvedPdas[name]; + } + } + visiting.delete(name); + visited.add(name); + sortedNames.push(name); + return resolvedPdas[name] !== undefined || !pdaDefaultedNames.has(name); + }; + + for (const account of accounts) { + topoVisit(account.name); + } + + return sortedNames.map(name => { + const account = accounts.find(a => a.name === name)!; + return { ...account, pdaDefault: resolvedPdas[name] ?? null }; + }); +} diff --git a/src/utils/computePda.ts b/src/utils/computePda.ts new file mode 100644 index 0000000..345dfdb --- /dev/null +++ b/src/utils/computePda.ts @@ -0,0 +1,159 @@ +import { createHash } from 'node:crypto'; + +import { type ConstantPdaSeedNode, isNode, type PdaSeedNode, resolveNestedTypeNode } from '@codama/nodes'; +import { ed25519 } from '@noble/curves/ed25519.js'; +import { getBase58Decoder, getBase58Encoder } from '@solana/codecs-strings'; + +import { getBytesFromBytesValueNode } from './codecs'; + +function isOnCurve(bytes: Uint8Array): boolean { + return ed25519.utils.isValidPublicKey(bytes); +} + +/** + * Mirrors Solana's `Pubkey::find_program_address`. + * Returns the base58 address and bump, or `null` if no valid bump exists. + */ +export function findProgramAddress( + seeds: Uint8Array[], + programId: Uint8Array, +): { address: string; bump: number } | null { + for (let bump = 255; bump >= 0; bump--) { + const hash = createHash('sha256'); + for (const seed of seeds) { + hash.update(seed); + } + hash.update(Uint8Array.from([bump])); + hash.update(programId); + hash.update(Buffer.from('ProgramDerivedAddress')); + const candidate = hash.digest(); + + if (!isOnCurve(candidate)) { + return { + address: getBase58Decoder().decode(candidate), + bump, + }; + } + } + return null; +} + +function serializeNumber(value: number, format: string, endian: 'be' | 'le'): Uint8Array | null { + const isLE = endian === 'le'; + switch (format) { + case 'u8': + return Uint8Array.from([value & 0xff]); + case 'i8': { + const buf = new ArrayBuffer(1); + new DataView(buf).setInt8(0, value); + return new Uint8Array(buf); + } + case 'u16': { + const buf = new ArrayBuffer(2); + new DataView(buf).setUint16(0, value, isLE); + return new Uint8Array(buf); + } + case 'i16': { + const buf = new ArrayBuffer(2); + new DataView(buf).setInt16(0, value, isLE); + return new Uint8Array(buf); + } + case 'u32': { + const buf = new ArrayBuffer(4); + new DataView(buf).setUint32(0, value, isLE); + return new Uint8Array(buf); + } + case 'i32': { + const buf = new ArrayBuffer(4); + new DataView(buf).setInt32(0, value, isLE); + return new Uint8Array(buf); + } + case 'f32': { + const buf = new ArrayBuffer(4); + new DataView(buf).setFloat32(0, value, isLE); + return new Uint8Array(buf); + } + case 'f64': { + const buf = new ArrayBuffer(8); + new DataView(buf).setFloat64(0, value, isLE); + return new Uint8Array(buf); + } + case 'u64': + case 'i64': { + const buf = new ArrayBuffer(8); + const view = new DataView(buf); + if (format === 'u64') view.setBigUint64(0, BigInt(value), isLE); + else view.setBigInt64(0, BigInt(value), isLE); + return new Uint8Array(buf); + } + case 'u128': + case 'i128': { + const bytes = new Uint8Array(16); + const view = new DataView(bytes.buffer); + const big = BigInt(value); + const mask = (1n << 64n) - 1n; + const lo = big & mask; + const hi = (big >> 64n) & mask; + if (isLE) { + view.setBigUint64(0, lo, true); + view.setBigUint64(8, hi, true); + } else { + view.setBigUint64(0, hi, false); + view.setBigUint64(8, lo, false); + } + return bytes; + } + default: + return null; + } +} + +function extractConstantSeedBytes(seed: ConstantPdaSeedNode, programAddress: string): Uint8Array | null { + const { value } = seed; + + if (isNode(value, 'programIdValueNode')) { + return getBase58Encoder().encode(programAddress) as Uint8Array; + } + if (isNode(value, 'stringValueNode')) { + return new TextEncoder().encode(value.string); + } + if (isNode(value, 'bytesValueNode')) { + return getBytesFromBytesValueNode(value); + } + if (isNode(value, 'numberValueNode')) { + const resolvedType = resolveNestedTypeNode(seed.type); + if (isNode(resolvedType, 'numberTypeNode')) { + return serializeNumber(value.number, resolvedType.format, resolvedType.endian); + } + return null; + } + if (isNode(value, 'publicKeyValueNode')) { + return getBase58Encoder().encode(value.publicKey) as Uint8Array; + } + + return null; +} + +/** + * Computes a PDA address at codegen time for PDAs with only constant seeds. + * Returns the base58 address string, or `null` if computation is not possible. + */ +export function computePdaAddress(seeds: readonly PdaSeedNode[], programAddress: string): string | null { + try { + const seedBytes: Uint8Array[] = []; + for (const seed of seeds) { + if (!isNode(seed, 'constantPdaSeedNode')) { + return null; + } + const bytes = extractConstantSeedBytes(seed, programAddress); + if (!bytes) return null; + seedBytes.push(bytes); + } + + const programIdBytes = getBase58Encoder().encode(programAddress) as Uint8Array; + const result = findProgramAddress(seedBytes, programIdBytes); + return result?.address ?? null; + } catch { + return null; + } +} diff --git a/src/utils/index.ts b/src/utils/index.ts index 6e73eb3..48569a6 100644 --- a/src/utils/index.ts +++ b/src/utils/index.ts @@ -1,5 +1,6 @@ export * from './cargoToml'; export * from './codecs'; +export * from './computePda'; export * from './discriminatorConstant'; export * from './fragment'; export * from './linkOverrides'; diff --git a/test/accountsPage.test.ts b/test/accountsPage.test.ts index 3dc7232..f10f9bc 100644 --- a/test/accountsPage.test.ts +++ b/test/accountsPage.test.ts @@ -103,7 +103,7 @@ test('it renders constant PDA seeds as prefix consts', () => { '/// 0. `TestAccount::PREFIX.0`', '/// 1. my_account (`Address`)', '/// 2. `TestAccount::PREFIX.1`', - /pub const PREFIX: \(\s*&'static \[u8\],\s*&'static \[u8\],\s*\) = \(\s*"myPrefix"\.as_bytes\(\),\s*42\.as_bytes\(\),\s*\)/, + /pub const PREFIX: \(\s*&'static \[u8\],\s*&'static \[u8\],\s*\) = \(\s*b"myPrefix",\s*&42u64\.to_le_bytes\(\),\s*\)/, ]); }); diff --git a/test/instructionsPage.test.ts b/test/instructionsPage.test.ts index 8d1ad3a..2ca8013 100644 --- a/test/instructionsPage.test.ts +++ b/test/instructionsPage.test.ts @@ -1,10 +1,32 @@ -import { instructionArgumentNode, instructionNode, programNode, stringTypeNode } from '@codama/nodes'; +import { + accountValueNode, + argumentValueNode, + bytesTypeNode, + bytesValueNode, + constantPdaSeedNode, + constantPdaSeedNodeFromString, + instructionAccountNode, + instructionArgumentNode, + instructionNode, + numberTypeNode, + numberValueNode, + pdaLinkNode, + pdaNode, + pdaSeedValueNode, + pdaValueNode, + programIdValueNode, + programNode, + publicKeyTypeNode, + publicKeyValueNode, + stringTypeNode, + variablePdaSeedNode, +} from '@codama/nodes'; import { getFromRenderMap } from '@codama/renderers-core'; import { visit } from '@codama/visitors-core'; -import { test } from 'vitest'; +import { expect, test } from 'vitest'; import { getRenderMapVisitor } from '../src'; -import { codeContains } from './_setup'; +import { codeContains, codeDoesNotContains } from './_setup'; test('it renders a public instruction data struct', () => { // Given the following program with 1 instruction. @@ -52,6 +74,723 @@ test('it renders an instruction with a remainder str', () => { ]); }); +test('it auto-derives PDA accounts from pdaLinkNode defaults', () => { + // Given an instruction with a PDA-defaulted account. + const node = programNode({ + instructions: [ + instructionNode({ + accounts: [ + instructionAccountNode({ isOptional: false, isSigner: false, isWritable: false, name: 'realm' }), + instructionAccountNode({ isOptional: false, isSigner: false, isWritable: false, name: 'mint' }), + instructionAccountNode({ isOptional: false, isSigner: false, isWritable: false, name: 'owner' }), + instructionAccountNode({ + defaultValue: pdaValueNode(pdaLinkNode('record'), [ + pdaSeedValueNode('realm', accountValueNode('realm')), + pdaSeedValueNode('mint', accountValueNode('mint')), + pdaSeedValueNode('owner', accountValueNode('owner')), + ]), + isOptional: false, + isSigner: false, + isWritable: true, + name: 'record', + }), + ], + name: 'createRecord', + }), + ], + name: 'testProgram', + publicKey: '11111111111111111111111111111111', + }); + + // When we render it. + const renderMap = visit(node, getRenderMapVisitor()); + const content = getFromRenderMap(renderMap, 'instructions/create_record.rs').content; + + // Then we expect the PDA to be auto-derived. + codeContains(content, [ + `unwrap_or_else(|| {`, + `crate::pdas::find_record_pda(`, + `&self.realm.expect("realm is needed for record PDA")`, + `&self.mint.expect("mint is needed for record PDA")`, + `&self.owner.expect("owner is needed for record PDA")`, + `.0`, + `default to PDA derived from 'record'`, + ]); +}); + +test('it passes argument seeds by value for non-Pubkey types', () => { + // Given an instruction with a PDA that has a string argument seed. + const node = programNode({ + instructions: [ + instructionNode({ + accounts: [ + instructionAccountNode({ isOptional: false, isSigner: true, isWritable: false, name: 'owner' }), + instructionAccountNode({ + defaultValue: pdaValueNode(pdaLinkNode('record'), [ + pdaSeedValueNode('owner', accountValueNode('owner')), + pdaSeedValueNode('label', argumentValueNode('label')), + ]), + isOptional: false, + isSigner: false, + isWritable: true, + name: 'record', + }), + ], + arguments: [instructionArgumentNode({ name: 'label', type: stringTypeNode('utf8') })], + name: 'createRecord', + }), + ], + name: 'testProgram', + pdas: [ + pdaNode({ + name: 'record', + seeds: [ + variablePdaSeedNode('owner', publicKeyTypeNode()), + variablePdaSeedNode('label', stringTypeNode('utf8')), + ], + }), + ], + publicKey: '11111111111111111111111111111111', + }); + + // When we render it. + const renderMap = visit(node, getRenderMapVisitor()); + const content = getFromRenderMap(renderMap, 'instructions/create_record.rs').content; + + // Then we expect by-ref for the account seed and by-value for the argument seed. + codeContains(content, [ + `crate::pdas::find_record_pda(`, + `&self.owner.expect("owner is needed for record PDA")`, + `self.label.clone().expect("label is needed for record PDA")`, + ]); +}); + +test('it resolves upstream account defaults as PDA seeds', () => { + // Given an instruction where a PDA seed references an account with a publicKeyValueNode default. + const node = programNode({ + instructions: [ + instructionNode({ + accounts: [ + instructionAccountNode({ isOptional: false, isSigner: true, isWritable: false, name: 'owner' }), + instructionAccountNode({ isOptional: false, isSigner: false, isWritable: false, name: 'mint' }), + instructionAccountNode({ + defaultValue: publicKeyValueNode('TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA'), + isOptional: false, + isSigner: false, + isWritable: false, + name: 'tokenProgram', + }), + instructionAccountNode({ + defaultValue: pdaValueNode(pdaLinkNode('ata'), [ + pdaSeedValueNode('owner', accountValueNode('owner')), + pdaSeedValueNode('tokenProgram', accountValueNode('tokenProgram')), + pdaSeedValueNode('mint', accountValueNode('mint')), + ]), + isOptional: false, + isSigner: false, + isWritable: true, + name: 'ata', + }), + ], + name: 'createAta', + }), + ], + name: 'testProgram', + publicKey: '11111111111111111111111111111111', + }); + + // When we render it. + const renderMap = visit(node, getRenderMapVisitor()); + const content = getFromRenderMap(renderMap, 'instructions/create_ata.rs').content; + + // Then we expect the tokenProgram seed to use unwrap_or with its default. + codeContains(content, [ + `crate::pdas::find_ata_pda(`, + `&self.owner.expect("owner is needed for ata PDA")`, + `&self.token_program.unwrap_or(solana_address::address!("TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA"))`, + `&self.mint.expect("mint is needed for ata PDA")`, + ]); +}); + +test('it resolves programIdValueNode defaults as PDA seed defaults', () => { + // Given a PDA seed that references an account with a programIdValueNode default. + const node = programNode({ + instructions: [ + instructionNode({ + accounts: [ + instructionAccountNode({ isOptional: false, isSigner: true, isWritable: false, name: 'owner' }), + instructionAccountNode({ + defaultValue: programIdValueNode(), + isOptional: false, + isSigner: false, + isWritable: false, + name: 'programAddress', + }), + instructionAccountNode({ + defaultValue: pdaValueNode(pdaLinkNode('record'), [ + pdaSeedValueNode('owner', accountValueNode('owner')), + pdaSeedValueNode('programAddress', accountValueNode('programAddress')), + ]), + isOptional: false, + isSigner: false, + isWritable: true, + name: 'record', + }), + ], + name: 'createRecord', + }), + ], + name: 'testProgram', + publicKey: '11111111111111111111111111111111', + }); + + // When we render it. + const renderMap = visit(node, getRenderMapVisitor()); + const content = getFromRenderMap(renderMap, 'instructions/create_record.rs').content; + + // Then the programAddress seed uses unwrap_or with the program ID constant. + codeContains(content, [`&self.program_address.unwrap_or(crate::TEST_PROGRAM_ID)`]); +}); + +test('it passes Pubkey argument seeds by reference', () => { + // Given an instruction with a PDA that has a Pubkey argument seed. + const node = programNode({ + instructions: [ + instructionNode({ + accounts: [ + instructionAccountNode({ isOptional: false, isSigner: true, isWritable: false, name: 'owner' }), + instructionAccountNode({ + defaultValue: pdaValueNode(pdaLinkNode('record'), [ + pdaSeedValueNode('owner', accountValueNode('owner')), + pdaSeedValueNode('delegate', argumentValueNode('delegate')), + ]), + isOptional: false, + isSigner: false, + isWritable: true, + name: 'record', + }), + ], + arguments: [instructionArgumentNode({ name: 'delegate', type: publicKeyTypeNode() })], + name: 'createRecord', + }), + ], + name: 'testProgram', + pdas: [ + pdaNode({ + name: 'record', + seeds: [ + constantPdaSeedNode(bytesTypeNode(), bytesValueNode('utf8', 'rec')), + variablePdaSeedNode('owner', publicKeyTypeNode()), + variablePdaSeedNode('delegate', publicKeyTypeNode()), + ], + }), + ], + publicKey: '11111111111111111111111111111111', + }); + + // When we render it. + const renderMap = visit(node, getRenderMapVisitor()); + const content = getFromRenderMap(renderMap, 'instructions/create_record.rs').content; + + // Then we expect the Pubkey argument seed to use by-ref. + codeContains(content, [ + `&self.owner.expect("owner is needed for record PDA")`, + `&self.delegate.clone().expect("delegate is needed for record PDA")`, + ]); +}); + +test('it handles argument/account name conflicts in PDA seeds', () => { + // Given a non-Pubkey argument that conflicts with an account name. + const stringConflict = programNode({ + instructions: [ + instructionNode({ + accounts: [ + instructionAccountNode({ isOptional: false, isSigner: true, isWritable: false, name: 'owner' }), + instructionAccountNode({ + defaultValue: pdaValueNode(pdaLinkNode('record'), [ + pdaSeedValueNode('owner', accountValueNode('owner')), + pdaSeedValueNode('label', argumentValueNode('owner')), + ]), + isOptional: false, + isSigner: false, + isWritable: true, + name: 'record', + }), + ], + arguments: [instructionArgumentNode({ name: 'owner', type: stringTypeNode('utf8') })], + name: 'createRecord', + }), + ], + name: 'testProgram', + pdas: [ + pdaNode({ + name: 'record', + seeds: [ + variablePdaSeedNode('owner', publicKeyTypeNode()), + variablePdaSeedNode('label', stringTypeNode('utf8')), + ], + }), + ], + publicKey: '11111111111111111111111111111111', + }); + + const content1 = getFromRenderMap( + visit(stringConflict, getRenderMapVisitor()), + 'instructions/create_record.rs', + ).content; + codeContains(content1, [ + `&self.owner.expect("owner is needed for record PDA")`, + `self.owner_arg.clone().expect("owner_arg is needed for record PDA")`, + ]); + + // And a Pubkey argument that conflicts — should also get _arg suffix with by-ref. + const pubkeyConflict = programNode({ + instructions: [ + instructionNode({ + accounts: [ + instructionAccountNode({ isOptional: false, isSigner: true, isWritable: false, name: 'delegate' }), + instructionAccountNode({ + defaultValue: pdaValueNode(pdaLinkNode('record'), [ + pdaSeedValueNode('owner', accountValueNode('delegate')), + pdaSeedValueNode('delegate', argumentValueNode('delegate')), + ]), + isOptional: false, + isSigner: false, + isWritable: true, + name: 'record', + }), + ], + arguments: [instructionArgumentNode({ name: 'delegate', type: publicKeyTypeNode() })], + name: 'createRecord', + }), + ], + name: 'testProgram', + pdas: [ + pdaNode({ + name: 'record', + seeds: [ + variablePdaSeedNode('owner', publicKeyTypeNode()), + variablePdaSeedNode('delegate', publicKeyTypeNode()), + ], + }), + ], + publicKey: '11111111111111111111111111111111', + }); + + const content2 = getFromRenderMap( + visit(pubkeyConflict, getRenderMapVisitor()), + 'instructions/create_record.rs', + ).content; + codeContains(content2, [ + `&self.delegate.expect("delegate is needed for record PDA")`, + `&self.delegate_arg.clone().expect("delegate_arg is needed for record PDA")`, + ]); +}); + +test('it handles argument defaults in PDA seeds', () => { + // Omitted arguments are inlined as their default value. + const omittedArg = programNode({ + instructions: [ + instructionNode({ + accounts: [ + instructionAccountNode({ isOptional: false, isSigner: true, isWritable: false, name: 'owner' }), + instructionAccountNode({ + defaultValue: pdaValueNode(pdaLinkNode('record'), [ + pdaSeedValueNode('owner', accountValueNode('owner')), + pdaSeedValueNode('kind', argumentValueNode('kind')), + ]), + isOptional: false, + isSigner: false, + isWritable: true, + name: 'record', + }), + ], + arguments: [ + instructionArgumentNode({ + defaultValue: numberValueNode(42), + defaultValueStrategy: 'omitted', + name: 'kind', + type: numberTypeNode('u32'), + }), + ], + name: 'createRecord', + }), + ], + name: 'testProgram', + pdas: [ + pdaNode({ + name: 'record', + seeds: [ + variablePdaSeedNode('owner', publicKeyTypeNode()), + variablePdaSeedNode('kind', numberTypeNode('u32')), + ], + }), + ], + publicKey: '11111111111111111111111111111111', + }); + + const content1 = getFromRenderMap( + visit(omittedArg, getRenderMapVisitor()), + 'instructions/create_record.rs', + ).content; + codeContains(content1, [`42`]); + expect(content1).not.toContain('self.kind'); + + // Non-omitted arguments still use expect (no silent defaulting for PDA seeds). + const nonOmittedArg = programNode({ + instructions: [ + instructionNode({ + accounts: [ + instructionAccountNode({ isOptional: false, isSigner: true, isWritable: false, name: 'owner' }), + instructionAccountNode({ + defaultValue: pdaValueNode(pdaLinkNode('record'), [ + pdaSeedValueNode('owner', accountValueNode('owner')), + pdaSeedValueNode('version', argumentValueNode('version')), + ]), + isOptional: false, + isSigner: false, + isWritable: true, + name: 'record', + }), + ], + arguments: [ + instructionArgumentNode({ + defaultValue: numberValueNode(1), + name: 'version', + type: numberTypeNode('u32'), + }), + ], + name: 'createRecord', + }), + ], + name: 'testProgram', + pdas: [ + pdaNode({ + name: 'record', + seeds: [ + variablePdaSeedNode('owner', publicKeyTypeNode()), + variablePdaSeedNode('version', numberTypeNode('u32')), + ], + }), + ], + publicKey: '11111111111111111111111111111111', + }); + + const content2 = getFromRenderMap( + visit(nonOmittedArg, getRenderMapVisitor()), + 'instructions/create_record.rs', + ).content; + codeContains(content2, [`self.version.clone().expect("version is needed for record PDA")`]); +}); + +test('it extracts Pubkey from either-signer tuple for PDA seeds', () => { + // Given a PDA seed that references an isSigner: 'either' account. + const node = programNode({ + instructions: [ + instructionNode({ + accounts: [ + instructionAccountNode({ + isOptional: false, + isSigner: 'either', + isWritable: false, + name: 'authority', + }), + instructionAccountNode({ + defaultValue: pdaValueNode(pdaLinkNode('record'), [ + pdaSeedValueNode('authority', accountValueNode('authority')), + ]), + isOptional: false, + isSigner: false, + isWritable: true, + name: 'record', + }), + ], + name: 'createRecord', + }), + ], + name: 'testProgram', + publicKey: '11111111111111111111111111111111', + }); + + // When we render it. + const renderMap = visit(node, getRenderMapVisitor()); + const content = getFromRenderMap(renderMap, 'instructions/create_record.rs').content; + + // Then we expect the seed to extract the Pubkey from the tuple. + codeContains(content, [`.map(|(k, _)| k).expect("authority is needed for record PDA")`]); +}); + +test('it extracts Pubkey from either-signer tuple for inline pdaNode seeds', () => { + // Given an inline pdaNode seed that references an isSigner: 'either' account. + const node = programNode({ + instructions: [ + instructionNode({ + accounts: [ + instructionAccountNode({ + isOptional: false, + isSigner: 'either', + isWritable: false, + name: 'authority', + }), + instructionAccountNode({ + defaultValue: pdaValueNode( + pdaNode({ + name: 'record', + seeds: [variablePdaSeedNode('authority', publicKeyTypeNode())], + }), + [pdaSeedValueNode('authority', accountValueNode('authority'))], + ), + isOptional: false, + isSigner: false, + isWritable: true, + name: 'record', + }), + ], + name: 'createRecord', + }), + ], + name: 'testProgram', + publicKey: '11111111111111111111111111111111', + }); + + // When we render it. + const renderMap = visit(node, getRenderMapVisitor()); + const content = getFromRenderMap(renderMap, 'instructions/create_record.rs').content; + + // Then we expect the seed to extract the Pubkey from the tuple. + codeContains(content, [`.map(|(k, _)| k).expect("authority is needed for record PDA")`]); +}); + +test('it renders a builder that auto-derives inline pdaNode accounts', () => { + // Given an instruction with an inline pdaNode default (constant + variable seeds). + const node = programNode({ + instructions: [ + instructionNode({ + accounts: [ + instructionAccountNode({ isOptional: false, isSigner: true, isWritable: false, name: 'mint' }), + instructionAccountNode({ + defaultValue: pdaValueNode( + pdaNode({ + name: 'guard', + seeds: [ + constantPdaSeedNode(bytesTypeNode(), bytesValueNode('utf8', 'my_seed')), + variablePdaSeedNode('mint', publicKeyTypeNode()), + ], + }), + [pdaSeedValueNode('mint', accountValueNode('mint'))], + ), + isOptional: false, + isSigner: false, + isWritable: true, + name: 'guard', + }), + ], + name: 'createGuard', + }), + ], + name: 'testProgram', + publicKey: '11111111111111111111111111111111', + }); + + // When we render it. + const renderMap = visit(node, getRenderMapVisitor()); + const content = getFromRenderMap(renderMap, 'instructions/create_guard.rs').content; + + // Then the builder should generate inline find_program_address. + codeContains(content, [ + `unwrap_or_else(|| {`, + `solana_address::Address::find_program_address(`, + /&\[109, 121, 95, 115, 101, 101, 100\]/, + `self.mint.expect("mint is needed for guard PDA").as_ref()`, + `&crate::TEST_PROGRAM_ID`, + `.0`, + `default to PDA derived from 'guard'`, + ]); +}); + +test('it renders inline pdaNode with argumentValueNode variable seed using type dispatch', () => { + // Given an instruction with an argument-valued variable seed. + const node = programNode({ + instructions: [ + instructionNode({ + accounts: [ + instructionAccountNode({ isOptional: false, isSigner: true, isWritable: false, name: 'mint' }), + instructionAccountNode({ + defaultValue: pdaValueNode( + pdaNode({ + name: 'record', + seeds: [ + constantPdaSeedNode(bytesTypeNode(), bytesValueNode('utf8', 'rec')), + variablePdaSeedNode('mint', publicKeyTypeNode()), + variablePdaSeedNode('label', stringTypeNode('utf8')), + ], + }), + [ + pdaSeedValueNode('mint', accountValueNode('mint')), + pdaSeedValueNode('label', argumentValueNode('label')), + ], + ), + isOptional: false, + isSigner: false, + isWritable: true, + name: 'record', + }), + ], + arguments: [instructionArgumentNode({ name: 'label', type: stringTypeNode('utf8') })], + name: 'createRecord', + }), + ], + name: 'testProgram', + publicKey: '11111111111111111111111111111111', + }); + + // When we render it. + const renderMap = visit(node, getRenderMapVisitor()); + const content = getFromRenderMap(renderMap, 'instructions/create_record.rs').content; + + // Then argument seeds use .to_string().as_ref() for string types (not bare .as_ref()). + codeContains(content, [ + `self.mint.expect("mint is needed for record PDA").as_ref()`, + `self.label.clone().expect("label is needed for record PDA").to_string().as_ref()`, + ]); +}); + +test('it renders inline pdaNode with custom programId', () => { + // Given an instruction with an inline pdaNode that specifies a custom programId. + const node = programNode({ + instructions: [ + instructionNode({ + accounts: [ + instructionAccountNode({ isOptional: false, isSigner: true, isWritable: false, name: 'mint' }), + instructionAccountNode({ + defaultValue: pdaValueNode( + pdaNode({ + name: 'ata', + programId: 'ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL', + seeds: [variablePdaSeedNode('mint', publicKeyTypeNode())], + }), + [pdaSeedValueNode('mint', accountValueNode('mint'))], + ), + isOptional: false, + isSigner: false, + isWritable: true, + name: 'ata', + }), + ], + name: 'createAta', + }), + ], + name: 'testProgram', + publicKey: '11111111111111111111111111111111', + }); + + // When we render it. + const renderMap = visit(node, getRenderMapVisitor()); + const content = getFromRenderMap(renderMap, 'instructions/create_ata.rs').content; + + // Then the custom programId is used instead of the current program's ID. + codeContains(content, [`&solana_address::address!("ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL")`]); +}); + +test('it resolves upstream account defaults when used as inline PDA seeds', () => { + // Given an instruction where a PDA seed references an account with its own default. + const node = programNode({ + instructions: [ + instructionNode({ + accounts: [ + instructionAccountNode({ isOptional: false, isSigner: true, isWritable: false, name: 'mint' }), + instructionAccountNode({ isOptional: false, isSigner: false, isWritable: false, name: 'owner' }), + instructionAccountNode({ + defaultValue: publicKeyValueNode('TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA'), + isOptional: false, + isSigner: false, + isWritable: false, + name: 'tokenProgram', + }), + instructionAccountNode({ + defaultValue: pdaValueNode( + pdaNode({ + name: 'ata', + programId: 'ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL', + seeds: [ + variablePdaSeedNode('owner', publicKeyTypeNode()), + variablePdaSeedNode('tokenProgram', publicKeyTypeNode()), + variablePdaSeedNode('mint', publicKeyTypeNode()), + ], + }), + [ + pdaSeedValueNode('owner', accountValueNode('owner')), + pdaSeedValueNode('tokenProgram', accountValueNode('tokenProgram')), + pdaSeedValueNode('mint', accountValueNode('mint')), + ], + ), + isOptional: false, + isSigner: false, + isWritable: true, + name: 'ata', + }), + ], + name: 'createAta', + }), + ], + name: 'testProgram', + publicKey: '11111111111111111111111111111111', + }); + + // When we render it. + const renderMap = visit(node, getRenderMapVisitor()); + const content = getFromRenderMap(renderMap, 'instructions/create_ata.rs').content; + + // Then tokenProgram seed uses unwrap_or with its default instead of expect. + codeContains(content, [ + `self.token_program.unwrap_or(solana_address::address!("TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA")).as_ref()`, + ]); + // And required accounts without defaults still use expect. + codeContains(content, [ + `self.owner.expect("owner is needed for ata PDA").as_ref()`, + `self.mint.expect("mint is needed for ata PDA").as_ref()`, + ]); +}); + +test('it renders inline pdaNode with programIdValueNode constant seed', () => { + // Given an instruction with a programIdValueNode as a constant seed. + const node = programNode({ + instructions: [ + instructionNode({ + accounts: [ + instructionAccountNode({ isOptional: false, isSigner: true, isWritable: false, name: 'mint' }), + instructionAccountNode({ + defaultValue: pdaValueNode( + pdaNode({ + name: 'record', + seeds: [ + constantPdaSeedNode(bytesTypeNode(), programIdValueNode()), + variablePdaSeedNode('mint', publicKeyTypeNode()), + ], + }), + [pdaSeedValueNode('mint', accountValueNode('mint'))], + ), + isOptional: false, + isSigner: false, + isWritable: true, + name: 'record', + }), + ], + name: 'createRecord', + }), + ], + name: 'testProgram', + publicKey: '11111111111111111111111111111111', + }); + + // When we render it. + const renderMap = visit(node, getRenderMapVisitor()); + const content = getFromRenderMap(renderMap, 'instructions/create_record.rs').content; + + // Then the programId is used as a constant seed. + codeContains(content, [`crate::TEST_PROGRAM_ID.as_ref()`]); +}); + test('it renders a default impl for instruction data struct', () => { // Given the following program with 1 instruction. const node = programNode({ @@ -69,3 +808,351 @@ test('it renders a default impl for instruction data struct', () => { `fn default(`, ]); }); + +test('it resolves cascading PDA defaults via let bindings', () => { + // Given an instruction where vault (inline PDA) depends on pool (linked PDA). + // Without let bindings, vault would read self.pool (still None) and panic. + const node = programNode({ + instructions: [ + instructionNode({ + accounts: [ + instructionAccountNode({ isOptional: false, isSigner: false, isWritable: false, name: 'mint' }), + instructionAccountNode({ + defaultValue: pdaValueNode(pdaLinkNode('pool'), [ + pdaSeedValueNode('mint', accountValueNode('mint')), + ]), + isOptional: false, + isSigner: false, + isWritable: true, + name: 'pool', + }), + instructionAccountNode({ + defaultValue: pdaValueNode( + pdaNode({ + name: 'vault', + programId: 'ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL', + seeds: [ + variablePdaSeedNode('authority', publicKeyTypeNode()), + variablePdaSeedNode('mint', publicKeyTypeNode()), + ], + }), + [ + pdaSeedValueNode('authority', accountValueNode('pool')), + pdaSeedValueNode('mint', accountValueNode('mint')), + ], + ), + isOptional: false, + isSigner: false, + isWritable: true, + name: 'vault', + }), + ], + name: 'swap', + }), + ], + name: 'testProgram', + pdas: [ + pdaNode({ + name: 'pool', + seeds: [variablePdaSeedNode('mint', publicKeyTypeNode())], + }), + ], + publicKey: '11111111111111111111111111111111', + }); + + // When we render it. + const renderMap = visit(node, getRenderMapVisitor()); + const content = getFromRenderMap(renderMap, 'instructions/swap.rs').content; + + // Then pool is emitted as a let binding. + codeContains(content, [`let pool = self.pool.unwrap_or_else(|| {`, `find_pool_pda(`]); + // And vault is also a let binding that references the local `pool`, not self.pool. + codeContains(content, [`let vault = self.vault.unwrap_or_else(|| {`, `pool.as_ref()`]); + // And the struct literal uses the locals. + codeContains(content, [/Swap \{\s*mint:/]); + // Verify vault does NOT read self.pool (which would panic). + expect(content).not.toContain('self.pool.expect'); +}); + +test('it topologically sorts PDA let bindings when dependency is declared after dependent', () => { + // Given an instruction where vault (inline PDA) references authority (linked PDA), + // but vault is declared BEFORE authority in the accounts list. + // This mirrors the real-world claim_airdrop pattern. + const node = programNode({ + instructions: [ + instructionNode({ + accounts: [ + instructionAccountNode({ isOptional: false, isSigner: false, isWritable: false, name: 'mint' }), + // vault comes first but depends on authority + instructionAccountNode({ + defaultValue: pdaValueNode( + pdaNode({ + name: 'vault', + programId: 'ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL', + seeds: [ + variablePdaSeedNode('authority', publicKeyTypeNode()), + variablePdaSeedNode('mint', publicKeyTypeNode()), + ], + }), + [ + pdaSeedValueNode('authority', accountValueNode('authority')), + pdaSeedValueNode('mint', accountValueNode('mint')), + ], + ), + isOptional: false, + isSigner: false, + isWritable: true, + name: 'vault', + }), + // authority comes second but is vault's dependency + instructionAccountNode({ + defaultValue: pdaValueNode(pdaLinkNode('authority'), []), + isOptional: false, + isSigner: false, + isWritable: false, + name: 'authority', + }), + ], + name: 'claimAirdrop', + }), + ], + name: 'testProgram', + pdas: [pdaNode({ name: 'authority', seeds: [] })], + publicKey: '11111111111111111111111111111111', + }); + + // When we render it. + const renderMap = visit(node, getRenderMapVisitor()); + const content = getFromRenderMap(renderMap, 'instructions/claim_airdrop.rs').content; + + // Then authority's let binding must appear BEFORE vault's let binding, + // even though vault is declared first in the accounts list. + const authorityPos = content.indexOf('let authority ='); + const vaultPos = content.indexOf('let vault ='); + expect(authorityPos).toBeGreaterThan(-1); + expect(vaultPos).toBeGreaterThan(-1); + expect(authorityPos).toBeLessThan(vaultPos); + + // And vault references the local `authority`, not self.authority. + codeContains(content, [`authority.as_ref()`]); + expect(content).not.toContain('self.authority.expect'); +}); + +test('it handles argument/account name conflicts in inline pdaNode seeds', () => { + // Given an inline PDA with an argument seed whose name conflicts with an account name. + const node = programNode({ + instructions: [ + instructionNode({ + accounts: [ + instructionAccountNode({ isOptional: false, isSigner: true, isWritable: false, name: 'owner' }), + instructionAccountNode({ + defaultValue: pdaValueNode( + pdaNode({ + name: 'record', + seeds: [ + variablePdaSeedNode('authority', publicKeyTypeNode()), + variablePdaSeedNode('label', stringTypeNode('utf8')), + ], + }), + [ + pdaSeedValueNode('authority', accountValueNode('owner')), + pdaSeedValueNode('label', argumentValueNode('owner')), + ], + ), + isOptional: false, + isSigner: false, + isWritable: true, + name: 'record', + }), + ], + arguments: [instructionArgumentNode({ name: 'owner', type: stringTypeNode('utf8') })], + name: 'createRecord', + }), + ], + name: 'testProgram', + publicKey: '11111111111111111111111111111111', + }); + + const renderMap = visit(node, getRenderMapVisitor()); + const content = getFromRenderMap(renderMap, 'instructions/create_record.rs').content; + + // The account seed should reference self.owner (the account field). + codeContains(content, [`self.owner.expect("owner is needed for record PDA").as_ref()`]); + // The argument seed should reference self.owner_arg (the _arg suffixed field). + codeContains(content, [`self.owner_arg.clone().expect("owner_arg is needed for record PDA")`]); +}); + +test('it handles omitted-default argument seeds in inline pdaNode', () => { + // Given an inline PDA with an omitted-default argument seed. + const node = programNode({ + instructions: [ + instructionNode({ + accounts: [ + instructionAccountNode({ isOptional: false, isSigner: true, isWritable: false, name: 'owner' }), + instructionAccountNode({ + defaultValue: pdaValueNode( + pdaNode({ + name: 'record', + seeds: [ + variablePdaSeedNode('owner', publicKeyTypeNode()), + variablePdaSeedNode('kind', numberTypeNode('u32')), + ], + }), + [ + pdaSeedValueNode('owner', accountValueNode('owner')), + pdaSeedValueNode('kind', argumentValueNode('kind')), + ], + ), + isOptional: false, + isSigner: false, + isWritable: true, + name: 'record', + }), + ], + arguments: [ + instructionArgumentNode({ + defaultValue: numberValueNode(42), + defaultValueStrategy: 'omitted', + name: 'kind', + type: numberTypeNode('u32'), + }), + ], + name: 'createRecord', + }), + ], + name: 'testProgram', + publicKey: '11111111111111111111111111111111', + }); + + const renderMap = visit(node, getRenderMapVisitor()); + const content = getFromRenderMap(renderMap, 'instructions/create_record.rs').content; + + // The omitted arg should be inlined as its default value, not read from self.kind. + codeContains(content, [`42`]); + expect(content).not.toContain('self.kind'); +}); + +test('it falls back to .expect() for both accounts in a circular PDA dependency', () => { + // Given two accounts with circular PDA dependencies (A depends on B, B depends on A). + const node = programNode({ + instructions: [ + instructionNode({ + accounts: [ + instructionAccountNode({ + defaultValue: pdaValueNode( + pdaNode({ + name: 'pdaA', + seeds: [variablePdaSeedNode('b', publicKeyTypeNode())], + }), + [pdaSeedValueNode('b', accountValueNode('accountB'))], + ), + isOptional: false, + isSigner: false, + isWritable: false, + name: 'accountA', + }), + instructionAccountNode({ + defaultValue: pdaValueNode( + pdaNode({ + name: 'pdaB', + seeds: [variablePdaSeedNode('a', publicKeyTypeNode())], + }), + [pdaSeedValueNode('a', accountValueNode('accountA'))], + ), + isOptional: false, + isSigner: false, + isWritable: false, + name: 'accountB', + }), + ], + name: 'circular', + }), + ], + name: 'testProgram', + publicKey: '11111111111111111111111111111111', + }); + + const renderMap = visit(node, getRenderMapVisitor()); + const content = getFromRenderMap(renderMap, 'instructions/circular.rs').content; + + // Then BOTH accounts must fall back to .expect() — neither PDA can be resolved. + codeContains(content, [ + 'self.account_a.expect("account_a is not set")', + 'self.account_b.expect("account_b is not set")', + ]); + // No PDA derivation code should be emitted for either. + codeDoesNotContains(content, ['find_program_address', 'unwrap_or_else']); +}); + +test('it bails entire PDA resolution when a variable seed has no binding', () => { + // Given an inline PDA with a variable seed that has no matching binding. + const node = programNode({ + instructions: [ + instructionNode({ + accounts: [ + instructionAccountNode({ isOptional: false, isSigner: false, isWritable: false, name: 'mint' }), + instructionAccountNode({ + defaultValue: pdaValueNode( + pdaNode({ + name: 'vault', + seeds: [ + variablePdaSeedNode('owner', publicKeyTypeNode()), + variablePdaSeedNode('mint', publicKeyTypeNode()), + ], + }), + // Only provide binding for 'mint', not 'owner' — incomplete seeds. + [pdaSeedValueNode('mint', accountValueNode('mint'))], + ), + isOptional: false, + isSigner: false, + isWritable: true, + name: 'vault', + }), + ], + name: 'deposit', + }), + ], + name: 'testProgram', + publicKey: '11111111111111111111111111111111', + }); + + const renderMap = visit(node, getRenderMapVisitor()); + const content = getFromRenderMap(renderMap, 'instructions/deposit.rs').content; + + // The account should fall back to .expect() — no PDA derivation with incomplete seeds. + codeContains(content, ['self.vault.expect("vault is not set")']); + codeDoesNotContains(content, ['find_program_address', 'unwrap_or_else']); +}); + +test('it uses unwrap_or with precomputed address for zero-variable-seed linked PDA', () => { + const node = programNode({ + instructions: [ + instructionNode({ + accounts: [ + instructionAccountNode({ + defaultValue: pdaValueNode(pdaLinkNode('config'), []), + isOptional: false, + isSigner: false, + isWritable: false, + name: 'config', + }), + ], + name: 'doSomething', + }), + ], + name: 'testProgram', + pdas: [ + pdaNode({ + name: 'config', + seeds: [constantPdaSeedNodeFromString('utf8', 'config')], + }), + ], + publicKey: '11111111111111111111111111111111', + }); + + const renderMap = visit(node, getRenderMapVisitor()); + const content = getFromRenderMap(renderMap, 'instructions/do_something.rs').content; + + codeContains(content, ['unwrap_or(', 'crate::pdas::CONFIG_ADDRESS']); + codeDoesNotContains(content, ['unwrap_or_else', 'find_config_pda']); +}); diff --git a/test/pdasPage.test.ts b/test/pdasPage.test.ts index 3912701..673d86d 100644 --- a/test/pdasPage.test.ts +++ b/test/pdasPage.test.ts @@ -1,6 +1,7 @@ import { bytesTypeNode, constantPdaSeedNode, + constantPdaSeedNodeFromBytes, constantPdaSeedNodeFromString, fixedSizeTypeNode, numberTypeNode, @@ -16,7 +17,7 @@ import { visit } from '@codama/visitors-core'; import { test } from 'vitest'; import { getRenderMapVisitor } from '../src'; -import { codeContains } from './_setup'; +import { codeContains, codeDoesNotContains } from './_setup'; test('it renders a standalone PDA with variable seeds', () => { // Given a program with a PDA that has variable seeds. @@ -68,10 +69,11 @@ test('it renders a PDA with only constant seeds', () => { // When we render it. const renderMap = visit(node, getRenderMapVisitor()); - // Then we expect the PDA functions without variable parameters. codeContains(getFromRenderMap(renderMap, 'pdas/config_pda.rs').content, [ 'pub const CONFIG_PDA_SEED_0: &\'static [u8] = b"config";', - "pub const CONFIG_PDA_SEED_1: &'static [u8] = b1;", + "pub const CONFIG_PDA_SEED_1: &'static [u8] = &1u64.to_le_bytes();", + 'pub const CONFIG_PDA_ADDRESS: solana_address::Address =', + 'solana_address::address!("EdgDu3sEjDtMpJuDkG8VsWnKq16EYxTsuwCmSko3wZnR")', 'pub fn create_config_pda_pda(', 'bump: u8,', 'pub fn find_config_pda_pda(', @@ -159,3 +161,51 @@ test('it includes PDAs module in the root mod file', () => { // Then we expect the pdas module to be included in the root mod. codeContains(getFromRenderMap(renderMap, 'mod.rs').content, ['pub mod pdas;']); }); + +test('it does not emit a precomputed address for PDAs with variable seeds', () => { + const node = programNode({ + name: 'myProgram', + pdas: [ + pdaNode({ + name: 'myPda', + seeds: [ + constantPdaSeedNodeFromString('utf8', 'metadata'), + variablePdaSeedNode('mint', publicKeyTypeNode()), + ], + }), + ], + publicKey: 'TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA', + }); + + const renderMap = visit(node, getRenderMapVisitor()); + codeDoesNotContains(getFromRenderMap(renderMap, 'pdas/my_pda.rs').content, ['_ADDRESS']); +}); + +test('it renders a PDA with byte array constant seeds', () => { + // Given a program with a PDA that has byte array seeds (e.g. from Anchor IDL extraction). + const node = programNode({ + name: 'myProgram', + pdas: [ + pdaNode({ + name: 'guardPda', + seeds: [ + constantPdaSeedNodeFromBytes('base58', 'F9bS'), + variablePdaSeedNode('mint', publicKeyTypeNode()), + ], + }), + ], + publicKey: 'TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA', + }); + + // When we render it. + const renderMap = visit(node, getRenderMapVisitor()); + + // Then we expect byte array seeds to use &[...] syntax, not b[...]. + codeContains(getFromRenderMap(renderMap, 'pdas/guard_pda.rs').content, [ + "pub const GUARD_PDA_SEED: &'static [u8] = &[", + 'pub fn create_guard_pda_pda(', + 'mint: Address,', + 'pub fn find_guard_pda_pda(', + 'mint: &Address,', + ]); +}); From 3d53b0527dc30b892b612d3216e142d60510df9e Mon Sep 17 00:00:00 2001 From: ioxde <228087182+ioxde@users.noreply.github.com> Date: Sat, 4 Apr 2026 12:58:19 -0700 Subject: [PATCH 17/24] Validate account discriminators, owners, and Anchor try_deserialize The generated from_bytes() blindly deserialized without checking that the discriminator bytes matched, silently accepting wrong account data. The TryFrom<&AccountInfo> and fetch_* helpers had no owner validation, and the Anchor AccountDeserialize::try_deserialize defaulted to unchecked deserialization with no discriminator gate. - from_bytes() now rejects data with a mismatched discriminator prefix - TryFrom<&AccountInfo> checks account_info.owner before deserializing - fetch_all_* and fetch_all_maybe_* check account.owner before deserializing - TryFrom delegates to from_bytes() instead of duplicating deserialization - Anchor try_deserialize checks the discriminator before calling unchecked - Anchor Discriminator trait uses the real constant instead of [0; 8] --- e2e/anchor/src/generated/accounts/guard_v1.rs | 37 +++- .../src/generated/accounts/governance_v1.rs | 20 +- .../src/generated/accounts/governance_v2.rs | 20 +- .../accounts/legacy_token_owner_record.rs | 20 +- .../generated/accounts/program_metadata.rs | 20 +- .../generated/accounts/proposal_deposit.rs | 20 +- .../accounts/proposal_instruction_v1.rs | 20 +- .../accounts/proposal_transaction_v2.rs | 20 +- .../src/generated/accounts/proposal_v1.rs | 20 +- .../src/generated/accounts/proposal_v2.rs | 20 +- .../accounts/realm_config_account.rs | 20 +- .../src/generated/accounts/realm_v1.rs | 20 +- .../src/generated/accounts/realm_v2.rs | 20 +- .../generated/accounts/required_signatory.rs | 20 +- .../generated/accounts/signatory_record_v1.rs | 20 +- .../generated/accounts/signatory_record_v2.rs | 20 +- .../accounts/token_owner_record_v1.rs | 20 +- .../accounts/token_owner_record_v2.rs | 20 +- .../src/generated/accounts/vote_record_v1.rs | 20 +- .../src/generated/accounts/vote_record_v2.rs | 20 +- e2e/system/src/generated/accounts/nonce.rs | 20 +- public/templates/accountsPage.njk | 39 +++- src/getRenderMapVisitor.ts | 8 + src/utils/discriminatorConstant.ts | 28 +++ test/accountsPage.test.ts | 206 ++++++++++++++++++ 25 files changed, 673 insertions(+), 45 deletions(-) diff --git a/e2e/anchor/src/generated/accounts/guard_v1.rs b/e2e/anchor/src/generated/accounts/guard_v1.rs index d766a97..2b2bb35 100644 --- a/e2e/anchor/src/generated/accounts/guard_v1.rs +++ b/e2e/anchor/src/generated/accounts/guard_v1.rs @@ -32,6 +32,12 @@ pub const GUARD_V1_DISCRIMINATOR: [u8; 8] = [185, 149, 156, 78, 245, 108, 172, 6 impl GuardV1 { #[inline(always)] pub fn from_bytes(data: &[u8]) -> Result { + if data.get(..GUARD_V1_DISCRIMINATOR.len()) != Some(&GUARD_V1_DISCRIMINATOR[..]) { + return Err(std::io::Error::new( + std::io::ErrorKind::InvalidData, + "invalid account discriminator", + )); + } let mut data = data; Self::deserialize(&mut data) } @@ -41,8 +47,14 @@ impl<'a> TryFrom<&solana_account_info::AccountInfo<'a>> for GuardV1 { type Error = std::io::Error; fn try_from(account_info: &solana_account_info::AccountInfo<'a>) -> Result { - let mut data: &[u8] = &(*account_info.data).borrow(); - Self::deserialize(&mut data) + if account_info.owner != &crate::WEN_TRANSFER_GUARD_ID { + return Err(std::io::Error::new( + std::io::ErrorKind::InvalidData, + "invalid account owner", + )); + } + let data: &[u8] = &(*account_info.data).borrow(); + Self::from_bytes(data) } } @@ -69,6 +81,11 @@ pub fn fetch_all_guard_v1( let account = accounts[i].as_ref().ok_or(std::io::Error::other(format!( "Account not found: {address}" )))?; + if account.owner != crate::WEN_TRANSFER_GUARD_ID { + return Err(std::io::Error::other(format!( + "Invalid owner for account: {address}" + ))); + } let data = GuardV1::from_bytes(&account.data)?; decoded_accounts.push(crate::shared::DecodedAccount { address, @@ -100,6 +117,11 @@ pub fn fetch_all_maybe_guard_v1( for i in 0..addresses.len() { let address = addresses[i]; if let Some(account) = accounts[i].as_ref() { + if account.owner != crate::WEN_TRANSFER_GUARD_ID { + return Err(std::io::Error::other(format!( + "Invalid owner for account: {address}" + ))); + } let data = GuardV1::from_bytes(&account.data)?; decoded_accounts.push(crate::shared::MaybeAccount::Exists( crate::shared::DecodedAccount { @@ -117,6 +139,15 @@ pub fn fetch_all_maybe_guard_v1( #[cfg(feature = "anchor")] impl anchor_lang::AccountDeserialize for GuardV1 { + fn try_deserialize(buf: &mut &[u8]) -> anchor_lang::Result { + if buf.len() < GUARD_V1_DISCRIMINATOR.len() + || buf[..GUARD_V1_DISCRIMINATOR.len()] != GUARD_V1_DISCRIMINATOR[..] + { + return Err(anchor_lang::error::ErrorCode::AccountDiscriminatorMismatch.into()); + } + Self::try_deserialize_unchecked(buf) + } + fn try_deserialize_unchecked(buf: &mut &[u8]) -> anchor_lang::Result { Ok(Self::deserialize(buf)?) } @@ -137,5 +168,5 @@ impl anchor_lang::IdlBuild for GuardV1 {} #[cfg(feature = "anchor-idl-build")] impl anchor_lang::Discriminator for GuardV1 { - const DISCRIMINATOR: &[u8] = &[0; 8]; + const DISCRIMINATOR: &[u8] = &GUARD_V1_DISCRIMINATOR; } diff --git a/e2e/governance/src/generated/accounts/governance_v1.rs b/e2e/governance/src/generated/accounts/governance_v1.rs index 50a6f99..35e33c2 100644 --- a/e2e/governance/src/generated/accounts/governance_v1.rs +++ b/e2e/governance/src/generated/accounts/governance_v1.rs @@ -64,8 +64,14 @@ impl<'a> TryFrom<&solana_account_info::AccountInfo<'a>> for GovernanceV1 { type Error = std::io::Error; fn try_from(account_info: &solana_account_info::AccountInfo<'a>) -> Result { - let mut data: &[u8] = &(*account_info.data).borrow(); - Self::deserialize(&mut data) + if account_info.owner != &crate::SPL_GOVERNANCE_ID { + return Err(std::io::Error::new( + std::io::ErrorKind::InvalidData, + "invalid account owner", + )); + } + let data: &[u8] = &(*account_info.data).borrow(); + Self::from_bytes(data) } } @@ -92,6 +98,11 @@ pub fn fetch_all_governance_v1( let account = accounts[i].as_ref().ok_or(std::io::Error::other(format!( "Account not found: {address}" )))?; + if account.owner != crate::SPL_GOVERNANCE_ID { + return Err(std::io::Error::other(format!( + "Invalid owner for account: {address}" + ))); + } let data = GovernanceV1::from_bytes(&account.data)?; decoded_accounts.push(crate::shared::DecodedAccount { address, @@ -123,6 +134,11 @@ pub fn fetch_all_maybe_governance_v1( for i in 0..addresses.len() { let address = addresses[i]; if let Some(account) = accounts[i].as_ref() { + if account.owner != crate::SPL_GOVERNANCE_ID { + return Err(std::io::Error::other(format!( + "Invalid owner for account: {address}" + ))); + } let data = GovernanceV1::from_bytes(&account.data)?; decoded_accounts.push(crate::shared::MaybeAccount::Exists( crate::shared::DecodedAccount { diff --git a/e2e/governance/src/generated/accounts/governance_v2.rs b/e2e/governance/src/generated/accounts/governance_v2.rs index 344834d..4814a88 100644 --- a/e2e/governance/src/generated/accounts/governance_v2.rs +++ b/e2e/governance/src/generated/accounts/governance_v2.rs @@ -68,8 +68,14 @@ impl<'a> TryFrom<&solana_account_info::AccountInfo<'a>> for GovernanceV2 { type Error = std::io::Error; fn try_from(account_info: &solana_account_info::AccountInfo<'a>) -> Result { - let mut data: &[u8] = &(*account_info.data).borrow(); - Self::deserialize(&mut data) + if account_info.owner != &crate::SPL_GOVERNANCE_ID { + return Err(std::io::Error::new( + std::io::ErrorKind::InvalidData, + "invalid account owner", + )); + } + let data: &[u8] = &(*account_info.data).borrow(); + Self::from_bytes(data) } } @@ -96,6 +102,11 @@ pub fn fetch_all_governance_v2( let account = accounts[i].as_ref().ok_or(std::io::Error::other(format!( "Account not found: {address}" )))?; + if account.owner != crate::SPL_GOVERNANCE_ID { + return Err(std::io::Error::other(format!( + "Invalid owner for account: {address}" + ))); + } let data = GovernanceV2::from_bytes(&account.data)?; decoded_accounts.push(crate::shared::DecodedAccount { address, @@ -127,6 +138,11 @@ pub fn fetch_all_maybe_governance_v2( for i in 0..addresses.len() { let address = addresses[i]; if let Some(account) = accounts[i].as_ref() { + if account.owner != crate::SPL_GOVERNANCE_ID { + return Err(std::io::Error::other(format!( + "Invalid owner for account: {address}" + ))); + } let data = GovernanceV2::from_bytes(&account.data)?; decoded_accounts.push(crate::shared::MaybeAccount::Exists( crate::shared::DecodedAccount { diff --git a/e2e/governance/src/generated/accounts/legacy_token_owner_record.rs b/e2e/governance/src/generated/accounts/legacy_token_owner_record.rs index c6cab3d..cbc690d 100644 --- a/e2e/governance/src/generated/accounts/legacy_token_owner_record.rs +++ b/e2e/governance/src/generated/accounts/legacy_token_owner_record.rs @@ -81,8 +81,14 @@ impl<'a> TryFrom<&solana_account_info::AccountInfo<'a>> for LegacyTokenOwnerReco type Error = std::io::Error; fn try_from(account_info: &solana_account_info::AccountInfo<'a>) -> Result { - let mut data: &[u8] = &(*account_info.data).borrow(); - Self::deserialize(&mut data) + if account_info.owner != &crate::SPL_GOVERNANCE_ID { + return Err(std::io::Error::new( + std::io::ErrorKind::InvalidData, + "invalid account owner", + )); + } + let data: &[u8] = &(*account_info.data).borrow(); + Self::from_bytes(data) } } @@ -110,6 +116,11 @@ pub fn fetch_all_legacy_token_owner_record( let account = accounts[i].as_ref().ok_or(std::io::Error::other(format!( "Account not found: {address}" )))?; + if account.owner != crate::SPL_GOVERNANCE_ID { + return Err(std::io::Error::other(format!( + "Invalid owner for account: {address}" + ))); + } let data = LegacyTokenOwnerRecord::from_bytes(&account.data)?; decoded_accounts.push(crate::shared::DecodedAccount { address, @@ -141,6 +152,11 @@ pub fn fetch_all_maybe_legacy_token_owner_record( for i in 0..addresses.len() { let address = addresses[i]; if let Some(account) = accounts[i].as_ref() { + if account.owner != crate::SPL_GOVERNANCE_ID { + return Err(std::io::Error::other(format!( + "Invalid owner for account: {address}" + ))); + } let data = LegacyTokenOwnerRecord::from_bytes(&account.data)?; decoded_accounts.push(crate::shared::MaybeAccount::Exists( crate::shared::DecodedAccount { diff --git a/e2e/governance/src/generated/accounts/program_metadata.rs b/e2e/governance/src/generated/accounts/program_metadata.rs index fa58103..dfe5617 100644 --- a/e2e/governance/src/generated/accounts/program_metadata.rs +++ b/e2e/governance/src/generated/accounts/program_metadata.rs @@ -30,8 +30,14 @@ impl<'a> TryFrom<&solana_account_info::AccountInfo<'a>> for ProgramMetadata { type Error = std::io::Error; fn try_from(account_info: &solana_account_info::AccountInfo<'a>) -> Result { - let mut data: &[u8] = &(*account_info.data).borrow(); - Self::deserialize(&mut data) + if account_info.owner != &crate::SPL_GOVERNANCE_ID { + return Err(std::io::Error::new( + std::io::ErrorKind::InvalidData, + "invalid account owner", + )); + } + let data: &[u8] = &(*account_info.data).borrow(); + Self::from_bytes(data) } } @@ -58,6 +64,11 @@ pub fn fetch_all_program_metadata( let account = accounts[i].as_ref().ok_or(std::io::Error::other(format!( "Account not found: {address}" )))?; + if account.owner != crate::SPL_GOVERNANCE_ID { + return Err(std::io::Error::other(format!( + "Invalid owner for account: {address}" + ))); + } let data = ProgramMetadata::from_bytes(&account.data)?; decoded_accounts.push(crate::shared::DecodedAccount { address, @@ -89,6 +100,11 @@ pub fn fetch_all_maybe_program_metadata( for i in 0..addresses.len() { let address = addresses[i]; if let Some(account) = accounts[i].as_ref() { + if account.owner != crate::SPL_GOVERNANCE_ID { + return Err(std::io::Error::other(format!( + "Invalid owner for account: {address}" + ))); + } let data = ProgramMetadata::from_bytes(&account.data)?; decoded_accounts.push(crate::shared::MaybeAccount::Exists( crate::shared::DecodedAccount { diff --git a/e2e/governance/src/generated/accounts/proposal_deposit.rs b/e2e/governance/src/generated/accounts/proposal_deposit.rs index 05f31df..ed75d1e 100644 --- a/e2e/governance/src/generated/accounts/proposal_deposit.rs +++ b/e2e/governance/src/generated/accounts/proposal_deposit.rs @@ -66,8 +66,14 @@ impl<'a> TryFrom<&solana_account_info::AccountInfo<'a>> for ProposalDeposit { type Error = std::io::Error; fn try_from(account_info: &solana_account_info::AccountInfo<'a>) -> Result { - let mut data: &[u8] = &(*account_info.data).borrow(); - Self::deserialize(&mut data) + if account_info.owner != &crate::SPL_GOVERNANCE_ID { + return Err(std::io::Error::new( + std::io::ErrorKind::InvalidData, + "invalid account owner", + )); + } + let data: &[u8] = &(*account_info.data).borrow(); + Self::from_bytes(data) } } @@ -94,6 +100,11 @@ pub fn fetch_all_proposal_deposit( let account = accounts[i].as_ref().ok_or(std::io::Error::other(format!( "Account not found: {address}" )))?; + if account.owner != crate::SPL_GOVERNANCE_ID { + return Err(std::io::Error::other(format!( + "Invalid owner for account: {address}" + ))); + } let data = ProposalDeposit::from_bytes(&account.data)?; decoded_accounts.push(crate::shared::DecodedAccount { address, @@ -125,6 +136,11 @@ pub fn fetch_all_maybe_proposal_deposit( for i in 0..addresses.len() { let address = addresses[i]; if let Some(account) = accounts[i].as_ref() { + if account.owner != crate::SPL_GOVERNANCE_ID { + return Err(std::io::Error::other(format!( + "Invalid owner for account: {address}" + ))); + } let data = ProposalDeposit::from_bytes(&account.data)?; decoded_accounts.push(crate::shared::MaybeAccount::Exists( crate::shared::DecodedAccount { diff --git a/e2e/governance/src/generated/accounts/proposal_instruction_v1.rs b/e2e/governance/src/generated/accounts/proposal_instruction_v1.rs index 105eb50..f52a3a1 100644 --- a/e2e/governance/src/generated/accounts/proposal_instruction_v1.rs +++ b/e2e/governance/src/generated/accounts/proposal_instruction_v1.rs @@ -80,8 +80,14 @@ impl<'a> TryFrom<&solana_account_info::AccountInfo<'a>> for ProposalInstructionV type Error = std::io::Error; fn try_from(account_info: &solana_account_info::AccountInfo<'a>) -> Result { - let mut data: &[u8] = &(*account_info.data).borrow(); - Self::deserialize(&mut data) + if account_info.owner != &crate::SPL_GOVERNANCE_ID { + return Err(std::io::Error::new( + std::io::ErrorKind::InvalidData, + "invalid account owner", + )); + } + let data: &[u8] = &(*account_info.data).borrow(); + Self::from_bytes(data) } } @@ -109,6 +115,11 @@ pub fn fetch_all_proposal_instruction_v1( let account = accounts[i].as_ref().ok_or(std::io::Error::other(format!( "Account not found: {address}" )))?; + if account.owner != crate::SPL_GOVERNANCE_ID { + return Err(std::io::Error::other(format!( + "Invalid owner for account: {address}" + ))); + } let data = ProposalInstructionV1::from_bytes(&account.data)?; decoded_accounts.push(crate::shared::DecodedAccount { address, @@ -140,6 +151,11 @@ pub fn fetch_all_maybe_proposal_instruction_v1( for i in 0..addresses.len() { let address = addresses[i]; if let Some(account) = accounts[i].as_ref() { + if account.owner != crate::SPL_GOVERNANCE_ID { + return Err(std::io::Error::other(format!( + "Invalid owner for account: {address}" + ))); + } let data = ProposalInstructionV1::from_bytes(&account.data)?; decoded_accounts.push(crate::shared::MaybeAccount::Exists( crate::shared::DecodedAccount { diff --git a/e2e/governance/src/generated/accounts/proposal_transaction_v2.rs b/e2e/governance/src/generated/accounts/proposal_transaction_v2.rs index e1b5c2b..673cab9 100644 --- a/e2e/governance/src/generated/accounts/proposal_transaction_v2.rs +++ b/e2e/governance/src/generated/accounts/proposal_transaction_v2.rs @@ -82,8 +82,14 @@ impl<'a> TryFrom<&solana_account_info::AccountInfo<'a>> for ProposalTransactionV type Error = std::io::Error; fn try_from(account_info: &solana_account_info::AccountInfo<'a>) -> Result { - let mut data: &[u8] = &(*account_info.data).borrow(); - Self::deserialize(&mut data) + if account_info.owner != &crate::SPL_GOVERNANCE_ID { + return Err(std::io::Error::new( + std::io::ErrorKind::InvalidData, + "invalid account owner", + )); + } + let data: &[u8] = &(*account_info.data).borrow(); + Self::from_bytes(data) } } @@ -111,6 +117,11 @@ pub fn fetch_all_proposal_transaction_v2( let account = accounts[i].as_ref().ok_or(std::io::Error::other(format!( "Account not found: {address}" )))?; + if account.owner != crate::SPL_GOVERNANCE_ID { + return Err(std::io::Error::other(format!( + "Invalid owner for account: {address}" + ))); + } let data = ProposalTransactionV2::from_bytes(&account.data)?; decoded_accounts.push(crate::shared::DecodedAccount { address, @@ -142,6 +153,11 @@ pub fn fetch_all_maybe_proposal_transaction_v2( for i in 0..addresses.len() { let address = addresses[i]; if let Some(account) = accounts[i].as_ref() { + if account.owner != crate::SPL_GOVERNANCE_ID { + return Err(std::io::Error::other(format!( + "Invalid owner for account: {address}" + ))); + } let data = ProposalTransactionV2::from_bytes(&account.data)?; decoded_accounts.push(crate::shared::MaybeAccount::Exists( crate::shared::DecodedAccount { diff --git a/e2e/governance/src/generated/accounts/proposal_v1.rs b/e2e/governance/src/generated/accounts/proposal_v1.rs index bc51e95..f85d14c 100644 --- a/e2e/governance/src/generated/accounts/proposal_v1.rs +++ b/e2e/governance/src/generated/accounts/proposal_v1.rs @@ -99,8 +99,14 @@ impl<'a> TryFrom<&solana_account_info::AccountInfo<'a>> for ProposalV1 { type Error = std::io::Error; fn try_from(account_info: &solana_account_info::AccountInfo<'a>) -> Result { - let mut data: &[u8] = &(*account_info.data).borrow(); - Self::deserialize(&mut data) + if account_info.owner != &crate::SPL_GOVERNANCE_ID { + return Err(std::io::Error::new( + std::io::ErrorKind::InvalidData, + "invalid account owner", + )); + } + let data: &[u8] = &(*account_info.data).borrow(); + Self::from_bytes(data) } } @@ -127,6 +133,11 @@ pub fn fetch_all_proposal_v1( let account = accounts[i].as_ref().ok_or(std::io::Error::other(format!( "Account not found: {address}" )))?; + if account.owner != crate::SPL_GOVERNANCE_ID { + return Err(std::io::Error::other(format!( + "Invalid owner for account: {address}" + ))); + } let data = ProposalV1::from_bytes(&account.data)?; decoded_accounts.push(crate::shared::DecodedAccount { address, @@ -158,6 +169,11 @@ pub fn fetch_all_maybe_proposal_v1( for i in 0..addresses.len() { let address = addresses[i]; if let Some(account) = accounts[i].as_ref() { + if account.owner != crate::SPL_GOVERNANCE_ID { + return Err(std::io::Error::other(format!( + "Invalid owner for account: {address}" + ))); + } let data = ProposalV1::from_bytes(&account.data)?; decoded_accounts.push(crate::shared::MaybeAccount::Exists( crate::shared::DecodedAccount { diff --git a/e2e/governance/src/generated/accounts/proposal_v2.rs b/e2e/governance/src/generated/accounts/proposal_v2.rs index 10cecc8..103cf8f 100644 --- a/e2e/governance/src/generated/accounts/proposal_v2.rs +++ b/e2e/governance/src/generated/accounts/proposal_v2.rs @@ -105,8 +105,14 @@ impl<'a> TryFrom<&solana_account_info::AccountInfo<'a>> for ProposalV2 { type Error = std::io::Error; fn try_from(account_info: &solana_account_info::AccountInfo<'a>) -> Result { - let mut data: &[u8] = &(*account_info.data).borrow(); - Self::deserialize(&mut data) + if account_info.owner != &crate::SPL_GOVERNANCE_ID { + return Err(std::io::Error::new( + std::io::ErrorKind::InvalidData, + "invalid account owner", + )); + } + let data: &[u8] = &(*account_info.data).borrow(); + Self::from_bytes(data) } } @@ -133,6 +139,11 @@ pub fn fetch_all_proposal_v2( let account = accounts[i].as_ref().ok_or(std::io::Error::other(format!( "Account not found: {address}" )))?; + if account.owner != crate::SPL_GOVERNANCE_ID { + return Err(std::io::Error::other(format!( + "Invalid owner for account: {address}" + ))); + } let data = ProposalV2::from_bytes(&account.data)?; decoded_accounts.push(crate::shared::DecodedAccount { address, @@ -164,6 +175,11 @@ pub fn fetch_all_maybe_proposal_v2( for i in 0..addresses.len() { let address = addresses[i]; if let Some(account) = accounts[i].as_ref() { + if account.owner != crate::SPL_GOVERNANCE_ID { + return Err(std::io::Error::other(format!( + "Invalid owner for account: {address}" + ))); + } let data = ProposalV2::from_bytes(&account.data)?; decoded_accounts.push(crate::shared::MaybeAccount::Exists( crate::shared::DecodedAccount { diff --git a/e2e/governance/src/generated/accounts/realm_config_account.rs b/e2e/governance/src/generated/accounts/realm_config_account.rs index f5194b3..4e77661 100644 --- a/e2e/governance/src/generated/accounts/realm_config_account.rs +++ b/e2e/governance/src/generated/accounts/realm_config_account.rs @@ -58,8 +58,14 @@ impl<'a> TryFrom<&solana_account_info::AccountInfo<'a>> for RealmConfigAccount { type Error = std::io::Error; fn try_from(account_info: &solana_account_info::AccountInfo<'a>) -> Result { - let mut data: &[u8] = &(*account_info.data).borrow(); - Self::deserialize(&mut data) + if account_info.owner != &crate::SPL_GOVERNANCE_ID { + return Err(std::io::Error::new( + std::io::ErrorKind::InvalidData, + "invalid account owner", + )); + } + let data: &[u8] = &(*account_info.data).borrow(); + Self::from_bytes(data) } } @@ -86,6 +92,11 @@ pub fn fetch_all_realm_config_account( let account = accounts[i].as_ref().ok_or(std::io::Error::other(format!( "Account not found: {address}" )))?; + if account.owner != crate::SPL_GOVERNANCE_ID { + return Err(std::io::Error::other(format!( + "Invalid owner for account: {address}" + ))); + } let data = RealmConfigAccount::from_bytes(&account.data)?; decoded_accounts.push(crate::shared::DecodedAccount { address, @@ -117,6 +128,11 @@ pub fn fetch_all_maybe_realm_config_account( for i in 0..addresses.len() { let address = addresses[i]; if let Some(account) = accounts[i].as_ref() { + if account.owner != crate::SPL_GOVERNANCE_ID { + return Err(std::io::Error::other(format!( + "Invalid owner for account: {address}" + ))); + } let data = RealmConfigAccount::from_bytes(&account.data)?; decoded_accounts.push(crate::shared::MaybeAccount::Exists( crate::shared::DecodedAccount { diff --git a/e2e/governance/src/generated/accounts/realm_v1.rs b/e2e/governance/src/generated/accounts/realm_v1.rs index 7cb0e90..567bfe6 100644 --- a/e2e/governance/src/generated/accounts/realm_v1.rs +++ b/e2e/governance/src/generated/accounts/realm_v1.rs @@ -60,8 +60,14 @@ impl<'a> TryFrom<&solana_account_info::AccountInfo<'a>> for RealmV1 { type Error = std::io::Error; fn try_from(account_info: &solana_account_info::AccountInfo<'a>) -> Result { - let mut data: &[u8] = &(*account_info.data).borrow(); - Self::deserialize(&mut data) + if account_info.owner != &crate::SPL_GOVERNANCE_ID { + return Err(std::io::Error::new( + std::io::ErrorKind::InvalidData, + "invalid account owner", + )); + } + let data: &[u8] = &(*account_info.data).borrow(); + Self::from_bytes(data) } } @@ -88,6 +94,11 @@ pub fn fetch_all_realm_v1( let account = accounts[i].as_ref().ok_or(std::io::Error::other(format!( "Account not found: {address}" )))?; + if account.owner != crate::SPL_GOVERNANCE_ID { + return Err(std::io::Error::other(format!( + "Invalid owner for account: {address}" + ))); + } let data = RealmV1::from_bytes(&account.data)?; decoded_accounts.push(crate::shared::DecodedAccount { address, @@ -119,6 +130,11 @@ pub fn fetch_all_maybe_realm_v1( for i in 0..addresses.len() { let address = addresses[i]; if let Some(account) = accounts[i].as_ref() { + if account.owner != crate::SPL_GOVERNANCE_ID { + return Err(std::io::Error::other(format!( + "Invalid owner for account: {address}" + ))); + } let data = RealmV1::from_bytes(&account.data)?; decoded_accounts.push(crate::shared::MaybeAccount::Exists( crate::shared::DecodedAccount { diff --git a/e2e/governance/src/generated/accounts/realm_v2.rs b/e2e/governance/src/generated/accounts/realm_v2.rs index 5d5d98a..52873d9 100644 --- a/e2e/governance/src/generated/accounts/realm_v2.rs +++ b/e2e/governance/src/generated/accounts/realm_v2.rs @@ -61,8 +61,14 @@ impl<'a> TryFrom<&solana_account_info::AccountInfo<'a>> for RealmV2 { type Error = std::io::Error; fn try_from(account_info: &solana_account_info::AccountInfo<'a>) -> Result { - let mut data: &[u8] = &(*account_info.data).borrow(); - Self::deserialize(&mut data) + if account_info.owner != &crate::SPL_GOVERNANCE_ID { + return Err(std::io::Error::new( + std::io::ErrorKind::InvalidData, + "invalid account owner", + )); + } + let data: &[u8] = &(*account_info.data).borrow(); + Self::from_bytes(data) } } @@ -89,6 +95,11 @@ pub fn fetch_all_realm_v2( let account = accounts[i].as_ref().ok_or(std::io::Error::other(format!( "Account not found: {address}" )))?; + if account.owner != crate::SPL_GOVERNANCE_ID { + return Err(std::io::Error::other(format!( + "Invalid owner for account: {address}" + ))); + } let data = RealmV2::from_bytes(&account.data)?; decoded_accounts.push(crate::shared::DecodedAccount { address, @@ -120,6 +131,11 @@ pub fn fetch_all_maybe_realm_v2( for i in 0..addresses.len() { let address = addresses[i]; if let Some(account) = accounts[i].as_ref() { + if account.owner != crate::SPL_GOVERNANCE_ID { + return Err(std::io::Error::other(format!( + "Invalid owner for account: {address}" + ))); + } let data = RealmV2::from_bytes(&account.data)?; decoded_accounts.push(crate::shared::MaybeAccount::Exists( crate::shared::DecodedAccount { diff --git a/e2e/governance/src/generated/accounts/required_signatory.rs b/e2e/governance/src/generated/accounts/required_signatory.rs index 449361b..9c6ba22 100644 --- a/e2e/governance/src/generated/accounts/required_signatory.rs +++ b/e2e/governance/src/generated/accounts/required_signatory.rs @@ -66,8 +66,14 @@ impl<'a> TryFrom<&solana_account_info::AccountInfo<'a>> for RequiredSignatory { type Error = std::io::Error; fn try_from(account_info: &solana_account_info::AccountInfo<'a>) -> Result { - let mut data: &[u8] = &(*account_info.data).borrow(); - Self::deserialize(&mut data) + if account_info.owner != &crate::SPL_GOVERNANCE_ID { + return Err(std::io::Error::new( + std::io::ErrorKind::InvalidData, + "invalid account owner", + )); + } + let data: &[u8] = &(*account_info.data).borrow(); + Self::from_bytes(data) } } @@ -94,6 +100,11 @@ pub fn fetch_all_required_signatory( let account = accounts[i].as_ref().ok_or(std::io::Error::other(format!( "Account not found: {address}" )))?; + if account.owner != crate::SPL_GOVERNANCE_ID { + return Err(std::io::Error::other(format!( + "Invalid owner for account: {address}" + ))); + } let data = RequiredSignatory::from_bytes(&account.data)?; decoded_accounts.push(crate::shared::DecodedAccount { address, @@ -125,6 +136,11 @@ pub fn fetch_all_maybe_required_signatory( for i in 0..addresses.len() { let address = addresses[i]; if let Some(account) = accounts[i].as_ref() { + if account.owner != crate::SPL_GOVERNANCE_ID { + return Err(std::io::Error::other(format!( + "Invalid owner for account: {address}" + ))); + } let data = RequiredSignatory::from_bytes(&account.data)?; decoded_accounts.push(crate::shared::MaybeAccount::Exists( crate::shared::DecodedAccount { diff --git a/e2e/governance/src/generated/accounts/signatory_record_v1.rs b/e2e/governance/src/generated/accounts/signatory_record_v1.rs index c31a660..4e5ae19 100644 --- a/e2e/governance/src/generated/accounts/signatory_record_v1.rs +++ b/e2e/governance/src/generated/accounts/signatory_record_v1.rs @@ -62,8 +62,14 @@ impl<'a> TryFrom<&solana_account_info::AccountInfo<'a>> for SignatoryRecordV1 { type Error = std::io::Error; fn try_from(account_info: &solana_account_info::AccountInfo<'a>) -> Result { - let mut data: &[u8] = &(*account_info.data).borrow(); - Self::deserialize(&mut data) + if account_info.owner != &crate::SPL_GOVERNANCE_ID { + return Err(std::io::Error::new( + std::io::ErrorKind::InvalidData, + "invalid account owner", + )); + } + let data: &[u8] = &(*account_info.data).borrow(); + Self::from_bytes(data) } } @@ -90,6 +96,11 @@ pub fn fetch_all_signatory_record_v1( let account = accounts[i].as_ref().ok_or(std::io::Error::other(format!( "Account not found: {address}" )))?; + if account.owner != crate::SPL_GOVERNANCE_ID { + return Err(std::io::Error::other(format!( + "Invalid owner for account: {address}" + ))); + } let data = SignatoryRecordV1::from_bytes(&account.data)?; decoded_accounts.push(crate::shared::DecodedAccount { address, @@ -121,6 +132,11 @@ pub fn fetch_all_maybe_signatory_record_v1( for i in 0..addresses.len() { let address = addresses[i]; if let Some(account) = accounts[i].as_ref() { + if account.owner != crate::SPL_GOVERNANCE_ID { + return Err(std::io::Error::other(format!( + "Invalid owner for account: {address}" + ))); + } let data = SignatoryRecordV1::from_bytes(&account.data)?; decoded_accounts.push(crate::shared::MaybeAccount::Exists( crate::shared::DecodedAccount { diff --git a/e2e/governance/src/generated/accounts/signatory_record_v2.rs b/e2e/governance/src/generated/accounts/signatory_record_v2.rs index e931463..0d983f7 100644 --- a/e2e/governance/src/generated/accounts/signatory_record_v2.rs +++ b/e2e/governance/src/generated/accounts/signatory_record_v2.rs @@ -63,8 +63,14 @@ impl<'a> TryFrom<&solana_account_info::AccountInfo<'a>> for SignatoryRecordV2 { type Error = std::io::Error; fn try_from(account_info: &solana_account_info::AccountInfo<'a>) -> Result { - let mut data: &[u8] = &(*account_info.data).borrow(); - Self::deserialize(&mut data) + if account_info.owner != &crate::SPL_GOVERNANCE_ID { + return Err(std::io::Error::new( + std::io::ErrorKind::InvalidData, + "invalid account owner", + )); + } + let data: &[u8] = &(*account_info.data).borrow(); + Self::from_bytes(data) } } @@ -91,6 +97,11 @@ pub fn fetch_all_signatory_record_v2( let account = accounts[i].as_ref().ok_or(std::io::Error::other(format!( "Account not found: {address}" )))?; + if account.owner != crate::SPL_GOVERNANCE_ID { + return Err(std::io::Error::other(format!( + "Invalid owner for account: {address}" + ))); + } let data = SignatoryRecordV2::from_bytes(&account.data)?; decoded_accounts.push(crate::shared::DecodedAccount { address, @@ -122,6 +133,11 @@ pub fn fetch_all_maybe_signatory_record_v2( for i in 0..addresses.len() { let address = addresses[i]; if let Some(account) = accounts[i].as_ref() { + if account.owner != crate::SPL_GOVERNANCE_ID { + return Err(std::io::Error::other(format!( + "Invalid owner for account: {address}" + ))); + } let data = SignatoryRecordV2::from_bytes(&account.data)?; decoded_accounts.push(crate::shared::MaybeAccount::Exists( crate::shared::DecodedAccount { diff --git a/e2e/governance/src/generated/accounts/token_owner_record_v1.rs b/e2e/governance/src/generated/accounts/token_owner_record_v1.rs index ee065c4..ec598ec 100644 --- a/e2e/governance/src/generated/accounts/token_owner_record_v1.rs +++ b/e2e/governance/src/generated/accounts/token_owner_record_v1.rs @@ -80,8 +80,14 @@ impl<'a> TryFrom<&solana_account_info::AccountInfo<'a>> for TokenOwnerRecordV1 { type Error = std::io::Error; fn try_from(account_info: &solana_account_info::AccountInfo<'a>) -> Result { - let mut data: &[u8] = &(*account_info.data).borrow(); - Self::deserialize(&mut data) + if account_info.owner != &crate::SPL_GOVERNANCE_ID { + return Err(std::io::Error::new( + std::io::ErrorKind::InvalidData, + "invalid account owner", + )); + } + let data: &[u8] = &(*account_info.data).borrow(); + Self::from_bytes(data) } } @@ -108,6 +114,11 @@ pub fn fetch_all_token_owner_record_v1( let account = accounts[i].as_ref().ok_or(std::io::Error::other(format!( "Account not found: {address}" )))?; + if account.owner != crate::SPL_GOVERNANCE_ID { + return Err(std::io::Error::other(format!( + "Invalid owner for account: {address}" + ))); + } let data = TokenOwnerRecordV1::from_bytes(&account.data)?; decoded_accounts.push(crate::shared::DecodedAccount { address, @@ -139,6 +150,11 @@ pub fn fetch_all_maybe_token_owner_record_v1( for i in 0..addresses.len() { let address = addresses[i]; if let Some(account) = accounts[i].as_ref() { + if account.owner != crate::SPL_GOVERNANCE_ID { + return Err(std::io::Error::other(format!( + "Invalid owner for account: {address}" + ))); + } let data = TokenOwnerRecordV1::from_bytes(&account.data)?; decoded_accounts.push(crate::shared::MaybeAccount::Exists( crate::shared::DecodedAccount { diff --git a/e2e/governance/src/generated/accounts/token_owner_record_v2.rs b/e2e/governance/src/generated/accounts/token_owner_record_v2.rs index 4dd9188..d2cbf3d 100644 --- a/e2e/governance/src/generated/accounts/token_owner_record_v2.rs +++ b/e2e/governance/src/generated/accounts/token_owner_record_v2.rs @@ -81,8 +81,14 @@ impl<'a> TryFrom<&solana_account_info::AccountInfo<'a>> for TokenOwnerRecordV2 { type Error = std::io::Error; fn try_from(account_info: &solana_account_info::AccountInfo<'a>) -> Result { - let mut data: &[u8] = &(*account_info.data).borrow(); - Self::deserialize(&mut data) + if account_info.owner != &crate::SPL_GOVERNANCE_ID { + return Err(std::io::Error::new( + std::io::ErrorKind::InvalidData, + "invalid account owner", + )); + } + let data: &[u8] = &(*account_info.data).borrow(); + Self::from_bytes(data) } } @@ -109,6 +115,11 @@ pub fn fetch_all_token_owner_record_v2( let account = accounts[i].as_ref().ok_or(std::io::Error::other(format!( "Account not found: {address}" )))?; + if account.owner != crate::SPL_GOVERNANCE_ID { + return Err(std::io::Error::other(format!( + "Invalid owner for account: {address}" + ))); + } let data = TokenOwnerRecordV2::from_bytes(&account.data)?; decoded_accounts.push(crate::shared::DecodedAccount { address, @@ -140,6 +151,11 @@ pub fn fetch_all_maybe_token_owner_record_v2( for i in 0..addresses.len() { let address = addresses[i]; if let Some(account) = accounts[i].as_ref() { + if account.owner != crate::SPL_GOVERNANCE_ID { + return Err(std::io::Error::other(format!( + "Invalid owner for account: {address}" + ))); + } let data = TokenOwnerRecordV2::from_bytes(&account.data)?; decoded_accounts.push(crate::shared::MaybeAccount::Exists( crate::shared::DecodedAccount { diff --git a/e2e/governance/src/generated/accounts/vote_record_v1.rs b/e2e/governance/src/generated/accounts/vote_record_v1.rs index 09cf1df..33f964d 100644 --- a/e2e/governance/src/generated/accounts/vote_record_v1.rs +++ b/e2e/governance/src/generated/accounts/vote_record_v1.rs @@ -71,8 +71,14 @@ impl<'a> TryFrom<&solana_account_info::AccountInfo<'a>> for VoteRecordV1 { type Error = std::io::Error; fn try_from(account_info: &solana_account_info::AccountInfo<'a>) -> Result { - let mut data: &[u8] = &(*account_info.data).borrow(); - Self::deserialize(&mut data) + if account_info.owner != &crate::SPL_GOVERNANCE_ID { + return Err(std::io::Error::new( + std::io::ErrorKind::InvalidData, + "invalid account owner", + )); + } + let data: &[u8] = &(*account_info.data).borrow(); + Self::from_bytes(data) } } @@ -99,6 +105,11 @@ pub fn fetch_all_vote_record_v1( let account = accounts[i].as_ref().ok_or(std::io::Error::other(format!( "Account not found: {address}" )))?; + if account.owner != crate::SPL_GOVERNANCE_ID { + return Err(std::io::Error::other(format!( + "Invalid owner for account: {address}" + ))); + } let data = VoteRecordV1::from_bytes(&account.data)?; decoded_accounts.push(crate::shared::DecodedAccount { address, @@ -130,6 +141,11 @@ pub fn fetch_all_maybe_vote_record_v1( for i in 0..addresses.len() { let address = addresses[i]; if let Some(account) = accounts[i].as_ref() { + if account.owner != crate::SPL_GOVERNANCE_ID { + return Err(std::io::Error::other(format!( + "Invalid owner for account: {address}" + ))); + } let data = VoteRecordV1::from_bytes(&account.data)?; decoded_accounts.push(crate::shared::MaybeAccount::Exists( crate::shared::DecodedAccount { diff --git a/e2e/governance/src/generated/accounts/vote_record_v2.rs b/e2e/governance/src/generated/accounts/vote_record_v2.rs index ea096e0..5a6ebd6 100644 --- a/e2e/governance/src/generated/accounts/vote_record_v2.rs +++ b/e2e/governance/src/generated/accounts/vote_record_v2.rs @@ -73,8 +73,14 @@ impl<'a> TryFrom<&solana_account_info::AccountInfo<'a>> for VoteRecordV2 { type Error = std::io::Error; fn try_from(account_info: &solana_account_info::AccountInfo<'a>) -> Result { - let mut data: &[u8] = &(*account_info.data).borrow(); - Self::deserialize(&mut data) + if account_info.owner != &crate::SPL_GOVERNANCE_ID { + return Err(std::io::Error::new( + std::io::ErrorKind::InvalidData, + "invalid account owner", + )); + } + let data: &[u8] = &(*account_info.data).borrow(); + Self::from_bytes(data) } } @@ -101,6 +107,11 @@ pub fn fetch_all_vote_record_v2( let account = accounts[i].as_ref().ok_or(std::io::Error::other(format!( "Account not found: {address}" )))?; + if account.owner != crate::SPL_GOVERNANCE_ID { + return Err(std::io::Error::other(format!( + "Invalid owner for account: {address}" + ))); + } let data = VoteRecordV2::from_bytes(&account.data)?; decoded_accounts.push(crate::shared::DecodedAccount { address, @@ -132,6 +143,11 @@ pub fn fetch_all_maybe_vote_record_v2( for i in 0..addresses.len() { let address = addresses[i]; if let Some(account) = accounts[i].as_ref() { + if account.owner != crate::SPL_GOVERNANCE_ID { + return Err(std::io::Error::other(format!( + "Invalid owner for account: {address}" + ))); + } let data = VoteRecordV2::from_bytes(&account.data)?; decoded_accounts.push(crate::shared::MaybeAccount::Exists( crate::shared::DecodedAccount { diff --git a/e2e/system/src/generated/accounts/nonce.rs b/e2e/system/src/generated/accounts/nonce.rs index 0f843c2..409cc42 100644 --- a/e2e/system/src/generated/accounts/nonce.rs +++ b/e2e/system/src/generated/accounts/nonce.rs @@ -34,8 +34,14 @@ impl<'a> TryFrom<&solana_account_info::AccountInfo<'a>> for Nonce { type Error = std::io::Error; fn try_from(account_info: &solana_account_info::AccountInfo<'a>) -> Result { - let mut data: &[u8] = &(*account_info.data).borrow(); - Self::deserialize(&mut data) + if account_info.owner != &crate::SYSTEM_ID { + return Err(std::io::Error::new( + std::io::ErrorKind::InvalidData, + "invalid account owner", + )); + } + let data: &[u8] = &(*account_info.data).borrow(); + Self::from_bytes(data) } } @@ -62,6 +68,11 @@ pub fn fetch_all_nonce( let account = accounts[i].as_ref().ok_or(std::io::Error::other(format!( "Account not found: {address}" )))?; + if account.owner != crate::SYSTEM_ID { + return Err(std::io::Error::other(format!( + "Invalid owner for account: {address}" + ))); + } let data = Nonce::from_bytes(&account.data)?; decoded_accounts.push(crate::shared::DecodedAccount { address, @@ -93,6 +104,11 @@ pub fn fetch_all_maybe_nonce( for i in 0..addresses.len() { let address = addresses[i]; if let Some(account) = accounts[i].as_ref() { + if account.owner != crate::SYSTEM_ID { + return Err(std::io::Error::other(format!( + "Invalid owner for account: {address}" + ))); + } let data = Nonce::from_bytes(&account.data)?; decoded_accounts.push(crate::shared::MaybeAccount::Exists( crate::shared::DecodedAccount { diff --git a/public/templates/accountsPage.njk b/public/templates/accountsPage.njk index 60e29c3..931193d 100644 --- a/public/templates/accountsPage.njk +++ b/public/templates/accountsPage.njk @@ -116,6 +116,14 @@ impl {{ account.name | pascalCase }} { #[inline(always)] pub fn from_bytes(data: &[u8]) -> Result { + {% if discriminatorConstantName %} + if data.get(..{{ discriminatorConstantName }}.len()) != Some(&{{ discriminatorConstantName }}[..]) { + return Err(std::io::Error::new( + std::io::ErrorKind::InvalidData, + "invalid account discriminator", + )); + } + {% endif %} let mut data = data; Self::deserialize(&mut data) } @@ -125,8 +133,14 @@ impl<'a> TryFrom<&solana_account_info::AccountInfo<'a>> for {{ account.name | pa type Error = std::io::Error; fn try_from(account_info: &solana_account_info::AccountInfo<'a>) -> Result { - let mut data: &[u8] = &(*account_info.data).borrow(); - Self::deserialize(&mut data) + if account_info.owner != &crate::{{ program.name | snakeCase | upper }}_ID { + return Err(std::io::Error::new( + std::io::ErrorKind::InvalidData, + "invalid account owner", + )); + } + let data: &[u8] = &(*account_info.data).borrow(); + Self::from_bytes(data) } } @@ -151,6 +165,9 @@ pub fn fetch_all_{{ account.name | snakeCase }}( let address = addresses[i]; let account = accounts[i].as_ref() .ok_or(std::io::Error::other(format!("Account not found: {address}")))?; + if account.owner != crate::{{ program.name | snakeCase | upper }}_ID { + return Err(std::io::Error::other(format!("Invalid owner for account: {address}"))); + } let data = {{ account.name | pascalCase }}::from_bytes(&account.data)?; decoded_accounts.push(crate::shared::DecodedAccount { address, account: account.clone(), data }); } @@ -177,6 +194,9 @@ pub fn fetch_all_maybe_{{ account.name | snakeCase }}( for i in 0..addresses.len() { let address = addresses[i]; if let Some(account) = accounts[i].as_ref() { + if account.owner != crate::{{ program.name | snakeCase | upper }}_ID { + return Err(std::io::Error::other(format!("Invalid owner for account: {address}"))); + } let data = {{ account.name | pascalCase }}::from_bytes(&account.data)?; decoded_accounts.push(crate::shared::MaybeAccount::Exists(crate::shared::DecodedAccount { address, account: account.clone(), data })); } else { @@ -189,6 +209,17 @@ pub fn fetch_all_maybe_{{ account.name | snakeCase }}( {% if anchorTraits %} #[cfg(feature = "anchor")] impl anchor_lang::AccountDeserialize for {{ account.name | pascalCase }} { + {% if discriminatorConstantName %} + fn try_deserialize(buf: &mut &[u8]) -> anchor_lang::Result { + if buf.len() < {{ discriminatorConstantName }}.len() + || buf[..{{ discriminatorConstantName }}.len()] != {{ discriminatorConstantName }}[..] + { + return Err(anchor_lang::error::ErrorCode::AccountDiscriminatorMismatch.into()); + } + Self::try_deserialize_unchecked(buf) + } + {% endif %} + fn try_deserialize_unchecked(buf: &mut &[u8]) -> anchor_lang::Result { Ok(Self::deserialize(buf)?) } @@ -215,7 +246,11 @@ pub fn fetch_all_maybe_{{ account.name | snakeCase }}( #} #[cfg(feature = "anchor-idl-build")] impl anchor_lang::Discriminator for {{ account.name | pascalCase }} { + {% if discriminatorConstantName %} + const DISCRIMINATOR: &[u8] = &{{ discriminatorConstantName }}; + {% else %} const DISCRIMINATOR: &[u8] = &[0; 8]; + {% endif %} } {% endif %} diff --git a/src/getRenderMapVisitor.ts b/src/getRenderMapVisitor.ts index 2d540c9..4618ba1 100644 --- a/src/getRenderMapVisitor.ts +++ b/src/getRenderMapVisitor.ts @@ -39,6 +39,7 @@ import { CargoDependencies, computePdaAddress, Fragment, + getByteArrayDiscriminatorConstantName, getDiscriminatorConstants, getImportFromFactory, type GetImportFromFunction, @@ -97,6 +98,12 @@ export function getRenderMapVisitor(options: GetRenderMapOptions = {}) { typeManifestVisitor, }); + const discriminatorConstantName = getByteArrayDiscriminatorConstantName({ + discriminatorNodes: node.discriminators ?? [], + fields, + prefix: node.name, + }); + // Seeds. const seedsImports = new ImportMap(); const pda = node.pda ? linkables.get([...stack.getPath(), node.pda]) : undefined; @@ -144,6 +151,7 @@ export function getRenderMapVisitor(options: GetRenderMapOptions = {}) { account: node, anchorTraits, constantSeeds, + discriminatorConstantName, discriminatorConstants: discriminatorConstants.render, hasVariableSeeds, imports: imports.toString(dependencyMap), diff --git a/src/utils/discriminatorConstant.ts b/src/utils/discriminatorConstant.ts index 8e88e34..0b42178 100644 --- a/src/utils/discriminatorConstant.ts +++ b/src/utils/discriminatorConstant.ts @@ -25,6 +25,34 @@ function mergeFragments(fragments: Fragment[], merge: (parts: string[]) => strin return { imports, render }; } +export function getByteArrayDiscriminatorConstantName(scope: { + discriminatorNodes: DiscriminatorNode[]; + fields: InstructionArgumentNode[] | StructFieldTypeNode[]; + prefix: string; +}): string | null { + const { discriminatorNodes, fields, prefix } = scope; + + for (const disc of discriminatorNodes) { + if (isNode(disc, 'constantDiscriminatorNode')) { + return snakeCase(camelCase(`${prefix}_discriminator`)).toUpperCase(); + } + if (isNode(disc, 'fieldDiscriminatorNode')) { + const field = fields.find(f => f.name === disc.name); + if ( + field && + field.defaultValue && + isNode(field.defaultValue, VALUE_NODES) && + isNode(field.type, 'fixedSizeTypeNode') && + isNode(field.type.type, 'bytesTypeNode') + ) { + return snakeCase(camelCase(`${prefix}_${disc.name}`)).toUpperCase(); + } + } + } + + return null; +} + export function getDiscriminatorConstants(scope: { discriminatorNodes: DiscriminatorNode[]; fields: InstructionArgumentNode[] | StructFieldTypeNode[]; diff --git a/test/accountsPage.test.ts b/test/accountsPage.test.ts index f10f9bc..1c40caa 100644 --- a/test/accountsPage.test.ts +++ b/test/accountsPage.test.ts @@ -1,9 +1,12 @@ import { accountNode, bytesTypeNode, + bytesValueNode, camelCase, + constantDiscriminatorNode, constantPdaSeedNode, constantPdaSeedNodeFromString, + constantValueNode, fixedSizeTypeNode, numberTypeNode, numberValueNode, @@ -11,6 +14,8 @@ import { pdaNode, programNode, publicKeyTypeNode, + structFieldTypeNode, + structTypeNode, variablePdaSeedNode, } from '@codama/nodes'; import { getFromRenderMap } from '@codama/renderers-core'; @@ -136,6 +141,7 @@ test('it renders anchor traits impl', () => { 'impl anchor_lang::AccountDeserialize for TestAccount', 'impl anchor_lang::AccountSerialize for TestAccount {}', 'impl anchor_lang::Owner for TestAccount', + 'const DISCRIMINATOR: &[u8] = &[0; 8]', ]); }); @@ -171,6 +177,206 @@ test('it renders fetch functions', () => { ]); }); +test('it validates byte-array discriminator in from_bytes and TryFrom', () => { + // Given an account with a byte-array discriminator field. + const node = programNode({ + accounts: [ + accountNode({ + data: structTypeNode([ + structFieldTypeNode({ + defaultValue: bytesValueNode('base16', 'b9959c4ef56cac44'), + defaultValueStrategy: 'omitted', + name: 'discriminator', + type: fixedSizeTypeNode(bytesTypeNode(), 8), + }), + structFieldTypeNode({ + name: 'amount', + type: numberTypeNode('u64'), + }), + ]), + discriminators: [ + { + kind: 'fieldDiscriminatorNode', + name: camelCase('discriminator'), + offset: 0, + }, + ], + name: 'testAccount', + }), + ], + name: 'myProgram', + publicKey: '1111', + }); + + // When we render it. + const renderMap = visit(node, getRenderMapVisitor()); + const code = getFromRenderMap(renderMap, 'accounts/test_account.rs').content; + + // Then from_bytes validates the discriminator before deserializing. + codeContains(code, ['TEST_ACCOUNT_DISCRIMINATOR', 'invalid account discriminator', 'Self::from_bytes(data)']); + + // And the Discriminator trait uses the real constant. + codeContains(code, ['const DISCRIMINATOR: &[u8] = &TEST_ACCOUNT_DISCRIMINATOR;']); +}); + +test('it validates constant discriminator in from_bytes and TryFrom', () => { + // Given an account with a constantDiscriminatorNode (no discriminator struct field). + const node = programNode({ + accounts: [ + accountNode({ + data: structTypeNode([ + structFieldTypeNode({ + name: 'amount', + type: numberTypeNode('u64'), + }), + ]), + discriminators: [ + constantDiscriminatorNode( + constantValueNode( + fixedSizeTypeNode(bytesTypeNode(), 8), + bytesValueNode('base16', 'aabbccdd11223344'), + ), + ), + ], + name: 'testAccount', + }), + ], + name: 'myProgram', + publicKey: '1111', + }); + + const renderMap = visit(node, getRenderMapVisitor()); + const code = getFromRenderMap(renderMap, 'accounts/test_account.rs').content; + + // from_bytes validates the discriminator. + codeContains(code, ['TEST_ACCOUNT_DISCRIMINATOR', 'invalid account discriminator']); + + // Anchor Discriminator trait uses the real constant. + codeContains(code, ['const DISCRIMINATOR: &[u8] = &TEST_ACCOUNT_DISCRIMINATOR;']); +}); + +test('it validates account owner in TryFrom and fetch', () => { + // Given an account with a discriminator. + const node = programNode({ + accounts: [ + accountNode({ + data: structTypeNode([ + structFieldTypeNode({ + defaultValue: bytesValueNode('base16', 'b9959c4ef56cac44'), + defaultValueStrategy: 'omitted', + name: 'discriminator', + type: fixedSizeTypeNode(bytesTypeNode(), 8), + }), + ]), + discriminators: [ + { + kind: 'fieldDiscriminatorNode', + name: camelCase('discriminator'), + offset: 0, + }, + ], + name: 'testAccount', + }), + ], + name: 'myProgram', + publicKey: '1111', + }); + + const renderMap = visit(node, getRenderMapVisitor()); + const code = getFromRenderMap(renderMap, 'accounts/test_account.rs').content; + + // TryFrom checks account owner. + codeContains(code, ['invalid account owner', 'account_info.owner', 'MY_PROGRAM_ID']); + + // Fetch functions check account owner. + codeContains(code, ['Invalid owner for account']); +}); + +test('it validates account owner even without a discriminator', () => { + const node = programNode({ + accounts: [accountNode({ name: 'testAccount' })], + name: 'myProgram', + publicKey: '1111', + }); + + const renderMap = visit(node, getRenderMapVisitor()); + const code = getFromRenderMap(renderMap, 'accounts/test_account.rs').content; + + codeContains(code, ['invalid account owner', 'MY_PROGRAM_ID']); + codeDoesNotContains(code, ['invalid account discriminator']); +}); + +test('it validates discriminator in anchor try_deserialize', () => { + // Given an account with a byte-array discriminator. + const node = programNode({ + accounts: [ + accountNode({ + data: structTypeNode([ + structFieldTypeNode({ + defaultValue: bytesValueNode('base16', 'b9959c4ef56cac44'), + defaultValueStrategy: 'omitted', + name: 'discriminator', + type: fixedSizeTypeNode(bytesTypeNode(), 8), + }), + ]), + discriminators: [ + { + kind: 'fieldDiscriminatorNode', + name: camelCase('discriminator'), + offset: 0, + }, + ], + name: 'testAccount', + }), + ], + name: 'myProgram', + publicKey: '1111', + }); + + const renderMap = visit(node, getRenderMapVisitor()); + const code = getFromRenderMap(renderMap, 'accounts/test_account.rs').content; + + // try_deserialize checks the discriminator before delegating to unchecked. + codeContains(code, [ + 'fn try_deserialize(buf: &mut &[u8])', + 'AccountDiscriminatorMismatch', + 'TEST_ACCOUNT_DISCRIMINATOR', + ]); +}); + +test('it skips discriminator validation when field has no default value', () => { + // Given an account with a byte-array discriminator field but no defaultValue. + const node = programNode({ + accounts: [ + accountNode({ + data: structTypeNode([ + structFieldTypeNode({ + name: 'discriminator', + type: fixedSizeTypeNode(bytesTypeNode(), 8), + }), + ]), + discriminators: [ + { + kind: 'fieldDiscriminatorNode', + name: camelCase('discriminator'), + offset: 0, + }, + ], + name: 'testAccount', + }), + ], + name: 'myProgram', + publicKey: '1111', + }); + + // When we render it. + const renderMap = visit(node, getRenderMapVisitor()); + const code = getFromRenderMap(renderMap, 'accounts/test_account.rs').content; + + // Then from_bytes does not validate a discriminator. + codeDoesNotContains(code, ['invalid account discriminator', 'TEST_ACCOUNT_DISCRIMINATOR']); +}); + test('it renders account without anchor traits', () => { // Given the following account. const node = programNode({ From cd5e3f207a61aa5fb3d0d15be489aabb8949dda2 Mon Sep 17 00:00:00 2001 From: ioxde <228087182+ioxde@users.noreply.github.com> Date: Sat, 4 Apr 2026 16:12:38 -0700 Subject: [PATCH 18/24] Enforce required accounts and args at compile time via constructor params Move required accounts (no defaults, not IDL-optional) and required args (no defaults, not Option types) from Option fields with setter methods into mandatory constructor parameters on both Builder and CpiBuilder. This shifts missing-field errors from runtime .expect() panics to compile-time type errors. Accounts with defaults (PDA, publicKey, programId) remain optional with setters. PDA seed resolution uses direct field access for required fields instead of .expect(). programIdValueNode accounts unwrap with the program's own ID as fallback. --- .../generated/instructions/create_guard.rs | 334 ++++------ .../src/generated/instructions/execute.rs | 242 +++----- .../src/generated/instructions/initialize.rs | 184 ++---- .../generated/instructions/update_guard.rs | 211 +++---- e2e/dummy/idl.json | 28 + .../generated/instructions/instruction1.rs | 4 +- .../generated/instructions/instruction10.rs | 299 +++++++++ .../generated/instructions/instruction2.rs | 4 +- .../generated/instructions/instruction3.rs | 4 +- .../generated/instructions/instruction4.rs | 37 +- .../generated/instructions/instruction5.rs | 4 +- .../generated/instructions/instruction6.rs | 43 +- .../generated/instructions/instruction7.rs | 10 +- .../generated/instructions/instruction8.rs | 87 +-- .../generated/instructions/instruction9.rs | 25 +- e2e/dummy/src/generated/instructions/mod.rs | 2 + .../instructions/add_required_signatory.rs | 163 ++--- .../generated/instructions/add_signatory.rs | 232 +++---- .../generated/instructions/cancel_proposal.rs | 179 ++---- .../src/generated/instructions/cast_vote.rs | 413 ++++--------- .../instructions/complete_proposal.rs | 117 ++-- .../instructions/create_governance.rs | 304 +++------- .../instructions/create_mint_governance.rs | 384 ++++-------- .../instructions/create_native_treasury.rs | 138 ++--- .../instructions/create_program_governance.rs | 427 ++++--------- .../generated/instructions/create_proposal.rs | 481 +++++---------- .../generated/instructions/create_realm.rs | 373 ++++-------- .../instructions/create_token_governance.rs | 393 ++++-------- .../instructions/create_token_owner_record.rs | 199 ++---- .../instructions/deposit_governing_tokens.rs | 354 +++-------- .../instructions/execute_transaction.rs | 113 ++-- .../generated/instructions/finalize_vote.rs | 215 ++----- .../instructions/flag_transaction_error.rs | 153 ++--- .../instructions/insert_transaction.rs | 359 ++++------- .../src/generated/instructions/legacy1.rs | 4 +- .../instructions/refund_proposal_deposit.rs | 118 ++-- .../generated/instructions/relinquish_vote.rs | 227 +++---- .../instructions/remove_required_signatory.rs | 118 ++-- .../instructions/remove_transaction.rs | 185 ++---- .../instructions/revoke_governing_tokens.rs | 269 +++----- .../instructions/set_governance_config.rs | 72 +-- .../instructions/set_governance_delegate.rs | 85 +-- .../instructions/set_realm_authority.rs | 105 ++-- .../instructions/set_realm_config.rs | 203 +++---- .../instructions/sign_off_proposal.rs | 182 ++---- .../instructions/update_program_metadata.rs | 103 ++-- .../instructions/withdraw_governing_tokens.rs | 245 ++------ .../src/generated/instructions/add_memo.rs | 33 +- .../instructions/advance_nonce_account.rs | 106 ++-- .../src/generated/instructions/allocate.rs | 68 +-- .../instructions/allocate_with_seed.rs | 176 ++---- .../src/generated/instructions/assign.rs | 69 +-- .../instructions/assign_with_seed.rs | 147 ++--- .../instructions/authorize_nonce_account.rs | 107 ++-- .../generated/instructions/create_account.rs | 152 ++--- .../instructions/create_account_with_seed.rs | 224 +++---- .../instructions/initialize_nonce_account.rs | 129 ++-- .../generated/instructions/transfer_sol.rs | 94 ++- .../instructions/transfer_sol_with_seed.rs | 179 ++---- .../instructions/upgrade_nonce_account.rs | 46 +- .../instructions/withdraw_nonce_account.rs | 194 ++---- .../templates/instructionsCpiPageBuilder.njk | 119 +++- public/templates/instructionsPageBuilder.njk | 136 +++-- src/getRenderMapVisitor.ts | 79 ++- test/instructionsPage.test.ts | 572 ++++++++++++++++-- 65 files changed, 4190 insertions(+), 6871 deletions(-) create mode 100644 e2e/dummy/src/generated/instructions/instruction10.rs diff --git a/e2e/anchor/src/generated/instructions/create_guard.rs b/e2e/anchor/src/generated/instructions/create_guard.rs index e3858d0..15c45e7 100644 --- a/e2e/anchor/src/generated/instructions/create_guard.rs +++ b/e2e/anchor/src/generated/instructions/create_guard.rs @@ -132,28 +132,52 @@ impl CreateGuardInstructionArgs { /// 5. `[optional]` associated_token_program (default to `ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL`) /// 6. `[optional]` token_program (default to `TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb`) /// 7. `[optional]` system_program (default to `11111111111111111111111111111111`) -#[derive(Clone, Debug, Default)] +#[derive(Clone, Debug)] pub struct CreateGuardBuilder { guard: Option, - mint: Option, + mint: solana_address::Address, mint_token_account: Option, - guard_authority: Option, - payer: Option, + guard_authority: solana_address::Address, + payer: solana_address::Address, associated_token_program: Option, token_program: Option, system_program: Option, - name: Option, - symbol: Option, - uri: Option, + name: String, + symbol: String, + uri: String, cpi_rule: Option, transfer_amount_rule: Option, - additional_fields_rule: Option>, + additional_fields_rule: Vec, __remaining_accounts: Vec, } impl CreateGuardBuilder { - pub fn new() -> Self { - Self::default() + pub fn new( + mint: solana_address::Address, + guard_authority: solana_address::Address, + payer: solana_address::Address, + name: String, + symbol: String, + uri: String, + additional_fields_rule: Vec, + ) -> Self { + Self { + guard: None, + mint, + mint_token_account: None, + guard_authority, + payer, + associated_token_program: None, + token_program: None, + system_program: None, + name, + symbol, + uri, + cpi_rule: None, + transfer_amount_rule: None, + additional_fields_rule, + __remaining_accounts: Vec::new(), + } } /// `[optional account, default to PDA derived from 'guard']` #[inline(always)] @@ -161,27 +185,12 @@ impl CreateGuardBuilder { self.guard = Some(guard); self } - #[inline(always)] - pub fn mint(&mut self, mint: solana_address::Address) -> &mut Self { - self.mint = Some(mint); - self - } /// `[optional account, default to PDA derived from 'mintTokenAccount']` #[inline(always)] pub fn mint_token_account(&mut self, mint_token_account: solana_address::Address) -> &mut Self { self.mint_token_account = Some(mint_token_account); self } - #[inline(always)] - pub fn guard_authority(&mut self, guard_authority: solana_address::Address) -> &mut Self { - self.guard_authority = Some(guard_authority); - self - } - #[inline(always)] - pub fn payer(&mut self, payer: solana_address::Address) -> &mut Self { - self.payer = Some(payer); - self - } /// `[optional account, default to 'ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL']` #[inline(always)] pub fn associated_token_program( @@ -203,21 +212,6 @@ impl CreateGuardBuilder { self.system_program = Some(system_program); self } - #[inline(always)] - pub fn name(&mut self, name: String) -> &mut Self { - self.name = Some(name); - self - } - #[inline(always)] - pub fn symbol(&mut self, symbol: String) -> &mut Self { - self.symbol = Some(symbol); - self - } - #[inline(always)] - pub fn uri(&mut self, uri: String) -> &mut Self { - self.uri = Some(uri); - self - } /// `[optional argument]` #[inline(always)] pub fn cpi_rule(&mut self, cpi_rule: CpiRule) -> &mut Self { @@ -230,14 +224,6 @@ impl CreateGuardBuilder { self.transfer_amount_rule = Some(transfer_amount_rule); self } - #[inline(always)] - pub fn additional_fields_rule( - &mut self, - additional_fields_rule: Vec, - ) -> &mut Self { - self.additional_fields_rule = Some(additional_fields_rule); - self - } /// Add an additional account to the instruction. #[inline(always)] pub fn add_remaining_account(&mut self, account: solana_instruction::AccountMeta) -> &mut Self { @@ -255,54 +241,55 @@ impl CreateGuardBuilder { } #[allow(clippy::clone_on_copy)] pub fn instruction(&self) -> solana_instruction::Instruction { - let guard = self.guard.unwrap_or_else(|| { - crate::pdas::find_guard_pda(&self.mint.expect("mint is needed for guard PDA")).0 - }); + let guard = self + .guard + .unwrap_or_else(|| crate::pdas::find_guard_pda(&self.mint).0); + let mint = self.mint; let mint_token_account = self.mint_token_account.unwrap_or_else(|| { solana_address::Address::find_program_address( &[ - self.guard_authority - .expect("guard_authority is needed for mint_token_account PDA") - .as_ref(), + self.guard_authority.as_ref(), self.token_program .unwrap_or(solana_address::address!( "TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb" )) .as_ref(), - self.mint - .expect("mint is needed for mint_token_account PDA") - .as_ref(), + self.mint.as_ref(), ], &solana_address::address!("ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL"), ) .0 }); + let guard_authority = self.guard_authority; + let payer = self.payer; + let associated_token_program = + self.associated_token_program + .unwrap_or(solana_address::address!( + "ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL" + )); + let token_program = self.token_program.unwrap_or(solana_address::address!( + "TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb" + )); + let system_program = self + .system_program + .unwrap_or(solana_address::address!("11111111111111111111111111111111")); let accounts = CreateGuard { guard, - mint: self.mint.expect("mint is not set"), + mint, mint_token_account, - guard_authority: self.guard_authority.expect("guard_authority is not set"), - payer: self.payer.expect("payer is not set"), - associated_token_program: self.associated_token_program.unwrap_or( - solana_address::address!("ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL"), - ), - token_program: self.token_program.unwrap_or(solana_address::address!( - "TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb" - )), - system_program: self - .system_program - .unwrap_or(solana_address::address!("11111111111111111111111111111111")), + guard_authority, + payer, + associated_token_program, + token_program, + system_program, }; let args = CreateGuardInstructionArgs { - name: self.name.clone().expect("name is not set"), - symbol: self.symbol.clone().expect("symbol is not set"), - uri: self.uri.clone().expect("uri is not set"), + name: self.name.clone(), + symbol: self.symbol.clone(), + uri: self.uri.clone(), cpi_rule: self.cpi_rule.clone(), transfer_amount_rule: self.transfer_amount_rule.clone(), - additional_fields_rule: self - .additional_fields_rule - .clone() - .expect("additional_fields_rule is not set"), + additional_fields_rule: self.additional_fields_rule.clone(), }; accounts.instruction_with_remaining_accounts(args, &self.__remaining_accounts) @@ -474,97 +461,41 @@ pub struct CreateGuardCpiBuilder<'a, 'b> { } impl<'a, 'b> CreateGuardCpiBuilder<'a, 'b> { - pub fn new(program: &'b solana_account_info::AccountInfo<'a>) -> Self { + pub fn new( + __program: &'b solana_account_info::AccountInfo<'a>, + guard: &'b solana_account_info::AccountInfo<'a>, + mint: &'b solana_account_info::AccountInfo<'a>, + mint_token_account: &'b solana_account_info::AccountInfo<'a>, + guard_authority: &'b solana_account_info::AccountInfo<'a>, + payer: &'b solana_account_info::AccountInfo<'a>, + associated_token_program: &'b solana_account_info::AccountInfo<'a>, + token_program: &'b solana_account_info::AccountInfo<'a>, + system_program: &'b solana_account_info::AccountInfo<'a>, + name: String, + symbol: String, + uri: String, + additional_fields_rule: Vec, + ) -> Self { let instruction = Box::new(CreateGuardCpiBuilderInstruction { - __program: program, - guard: None, - mint: None, - mint_token_account: None, - guard_authority: None, - payer: None, - associated_token_program: None, - token_program: None, - system_program: None, - name: None, - symbol: None, - uri: None, + __program, + guard, + mint, + mint_token_account, + guard_authority, + payer, + associated_token_program, + token_program, + system_program, + name, + symbol, + uri, cpi_rule: None, transfer_amount_rule: None, - additional_fields_rule: None, + additional_fields_rule, __remaining_accounts: Vec::new(), }); Self { instruction } } - #[inline(always)] - pub fn guard(&mut self, guard: &'b solana_account_info::AccountInfo<'a>) -> &mut Self { - self.instruction.guard = Some(guard); - self - } - #[inline(always)] - pub fn mint(&mut self, mint: &'b solana_account_info::AccountInfo<'a>) -> &mut Self { - self.instruction.mint = Some(mint); - self - } - #[inline(always)] - pub fn mint_token_account( - &mut self, - mint_token_account: &'b solana_account_info::AccountInfo<'a>, - ) -> &mut Self { - self.instruction.mint_token_account = Some(mint_token_account); - self - } - #[inline(always)] - pub fn guard_authority( - &mut self, - guard_authority: &'b solana_account_info::AccountInfo<'a>, - ) -> &mut Self { - self.instruction.guard_authority = Some(guard_authority); - self - } - #[inline(always)] - pub fn payer(&mut self, payer: &'b solana_account_info::AccountInfo<'a>) -> &mut Self { - self.instruction.payer = Some(payer); - self - } - #[inline(always)] - pub fn associated_token_program( - &mut self, - associated_token_program: &'b solana_account_info::AccountInfo<'a>, - ) -> &mut Self { - self.instruction.associated_token_program = Some(associated_token_program); - self - } - #[inline(always)] - pub fn token_program( - &mut self, - token_program: &'b solana_account_info::AccountInfo<'a>, - ) -> &mut Self { - self.instruction.token_program = Some(token_program); - self - } - #[inline(always)] - pub fn system_program( - &mut self, - system_program: &'b solana_account_info::AccountInfo<'a>, - ) -> &mut Self { - self.instruction.system_program = Some(system_program); - self - } - #[inline(always)] - pub fn name(&mut self, name: String) -> &mut Self { - self.instruction.name = Some(name); - self - } - #[inline(always)] - pub fn symbol(&mut self, symbol: String) -> &mut Self { - self.instruction.symbol = Some(symbol); - self - } - #[inline(always)] - pub fn uri(&mut self, uri: String) -> &mut Self { - self.instruction.uri = Some(uri); - self - } /// `[optional argument]` #[inline(always)] pub fn cpi_rule(&mut self, cpi_rule: CpiRule) -> &mut Self { @@ -577,14 +508,6 @@ impl<'a, 'b> CreateGuardCpiBuilder<'a, 'b> { self.instruction.transfer_amount_rule = Some(transfer_amount_rule); self } - #[inline(always)] - pub fn additional_fields_rule( - &mut self, - additional_fields_rule: Vec, - ) -> &mut Self { - self.instruction.additional_fields_rule = Some(additional_fields_rule); - self - } /// Add an additional account to the instruction. #[inline(always)] pub fn add_remaining_account( @@ -620,50 +543,23 @@ impl<'a, 'b> CreateGuardCpiBuilder<'a, 'b> { #[allow(clippy::vec_init_then_push)] pub fn invoke_signed(&self, signers_seeds: &[&[&[u8]]]) -> solana_program_error::ProgramResult { let args = CreateGuardInstructionArgs { - name: self.instruction.name.clone().expect("name is not set"), - symbol: self.instruction.symbol.clone().expect("symbol is not set"), - uri: self.instruction.uri.clone().expect("uri is not set"), + name: self.instruction.name.clone(), + symbol: self.instruction.symbol.clone(), + uri: self.instruction.uri.clone(), cpi_rule: self.instruction.cpi_rule.clone(), transfer_amount_rule: self.instruction.transfer_amount_rule.clone(), - additional_fields_rule: self - .instruction - .additional_fields_rule - .clone() - .expect("additional_fields_rule is not set"), + additional_fields_rule: self.instruction.additional_fields_rule.clone(), }; let instruction = CreateGuardCpi { __program: self.instruction.__program, - - guard: self.instruction.guard.expect("guard is not set"), - - mint: self.instruction.mint.expect("mint is not set"), - - mint_token_account: self - .instruction - .mint_token_account - .expect("mint_token_account is not set"), - - guard_authority: self - .instruction - .guard_authority - .expect("guard_authority is not set"), - - payer: self.instruction.payer.expect("payer is not set"), - - associated_token_program: self - .instruction - .associated_token_program - .expect("associated_token_program is not set"), - - token_program: self - .instruction - .token_program - .expect("token_program is not set"), - - system_program: self - .instruction - .system_program - .expect("system_program is not set"), + guard: self.instruction.guard, + mint: self.instruction.mint, + mint_token_account: self.instruction.mint_token_account, + guard_authority: self.instruction.guard_authority, + payer: self.instruction.payer, + associated_token_program: self.instruction.associated_token_program, + token_program: self.instruction.token_program, + system_program: self.instruction.system_program, __args: args, }; instruction.invoke_signed_with_remaining_accounts( @@ -676,20 +572,20 @@ impl<'a, 'b> CreateGuardCpiBuilder<'a, 'b> { #[derive(Clone, Debug)] struct CreateGuardCpiBuilderInstruction<'a, 'b> { __program: &'b solana_account_info::AccountInfo<'a>, - guard: Option<&'b solana_account_info::AccountInfo<'a>>, - mint: Option<&'b solana_account_info::AccountInfo<'a>>, - mint_token_account: Option<&'b solana_account_info::AccountInfo<'a>>, - guard_authority: Option<&'b solana_account_info::AccountInfo<'a>>, - payer: Option<&'b solana_account_info::AccountInfo<'a>>, - associated_token_program: Option<&'b solana_account_info::AccountInfo<'a>>, - token_program: Option<&'b solana_account_info::AccountInfo<'a>>, - system_program: Option<&'b solana_account_info::AccountInfo<'a>>, - name: Option, - symbol: Option, - uri: Option, + guard: &'b solana_account_info::AccountInfo<'a>, + mint: &'b solana_account_info::AccountInfo<'a>, + mint_token_account: &'b solana_account_info::AccountInfo<'a>, + guard_authority: &'b solana_account_info::AccountInfo<'a>, + payer: &'b solana_account_info::AccountInfo<'a>, + associated_token_program: &'b solana_account_info::AccountInfo<'a>, + token_program: &'b solana_account_info::AccountInfo<'a>, + system_program: &'b solana_account_info::AccountInfo<'a>, + name: String, + symbol: String, + uri: String, cpi_rule: Option, transfer_amount_rule: Option, - additional_fields_rule: Option>, + additional_fields_rule: Vec, /// Additional instruction accounts `(AccountInfo, is_writable, is_signer)`. __remaining_accounts: Vec<(&'b solana_account_info::AccountInfo<'a>, bool, bool)>, } diff --git a/e2e/anchor/src/generated/instructions/execute.rs b/e2e/anchor/src/generated/instructions/execute.rs index 8365564..5ce2c95 100644 --- a/e2e/anchor/src/generated/instructions/execute.rs +++ b/e2e/anchor/src/generated/instructions/execute.rs @@ -124,45 +124,39 @@ impl ExecuteInstructionArgs { /// 4. `[optional]` extra_metas_account (default to PDA derived from 'extraMetasAccount') /// 5. `[]` guard /// 6. `[optional]` instruction_sysvar_account (default to `Sysvar1nstructions1111111111111111111111111`) -#[derive(Clone, Debug, Default)] +#[derive(Clone, Debug)] pub struct ExecuteBuilder { - source_account: Option, - mint: Option, - destination_account: Option, - owner_delegate: Option, + source_account: solana_address::Address, + mint: solana_address::Address, + destination_account: solana_address::Address, + owner_delegate: solana_address::Address, extra_metas_account: Option, - guard: Option, + guard: solana_address::Address, instruction_sysvar_account: Option, - amount: Option, + amount: u64, __remaining_accounts: Vec, } impl ExecuteBuilder { - pub fn new() -> Self { - Self::default() - } - #[inline(always)] - pub fn source_account(&mut self, source_account: solana_address::Address) -> &mut Self { - self.source_account = Some(source_account); - self - } - #[inline(always)] - pub fn mint(&mut self, mint: solana_address::Address) -> &mut Self { - self.mint = Some(mint); - self - } - #[inline(always)] - pub fn destination_account( - &mut self, + pub fn new( + source_account: solana_address::Address, + mint: solana_address::Address, destination_account: solana_address::Address, - ) -> &mut Self { - self.destination_account = Some(destination_account); - self - } - #[inline(always)] - pub fn owner_delegate(&mut self, owner_delegate: solana_address::Address) -> &mut Self { - self.owner_delegate = Some(owner_delegate); - self + owner_delegate: solana_address::Address, + guard: solana_address::Address, + amount: u64, + ) -> Self { + Self { + source_account, + mint, + destination_account, + owner_delegate, + extra_metas_account: None, + guard, + instruction_sysvar_account: None, + amount, + __remaining_accounts: Vec::new(), + } } /// `[optional account, default to PDA derived from 'extraMetasAccount']` #[inline(always)] @@ -173,11 +167,6 @@ impl ExecuteBuilder { self.extra_metas_account = Some(extra_metas_account); self } - #[inline(always)] - pub fn guard(&mut self, guard: solana_address::Address) -> &mut Self { - self.guard = Some(guard); - self - } /// `[optional account, default to 'Sysvar1nstructions1111111111111111111111111']` #[inline(always)] pub fn instruction_sysvar_account( @@ -187,11 +176,6 @@ impl ExecuteBuilder { self.instruction_sysvar_account = Some(instruction_sysvar_account); self } - #[inline(always)] - pub fn amount(&mut self, amount: u64) -> &mut Self { - self.amount = Some(amount); - self - } /// Add an additional account to the instruction. #[inline(always)] pub fn add_remaining_account(&mut self, account: solana_instruction::AccountMeta) -> &mut Self { @@ -209,29 +193,30 @@ impl ExecuteBuilder { } #[allow(clippy::clone_on_copy)] pub fn instruction(&self) -> solana_instruction::Instruction { - let extra_metas_account = self.extra_metas_account.unwrap_or_else(|| { - crate::pdas::find_extra_metas_account_pda( - &self - .mint - .expect("mint is needed for extra_metas_account PDA"), - ) - .0 - }); + let source_account = self.source_account; + let mint = self.mint; + let destination_account = self.destination_account; + let owner_delegate = self.owner_delegate; + let extra_metas_account = self + .extra_metas_account + .unwrap_or_else(|| crate::pdas::find_extra_metas_account_pda(&self.mint).0); + let guard = self.guard; + let instruction_sysvar_account = + self.instruction_sysvar_account + .unwrap_or(solana_address::address!( + "Sysvar1nstructions1111111111111111111111111" + )); let accounts = Execute { - source_account: self.source_account.expect("source_account is not set"), - mint: self.mint.expect("mint is not set"), - destination_account: self - .destination_account - .expect("destination_account is not set"), - owner_delegate: self.owner_delegate.expect("owner_delegate is not set"), + source_account, + mint, + destination_account, + owner_delegate, extra_metas_account, - guard: self.guard.expect("guard is not set"), - instruction_sysvar_account: self.instruction_sysvar_account.unwrap_or( - solana_address::address!("Sysvar1nstructions1111111111111111111111111"), - ), + guard, + instruction_sysvar_account, }; let args = ExecuteInstructionArgs { - amount: self.amount.clone().expect("amount is not set"), + amount: self.amount.clone(), }; accounts.instruction_with_remaining_accounts(args, &self.__remaining_accounts) @@ -401,75 +386,30 @@ pub struct ExecuteCpiBuilder<'a, 'b> { } impl<'a, 'b> ExecuteCpiBuilder<'a, 'b> { - pub fn new(program: &'b solana_account_info::AccountInfo<'a>) -> Self { - let instruction = Box::new(ExecuteCpiBuilderInstruction { - __program: program, - source_account: None, - mint: None, - destination_account: None, - owner_delegate: None, - extra_metas_account: None, - guard: None, - instruction_sysvar_account: None, - amount: None, - __remaining_accounts: Vec::new(), - }); - Self { instruction } - } - #[inline(always)] - pub fn source_account( - &mut self, + pub fn new( + __program: &'b solana_account_info::AccountInfo<'a>, source_account: &'b solana_account_info::AccountInfo<'a>, - ) -> &mut Self { - self.instruction.source_account = Some(source_account); - self - } - #[inline(always)] - pub fn mint(&mut self, mint: &'b solana_account_info::AccountInfo<'a>) -> &mut Self { - self.instruction.mint = Some(mint); - self - } - #[inline(always)] - pub fn destination_account( - &mut self, + mint: &'b solana_account_info::AccountInfo<'a>, destination_account: &'b solana_account_info::AccountInfo<'a>, - ) -> &mut Self { - self.instruction.destination_account = Some(destination_account); - self - } - #[inline(always)] - pub fn owner_delegate( - &mut self, owner_delegate: &'b solana_account_info::AccountInfo<'a>, - ) -> &mut Self { - self.instruction.owner_delegate = Some(owner_delegate); - self - } - #[inline(always)] - pub fn extra_metas_account( - &mut self, extra_metas_account: &'b solana_account_info::AccountInfo<'a>, - ) -> &mut Self { - self.instruction.extra_metas_account = Some(extra_metas_account); - self - } - #[inline(always)] - pub fn guard(&mut self, guard: &'b solana_account_info::AccountInfo<'a>) -> &mut Self { - self.instruction.guard = Some(guard); - self - } - #[inline(always)] - pub fn instruction_sysvar_account( - &mut self, + guard: &'b solana_account_info::AccountInfo<'a>, instruction_sysvar_account: &'b solana_account_info::AccountInfo<'a>, - ) -> &mut Self { - self.instruction.instruction_sysvar_account = Some(instruction_sysvar_account); - self - } - #[inline(always)] - pub fn amount(&mut self, amount: u64) -> &mut Self { - self.instruction.amount = Some(amount); - self + amount: u64, + ) -> Self { + let instruction = Box::new(ExecuteCpiBuilderInstruction { + __program, + source_account, + mint, + destination_account, + owner_delegate, + extra_metas_account, + guard, + instruction_sysvar_account, + amount, + __remaining_accounts: Vec::new(), + }); + Self { instruction } } /// Add an additional account to the instruction. #[inline(always)] @@ -506,39 +446,17 @@ impl<'a, 'b> ExecuteCpiBuilder<'a, 'b> { #[allow(clippy::vec_init_then_push)] pub fn invoke_signed(&self, signers_seeds: &[&[&[u8]]]) -> solana_program_error::ProgramResult { let args = ExecuteInstructionArgs { - amount: self.instruction.amount.clone().expect("amount is not set"), + amount: self.instruction.amount.clone(), }; let instruction = ExecuteCpi { __program: self.instruction.__program, - - source_account: self - .instruction - .source_account - .expect("source_account is not set"), - - mint: self.instruction.mint.expect("mint is not set"), - - destination_account: self - .instruction - .destination_account - .expect("destination_account is not set"), - - owner_delegate: self - .instruction - .owner_delegate - .expect("owner_delegate is not set"), - - extra_metas_account: self - .instruction - .extra_metas_account - .expect("extra_metas_account is not set"), - - guard: self.instruction.guard.expect("guard is not set"), - - instruction_sysvar_account: self - .instruction - .instruction_sysvar_account - .expect("instruction_sysvar_account is not set"), + source_account: self.instruction.source_account, + mint: self.instruction.mint, + destination_account: self.instruction.destination_account, + owner_delegate: self.instruction.owner_delegate, + extra_metas_account: self.instruction.extra_metas_account, + guard: self.instruction.guard, + instruction_sysvar_account: self.instruction.instruction_sysvar_account, __args: args, }; instruction.invoke_signed_with_remaining_accounts( @@ -551,14 +469,14 @@ impl<'a, 'b> ExecuteCpiBuilder<'a, 'b> { #[derive(Clone, Debug)] struct ExecuteCpiBuilderInstruction<'a, 'b> { __program: &'b solana_account_info::AccountInfo<'a>, - source_account: Option<&'b solana_account_info::AccountInfo<'a>>, - mint: Option<&'b solana_account_info::AccountInfo<'a>>, - destination_account: Option<&'b solana_account_info::AccountInfo<'a>>, - owner_delegate: Option<&'b solana_account_info::AccountInfo<'a>>, - extra_metas_account: Option<&'b solana_account_info::AccountInfo<'a>>, - guard: Option<&'b solana_account_info::AccountInfo<'a>>, - instruction_sysvar_account: Option<&'b solana_account_info::AccountInfo<'a>>, - amount: Option, + source_account: &'b solana_account_info::AccountInfo<'a>, + mint: &'b solana_account_info::AccountInfo<'a>, + destination_account: &'b solana_account_info::AccountInfo<'a>, + owner_delegate: &'b solana_account_info::AccountInfo<'a>, + extra_metas_account: &'b solana_account_info::AccountInfo<'a>, + guard: &'b solana_account_info::AccountInfo<'a>, + instruction_sysvar_account: &'b solana_account_info::AccountInfo<'a>, + amount: u64, /// Additional instruction accounts `(AccountInfo, is_writable, is_signer)`. __remaining_accounts: Vec<(&'b solana_account_info::AccountInfo<'a>, bool, bool)>, } diff --git a/e2e/anchor/src/generated/instructions/initialize.rs b/e2e/anchor/src/generated/instructions/initialize.rs index 444ac75..9527f44 100644 --- a/e2e/anchor/src/generated/instructions/initialize.rs +++ b/e2e/anchor/src/generated/instructions/initialize.rs @@ -100,20 +100,33 @@ impl Default for InitializeInstructionData { /// 3. `[writable, signer]` transfer_hook_authority /// 4. `[optional]` system_program (default to `11111111111111111111111111111111`) /// 5. `[writable, signer]` payer -#[derive(Clone, Debug, Default)] +#[derive(Clone, Debug)] pub struct InitializeBuilder { extra_metas_account: Option, - guard: Option, - mint: Option, - transfer_hook_authority: Option, + guard: solana_address::Address, + mint: solana_address::Address, + transfer_hook_authority: solana_address::Address, system_program: Option, - payer: Option, + payer: solana_address::Address, __remaining_accounts: Vec, } impl InitializeBuilder { - pub fn new() -> Self { - Self::default() + pub fn new( + guard: solana_address::Address, + mint: solana_address::Address, + transfer_hook_authority: solana_address::Address, + payer: solana_address::Address, + ) -> Self { + Self { + extra_metas_account: None, + guard, + mint, + transfer_hook_authority, + system_program: None, + payer, + __remaining_accounts: Vec::new(), + } } /// `[optional account, default to PDA derived from 'extraMetasAccount']` #[inline(always)] @@ -124,35 +137,12 @@ impl InitializeBuilder { self.extra_metas_account = Some(extra_metas_account); self } - #[inline(always)] - pub fn guard(&mut self, guard: solana_address::Address) -> &mut Self { - self.guard = Some(guard); - self - } - #[inline(always)] - pub fn mint(&mut self, mint: solana_address::Address) -> &mut Self { - self.mint = Some(mint); - self - } - #[inline(always)] - pub fn transfer_hook_authority( - &mut self, - transfer_hook_authority: solana_address::Address, - ) -> &mut Self { - self.transfer_hook_authority = Some(transfer_hook_authority); - self - } /// `[optional account, default to '11111111111111111111111111111111']` #[inline(always)] pub fn system_program(&mut self, system_program: solana_address::Address) -> &mut Self { self.system_program = Some(system_program); self } - #[inline(always)] - pub fn payer(&mut self, payer: solana_address::Address) -> &mut Self { - self.payer = Some(payer); - self - } /// Add an additional account to the instruction. #[inline(always)] pub fn add_remaining_account(&mut self, account: solana_instruction::AccountMeta) -> &mut Self { @@ -170,25 +160,23 @@ impl InitializeBuilder { } #[allow(clippy::clone_on_copy)] pub fn instruction(&self) -> solana_instruction::Instruction { - let extra_metas_account = self.extra_metas_account.unwrap_or_else(|| { - crate::pdas::find_extra_metas_account_pda( - &self - .mint - .expect("mint is needed for extra_metas_account PDA"), - ) - .0 - }); + let extra_metas_account = self + .extra_metas_account + .unwrap_or_else(|| crate::pdas::find_extra_metas_account_pda(&self.mint).0); + let guard = self.guard; + let mint = self.mint; + let transfer_hook_authority = self.transfer_hook_authority; + let system_program = self + .system_program + .unwrap_or(solana_address::address!("11111111111111111111111111111111")); + let payer = self.payer; let accounts = Initialize { extra_metas_account, - guard: self.guard.expect("guard is not set"), - mint: self.mint.expect("mint is not set"), - transfer_hook_authority: self - .transfer_hook_authority - .expect("transfer_hook_authority is not set"), - system_program: self - .system_program - .unwrap_or(solana_address::address!("11111111111111111111111111111111")), - payer: self.payer.expect("payer is not set"), + guard, + mint, + transfer_hook_authority, + system_program, + payer, }; accounts.instruction_with_remaining_accounts(&self.__remaining_accounts) @@ -338,58 +326,27 @@ pub struct InitializeCpiBuilder<'a, 'b> { } impl<'a, 'b> InitializeCpiBuilder<'a, 'b> { - pub fn new(program: &'b solana_account_info::AccountInfo<'a>) -> Self { + pub fn new( + __program: &'b solana_account_info::AccountInfo<'a>, + extra_metas_account: &'b solana_account_info::AccountInfo<'a>, + guard: &'b solana_account_info::AccountInfo<'a>, + mint: &'b solana_account_info::AccountInfo<'a>, + transfer_hook_authority: &'b solana_account_info::AccountInfo<'a>, + system_program: &'b solana_account_info::AccountInfo<'a>, + payer: &'b solana_account_info::AccountInfo<'a>, + ) -> Self { let instruction = Box::new(InitializeCpiBuilderInstruction { - __program: program, - extra_metas_account: None, - guard: None, - mint: None, - transfer_hook_authority: None, - system_program: None, - payer: None, + __program, + extra_metas_account, + guard, + mint, + transfer_hook_authority, + system_program, + payer, __remaining_accounts: Vec::new(), }); Self { instruction } } - #[inline(always)] - pub fn extra_metas_account( - &mut self, - extra_metas_account: &'b solana_account_info::AccountInfo<'a>, - ) -> &mut Self { - self.instruction.extra_metas_account = Some(extra_metas_account); - self - } - #[inline(always)] - pub fn guard(&mut self, guard: &'b solana_account_info::AccountInfo<'a>) -> &mut Self { - self.instruction.guard = Some(guard); - self - } - #[inline(always)] - pub fn mint(&mut self, mint: &'b solana_account_info::AccountInfo<'a>) -> &mut Self { - self.instruction.mint = Some(mint); - self - } - #[inline(always)] - pub fn transfer_hook_authority( - &mut self, - transfer_hook_authority: &'b solana_account_info::AccountInfo<'a>, - ) -> &mut Self { - self.instruction.transfer_hook_authority = Some(transfer_hook_authority); - self - } - #[inline(always)] - pub fn system_program( - &mut self, - system_program: &'b solana_account_info::AccountInfo<'a>, - ) -> &mut Self { - self.instruction.system_program = Some(system_program); - self - } - #[inline(always)] - pub fn payer(&mut self, payer: &'b solana_account_info::AccountInfo<'a>) -> &mut Self { - self.instruction.payer = Some(payer); - self - } /// Add an additional account to the instruction. #[inline(always)] pub fn add_remaining_account( @@ -426,27 +383,12 @@ impl<'a, 'b> InitializeCpiBuilder<'a, 'b> { pub fn invoke_signed(&self, signers_seeds: &[&[&[u8]]]) -> solana_program_error::ProgramResult { let instruction = InitializeCpi { __program: self.instruction.__program, - - extra_metas_account: self - .instruction - .extra_metas_account - .expect("extra_metas_account is not set"), - - guard: self.instruction.guard.expect("guard is not set"), - - mint: self.instruction.mint.expect("mint is not set"), - - transfer_hook_authority: self - .instruction - .transfer_hook_authority - .expect("transfer_hook_authority is not set"), - - system_program: self - .instruction - .system_program - .expect("system_program is not set"), - - payer: self.instruction.payer.expect("payer is not set"), + extra_metas_account: self.instruction.extra_metas_account, + guard: self.instruction.guard, + mint: self.instruction.mint, + transfer_hook_authority: self.instruction.transfer_hook_authority, + system_program: self.instruction.system_program, + payer: self.instruction.payer, }; instruction.invoke_signed_with_remaining_accounts( signers_seeds, @@ -458,12 +400,12 @@ impl<'a, 'b> InitializeCpiBuilder<'a, 'b> { #[derive(Clone, Debug)] struct InitializeCpiBuilderInstruction<'a, 'b> { __program: &'b solana_account_info::AccountInfo<'a>, - extra_metas_account: Option<&'b solana_account_info::AccountInfo<'a>>, - guard: Option<&'b solana_account_info::AccountInfo<'a>>, - mint: Option<&'b solana_account_info::AccountInfo<'a>>, - transfer_hook_authority: Option<&'b solana_account_info::AccountInfo<'a>>, - system_program: Option<&'b solana_account_info::AccountInfo<'a>>, - payer: Option<&'b solana_account_info::AccountInfo<'a>>, + extra_metas_account: &'b solana_account_info::AccountInfo<'a>, + guard: &'b solana_account_info::AccountInfo<'a>, + mint: &'b solana_account_info::AccountInfo<'a>, + transfer_hook_authority: &'b solana_account_info::AccountInfo<'a>, + system_program: &'b solana_account_info::AccountInfo<'a>, + payer: &'b solana_account_info::AccountInfo<'a>, /// Additional instruction accounts `(AccountInfo, is_writable, is_signer)`. __remaining_accounts: Vec<(&'b solana_account_info::AccountInfo<'a>, bool, bool)>, } diff --git a/e2e/anchor/src/generated/instructions/update_guard.rs b/e2e/anchor/src/generated/instructions/update_guard.rs index 530eaf9..3d1b0fb 100644 --- a/e2e/anchor/src/generated/instructions/update_guard.rs +++ b/e2e/anchor/src/generated/instructions/update_guard.rs @@ -120,23 +120,38 @@ impl UpdateGuardInstructionArgs { /// 3. `[signer]` guard_authority /// 4. `[optional]` token_program (default to `TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb`) /// 5. `[optional]` system_program (default to `11111111111111111111111111111111`) -#[derive(Clone, Debug, Default)] +#[derive(Clone, Debug)] pub struct UpdateGuardBuilder { guard: Option, - mint: Option, + mint: solana_address::Address, token_account: Option, - guard_authority: Option, + guard_authority: solana_address::Address, token_program: Option, system_program: Option, cpi_rule: Option, transfer_amount_rule: Option, - additional_fields_rule: Option>, + additional_fields_rule: Vec, __remaining_accounts: Vec, } impl UpdateGuardBuilder { - pub fn new() -> Self { - Self::default() + pub fn new( + mint: solana_address::Address, + guard_authority: solana_address::Address, + additional_fields_rule: Vec, + ) -> Self { + Self { + guard: None, + mint, + token_account: None, + guard_authority, + token_program: None, + system_program: None, + cpi_rule: None, + transfer_amount_rule: None, + additional_fields_rule, + __remaining_accounts: Vec::new(), + } } /// `[optional account, default to PDA derived from 'guard']` #[inline(always)] @@ -144,22 +159,12 @@ impl UpdateGuardBuilder { self.guard = Some(guard); self } - #[inline(always)] - pub fn mint(&mut self, mint: solana_address::Address) -> &mut Self { - self.mint = Some(mint); - self - } /// `[optional account, default to PDA derived from 'tokenAccount']` #[inline(always)] pub fn token_account(&mut self, token_account: solana_address::Address) -> &mut Self { self.token_account = Some(token_account); self } - #[inline(always)] - pub fn guard_authority(&mut self, guard_authority: solana_address::Address) -> &mut Self { - self.guard_authority = Some(guard_authority); - self - } /// `[optional account, default to 'TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb']` #[inline(always)] pub fn token_program(&mut self, token_program: solana_address::Address) -> &mut Self { @@ -184,14 +189,6 @@ impl UpdateGuardBuilder { self.transfer_amount_rule = Some(transfer_amount_rule); self } - #[inline(always)] - pub fn additional_fields_rule( - &mut self, - additional_fields_rule: Vec, - ) -> &mut Self { - self.additional_fields_rule = Some(additional_fields_rule); - self - } /// Add an additional account to the instruction. #[inline(always)] pub fn add_remaining_account(&mut self, account: solana_instruction::AccountMeta) -> &mut Self { @@ -209,47 +206,44 @@ impl UpdateGuardBuilder { } #[allow(clippy::clone_on_copy)] pub fn instruction(&self) -> solana_instruction::Instruction { - let guard = self.guard.unwrap_or_else(|| { - crate::pdas::find_guard_pda(&self.mint.expect("mint is needed for guard PDA")).0 - }); + let guard = self + .guard + .unwrap_or_else(|| crate::pdas::find_guard_pda(&self.mint).0); + let mint = self.mint; let token_account = self.token_account.unwrap_or_else(|| { solana_address::Address::find_program_address( &[ - self.guard_authority - .expect("guard_authority is needed for token_account PDA") - .as_ref(), + self.guard_authority.as_ref(), self.token_program .unwrap_or(solana_address::address!( "TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb" )) .as_ref(), - self.mint - .expect("mint is needed for token_account PDA") - .as_ref(), + self.mint.as_ref(), ], &solana_address::address!("ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL"), ) .0 }); + let guard_authority = self.guard_authority; + let token_program = self.token_program.unwrap_or(solana_address::address!( + "TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb" + )); + let system_program = self + .system_program + .unwrap_or(solana_address::address!("11111111111111111111111111111111")); let accounts = UpdateGuard { guard, - mint: self.mint.expect("mint is not set"), + mint, token_account, - guard_authority: self.guard_authority.expect("guard_authority is not set"), - token_program: self.token_program.unwrap_or(solana_address::address!( - "TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb" - )), - system_program: self - .system_program - .unwrap_or(solana_address::address!("11111111111111111111111111111111")), + guard_authority, + token_program, + system_program, }; let args = UpdateGuardInstructionArgs { cpi_rule: self.cpi_rule.clone(), transfer_amount_rule: self.transfer_amount_rule.clone(), - additional_fields_rule: self - .additional_fields_rule - .clone() - .expect("additional_fields_rule is not set"), + additional_fields_rule: self.additional_fields_rule.clone(), }; accounts.instruction_with_remaining_accounts(args, &self.__remaining_accounts) @@ -405,64 +399,31 @@ pub struct UpdateGuardCpiBuilder<'a, 'b> { } impl<'a, 'b> UpdateGuardCpiBuilder<'a, 'b> { - pub fn new(program: &'b solana_account_info::AccountInfo<'a>) -> Self { + pub fn new( + __program: &'b solana_account_info::AccountInfo<'a>, + guard: &'b solana_account_info::AccountInfo<'a>, + mint: &'b solana_account_info::AccountInfo<'a>, + token_account: &'b solana_account_info::AccountInfo<'a>, + guard_authority: &'b solana_account_info::AccountInfo<'a>, + token_program: &'b solana_account_info::AccountInfo<'a>, + system_program: &'b solana_account_info::AccountInfo<'a>, + additional_fields_rule: Vec, + ) -> Self { let instruction = Box::new(UpdateGuardCpiBuilderInstruction { - __program: program, - guard: None, - mint: None, - token_account: None, - guard_authority: None, - token_program: None, - system_program: None, + __program, + guard, + mint, + token_account, + guard_authority, + token_program, + system_program, cpi_rule: None, transfer_amount_rule: None, - additional_fields_rule: None, + additional_fields_rule, __remaining_accounts: Vec::new(), }); Self { instruction } } - #[inline(always)] - pub fn guard(&mut self, guard: &'b solana_account_info::AccountInfo<'a>) -> &mut Self { - self.instruction.guard = Some(guard); - self - } - #[inline(always)] - pub fn mint(&mut self, mint: &'b solana_account_info::AccountInfo<'a>) -> &mut Self { - self.instruction.mint = Some(mint); - self - } - #[inline(always)] - pub fn token_account( - &mut self, - token_account: &'b solana_account_info::AccountInfo<'a>, - ) -> &mut Self { - self.instruction.token_account = Some(token_account); - self - } - #[inline(always)] - pub fn guard_authority( - &mut self, - guard_authority: &'b solana_account_info::AccountInfo<'a>, - ) -> &mut Self { - self.instruction.guard_authority = Some(guard_authority); - self - } - #[inline(always)] - pub fn token_program( - &mut self, - token_program: &'b solana_account_info::AccountInfo<'a>, - ) -> &mut Self { - self.instruction.token_program = Some(token_program); - self - } - #[inline(always)] - pub fn system_program( - &mut self, - system_program: &'b solana_account_info::AccountInfo<'a>, - ) -> &mut Self { - self.instruction.system_program = Some(system_program); - self - } /// `[optional argument]` #[inline(always)] pub fn cpi_rule(&mut self, cpi_rule: CpiRule) -> &mut Self { @@ -475,14 +436,6 @@ impl<'a, 'b> UpdateGuardCpiBuilder<'a, 'b> { self.instruction.transfer_amount_rule = Some(transfer_amount_rule); self } - #[inline(always)] - pub fn additional_fields_rule( - &mut self, - additional_fields_rule: Vec, - ) -> &mut Self { - self.instruction.additional_fields_rule = Some(additional_fields_rule); - self - } /// Add an additional account to the instruction. #[inline(always)] pub fn add_remaining_account( @@ -520,38 +473,16 @@ impl<'a, 'b> UpdateGuardCpiBuilder<'a, 'b> { let args = UpdateGuardInstructionArgs { cpi_rule: self.instruction.cpi_rule.clone(), transfer_amount_rule: self.instruction.transfer_amount_rule.clone(), - additional_fields_rule: self - .instruction - .additional_fields_rule - .clone() - .expect("additional_fields_rule is not set"), + additional_fields_rule: self.instruction.additional_fields_rule.clone(), }; let instruction = UpdateGuardCpi { __program: self.instruction.__program, - - guard: self.instruction.guard.expect("guard is not set"), - - mint: self.instruction.mint.expect("mint is not set"), - - token_account: self - .instruction - .token_account - .expect("token_account is not set"), - - guard_authority: self - .instruction - .guard_authority - .expect("guard_authority is not set"), - - token_program: self - .instruction - .token_program - .expect("token_program is not set"), - - system_program: self - .instruction - .system_program - .expect("system_program is not set"), + guard: self.instruction.guard, + mint: self.instruction.mint, + token_account: self.instruction.token_account, + guard_authority: self.instruction.guard_authority, + token_program: self.instruction.token_program, + system_program: self.instruction.system_program, __args: args, }; instruction.invoke_signed_with_remaining_accounts( @@ -564,15 +495,15 @@ impl<'a, 'b> UpdateGuardCpiBuilder<'a, 'b> { #[derive(Clone, Debug)] struct UpdateGuardCpiBuilderInstruction<'a, 'b> { __program: &'b solana_account_info::AccountInfo<'a>, - guard: Option<&'b solana_account_info::AccountInfo<'a>>, - mint: Option<&'b solana_account_info::AccountInfo<'a>>, - token_account: Option<&'b solana_account_info::AccountInfo<'a>>, - guard_authority: Option<&'b solana_account_info::AccountInfo<'a>>, - token_program: Option<&'b solana_account_info::AccountInfo<'a>>, - system_program: Option<&'b solana_account_info::AccountInfo<'a>>, + guard: &'b solana_account_info::AccountInfo<'a>, + mint: &'b solana_account_info::AccountInfo<'a>, + token_account: &'b solana_account_info::AccountInfo<'a>, + guard_authority: &'b solana_account_info::AccountInfo<'a>, + token_program: &'b solana_account_info::AccountInfo<'a>, + system_program: &'b solana_account_info::AccountInfo<'a>, cpi_rule: Option, transfer_amount_rule: Option, - additional_fields_rule: Option>, + additional_fields_rule: Vec, /// Additional instruction accounts `(AccountInfo, is_writable, is_signer)`. __remaining_accounts: Vec<(&'b solana_account_info::AccountInfo<'a>, bool, bool)>, } diff --git a/e2e/dummy/idl.json b/e2e/dummy/idl.json index f2e0f71..110235e 100644 --- a/e2e/dummy/idl.json +++ b/e2e/dummy/idl.json @@ -252,6 +252,34 @@ } ], "arguments": [] + }, + { + "kind": "instructionNode", + "name": "instruction10", + "optionalAccountStrategy": "programId", + "docs": ["Testing programIdValueNode account default"], + "accounts": [ + { + "kind": "instructionAccountNode", + "name": "owner", + "isWritable": false, + "isSigner": true, + "isOptional": false, + "docs": [] + }, + { + "kind": "instructionAccountNode", + "name": "selfProgram", + "isWritable": false, + "isSigner": false, + "isOptional": false, + "docs": [], + "defaultValue": { + "kind": "programIdValueNode" + } + } + ], + "arguments": [] } ], "definedTypes": [], diff --git a/e2e/dummy/src/generated/instructions/instruction1.rs b/e2e/dummy/src/generated/instructions/instruction1.rs index cae4c09..f635f68 100644 --- a/e2e/dummy/src/generated/instructions/instruction1.rs +++ b/e2e/dummy/src/generated/instructions/instruction1.rs @@ -161,9 +161,9 @@ pub struct Instruction1CpiBuilder<'a, 'b> { } impl<'a, 'b> Instruction1CpiBuilder<'a, 'b> { - pub fn new(program: &'b solana_account_info::AccountInfo<'a>) -> Self { + pub fn new(__program: &'b solana_account_info::AccountInfo<'a>) -> Self { let instruction = Box::new(Instruction1CpiBuilderInstruction { - __program: program, + __program, __remaining_accounts: Vec::new(), }); Self { instruction } diff --git a/e2e/dummy/src/generated/instructions/instruction10.rs b/e2e/dummy/src/generated/instructions/instruction10.rs new file mode 100644 index 0000000..cb64872 --- /dev/null +++ b/e2e/dummy/src/generated/instructions/instruction10.rs @@ -0,0 +1,299 @@ +//! This code was AUTOGENERATED using the codama library. +//! Please DO NOT EDIT THIS FILE, instead use visitors +//! to add features, then rerun codama to update it. +//! +//! +//! + +use borsh::BorshDeserialize; +use borsh::BorshSerialize; + +/// Accounts. +#[derive(Debug)] +pub struct Instruction10 { + pub owner: solana_address::Address, + + pub self_program: solana_address::Address, +} + +impl Instruction10 { + pub fn instruction(&self) -> solana_instruction::Instruction { + self.instruction_with_remaining_accounts(&[]) + } + #[allow(clippy::arithmetic_side_effects)] + #[allow(clippy::vec_init_then_push)] + pub fn instruction_with_remaining_accounts( + &self, + remaining_accounts: &[solana_instruction::AccountMeta], + ) -> solana_instruction::Instruction { + let mut accounts = Vec::with_capacity(2 + remaining_accounts.len()); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.owner, true, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + self.self_program, + false, + )); + accounts.extend_from_slice(remaining_accounts); + let data = Instruction10InstructionData::new().try_to_vec().unwrap(); + + solana_instruction::Instruction { + program_id: crate::DUMMY_ID, + accounts, + data, + } + } +} + +#[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] +pub struct Instruction10InstructionData {} + +impl Instruction10InstructionData { + pub fn new() -> Self { + Self {} + } + + pub(crate) fn try_to_vec(&self) -> Result, std::io::Error> { + borsh::to_vec(self) + } +} + +impl Default for Instruction10InstructionData { + fn default() -> Self { + Self::new() + } +} + +/// Instruction builder for `Instruction10`. +/// +/// ### Accounts: +/// +/// 0. `[signer]` owner +/// 1. `[optional]` self_program +#[derive(Clone, Debug)] +pub struct Instruction10Builder { + owner: solana_address::Address, + self_program: Option, + __remaining_accounts: Vec, +} + +impl Instruction10Builder { + pub fn new(owner: solana_address::Address) -> Self { + Self { + owner, + self_program: None, + __remaining_accounts: Vec::new(), + } + } + #[inline(always)] + pub fn self_program(&mut self, self_program: solana_address::Address) -> &mut Self { + self.self_program = Some(self_program); + self + } + /// Add an additional account to the instruction. + #[inline(always)] + pub fn add_remaining_account(&mut self, account: solana_instruction::AccountMeta) -> &mut Self { + self.__remaining_accounts.push(account); + self + } + /// Add additional accounts to the instruction. + #[inline(always)] + pub fn add_remaining_accounts( + &mut self, + accounts: &[solana_instruction::AccountMeta], + ) -> &mut Self { + self.__remaining_accounts.extend_from_slice(accounts); + self + } + #[allow(clippy::clone_on_copy)] + pub fn instruction(&self) -> solana_instruction::Instruction { + let owner = self.owner; + let self_program = self.self_program.unwrap_or(crate::DUMMY_ID); + let accounts = Instruction10 { + owner, + self_program, + }; + + accounts.instruction_with_remaining_accounts(&self.__remaining_accounts) + } +} + +/// `instruction10` CPI accounts. +pub struct Instruction10CpiAccounts<'a, 'b> { + pub owner: &'b solana_account_info::AccountInfo<'a>, + + pub self_program: &'b solana_account_info::AccountInfo<'a>, +} + +/// `instruction10` CPI instruction. +pub struct Instruction10Cpi<'a, 'b> { + /// The program to invoke. + pub __program: &'b solana_account_info::AccountInfo<'a>, + + pub owner: &'b solana_account_info::AccountInfo<'a>, + + pub self_program: &'b solana_account_info::AccountInfo<'a>, +} + +impl<'a, 'b> Instruction10Cpi<'a, 'b> { + pub fn new( + program: &'b solana_account_info::AccountInfo<'a>, + accounts: Instruction10CpiAccounts<'a, 'b>, + ) -> Self { + Self { + __program: program, + owner: accounts.owner, + self_program: accounts.self_program, + } + } + #[inline(always)] + pub fn invoke(&self) -> solana_program_error::ProgramResult { + self.invoke_signed_with_remaining_accounts(&[], &[]) + } + #[inline(always)] + pub fn invoke_with_remaining_accounts( + &self, + remaining_accounts: &[(&'b solana_account_info::AccountInfo<'a>, bool, bool)], + ) -> solana_program_error::ProgramResult { + self.invoke_signed_with_remaining_accounts(&[], remaining_accounts) + } + #[inline(always)] + pub fn invoke_signed(&self, signers_seeds: &[&[&[u8]]]) -> solana_program_error::ProgramResult { + self.invoke_signed_with_remaining_accounts(signers_seeds, &[]) + } + #[allow(clippy::arithmetic_side_effects)] + #[allow(clippy::clone_on_copy)] + #[allow(clippy::vec_init_then_push)] + pub fn invoke_signed_with_remaining_accounts( + &self, + signers_seeds: &[&[&[u8]]], + remaining_accounts: &[(&'b solana_account_info::AccountInfo<'a>, bool, bool)], + ) -> solana_program_error::ProgramResult { + let mut accounts = Vec::with_capacity(2 + remaining_accounts.len()); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.owner.key, + true, + )); + accounts.push(solana_instruction::AccountMeta::new_readonly( + *self.self_program.key, + false, + )); + remaining_accounts.iter().for_each(|remaining_account| { + accounts.push(solana_instruction::AccountMeta { + pubkey: *remaining_account.0.key, + is_signer: remaining_account.1, + is_writable: remaining_account.2, + }) + }); + let data = Instruction10InstructionData::new().try_to_vec().unwrap(); + + let instruction = solana_instruction::Instruction { + program_id: crate::DUMMY_ID, + accounts, + data, + }; + let mut account_infos = Vec::with_capacity(3 + remaining_accounts.len()); + account_infos.push(self.__program.clone()); + account_infos.push(self.owner.clone()); + account_infos.push(self.self_program.clone()); + remaining_accounts + .iter() + .for_each(|remaining_account| account_infos.push(remaining_account.0.clone())); + + if signers_seeds.is_empty() { + solana_cpi::invoke(&instruction, &account_infos) + } else { + solana_cpi::invoke_signed(&instruction, &account_infos, signers_seeds) + } + } +} + +/// Instruction builder for `Instruction10` via CPI. +/// +/// ### Accounts: +/// +/// 0. `[signer]` owner +/// 1. `[optional]` self_program +#[derive(Clone, Debug)] +pub struct Instruction10CpiBuilder<'a, 'b> { + instruction: Box>, +} + +impl<'a, 'b> Instruction10CpiBuilder<'a, 'b> { + pub fn new( + __program: &'b solana_account_info::AccountInfo<'a>, + owner: &'b solana_account_info::AccountInfo<'a>, + ) -> Self { + let instruction = Box::new(Instruction10CpiBuilderInstruction { + __program, + owner, + self_program: None, + __remaining_accounts: Vec::new(), + }); + Self { instruction } + } + #[inline(always)] + pub fn self_program( + &mut self, + self_program: &'b solana_account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.self_program = Some(self_program); + self + } + /// Add an additional account to the instruction. + #[inline(always)] + pub fn add_remaining_account( + &mut self, + account: &'b solana_account_info::AccountInfo<'a>, + is_writable: bool, + is_signer: bool, + ) -> &mut Self { + self.instruction + .__remaining_accounts + .push((account, is_writable, is_signer)); + self + } + /// Add additional accounts to the instruction. + /// + /// Each account is represented by a tuple of the `AccountInfo`, a `bool` indicating whether the account is writable or not, + /// and a `bool` indicating whether the account is a signer or not. + #[inline(always)] + pub fn add_remaining_accounts( + &mut self, + accounts: &[(&'b solana_account_info::AccountInfo<'a>, bool, bool)], + ) -> &mut Self { + self.instruction + .__remaining_accounts + .extend_from_slice(accounts); + self + } + #[inline(always)] + pub fn invoke(&self) -> solana_program_error::ProgramResult { + self.invoke_signed(&[]) + } + #[allow(clippy::clone_on_copy)] + #[allow(clippy::vec_init_then_push)] + pub fn invoke_signed(&self, signers_seeds: &[&[&[u8]]]) -> solana_program_error::ProgramResult { + let instruction = Instruction10Cpi { + __program: self.instruction.__program, + owner: self.instruction.owner, + self_program: self + .instruction + .self_program + .unwrap_or(self.instruction.__program), + }; + instruction.invoke_signed_with_remaining_accounts( + signers_seeds, + &self.instruction.__remaining_accounts, + ) + } +} + +#[derive(Clone, Debug)] +struct Instruction10CpiBuilderInstruction<'a, 'b> { + __program: &'b solana_account_info::AccountInfo<'a>, + owner: &'b solana_account_info::AccountInfo<'a>, + self_program: Option<&'b solana_account_info::AccountInfo<'a>>, + /// Additional instruction accounts `(AccountInfo, is_writable, is_signer)`. + __remaining_accounts: Vec<(&'b solana_account_info::AccountInfo<'a>, bool, bool)>, +} diff --git a/e2e/dummy/src/generated/instructions/instruction2.rs b/e2e/dummy/src/generated/instructions/instruction2.rs index d946ef0..2ff4c32 100644 --- a/e2e/dummy/src/generated/instructions/instruction2.rs +++ b/e2e/dummy/src/generated/instructions/instruction2.rs @@ -161,9 +161,9 @@ pub struct Instruction2CpiBuilder<'a, 'b> { } impl<'a, 'b> Instruction2CpiBuilder<'a, 'b> { - pub fn new(program: &'b solana_account_info::AccountInfo<'a>) -> Self { + pub fn new(__program: &'b solana_account_info::AccountInfo<'a>) -> Self { let instruction = Box::new(Instruction2CpiBuilderInstruction { - __program: program, + __program, __remaining_accounts: Vec::new(), }); Self { instruction } diff --git a/e2e/dummy/src/generated/instructions/instruction3.rs b/e2e/dummy/src/generated/instructions/instruction3.rs index 876b035..631f78e 100644 --- a/e2e/dummy/src/generated/instructions/instruction3.rs +++ b/e2e/dummy/src/generated/instructions/instruction3.rs @@ -165,9 +165,9 @@ pub struct Instruction3CpiBuilder<'a, 'b> { } impl<'a, 'b> Instruction3CpiBuilder<'a, 'b> { - pub fn new(program: &'b solana_account_info::AccountInfo<'a>) -> Self { + pub fn new(__program: &'b solana_account_info::AccountInfo<'a>) -> Self { let instruction = Box::new(Instruction3CpiBuilderInstruction { - __program: program, + __program, __remaining_accounts: Vec::new(), }); Self { instruction } diff --git a/e2e/dummy/src/generated/instructions/instruction4.rs b/e2e/dummy/src/generated/instructions/instruction4.rs index 860b06e..817fc74 100644 --- a/e2e/dummy/src/generated/instructions/instruction4.rs +++ b/e2e/dummy/src/generated/instructions/instruction4.rs @@ -74,20 +74,18 @@ impl Instruction4InstructionArgs { /// /// ### Accounts: /// -#[derive(Clone, Debug, Default)] +#[derive(Clone, Debug)] pub struct Instruction4Builder { - my_argument: Option, + my_argument: u64, __remaining_accounts: Vec, } impl Instruction4Builder { - pub fn new() -> Self { - Self::default() - } - #[inline(always)] - pub fn my_argument(&mut self, my_argument: u64) -> &mut Self { - self.my_argument = Some(my_argument); - self + pub fn new(my_argument: u64) -> Self { + Self { + my_argument, + __remaining_accounts: Vec::new(), + } } /// Add an additional account to the instruction. #[inline(always)] @@ -108,7 +106,7 @@ impl Instruction4Builder { pub fn instruction(&self) -> solana_instruction::Instruction { let accounts = Instruction4 {}; let args = Instruction4InstructionArgs { - my_argument: self.my_argument.clone().expect("my_argument is not set"), + my_argument: self.my_argument.clone(), }; accounts.instruction_with_remaining_accounts(args, &self.__remaining_accounts) @@ -197,19 +195,14 @@ pub struct Instruction4CpiBuilder<'a, 'b> { } impl<'a, 'b> Instruction4CpiBuilder<'a, 'b> { - pub fn new(program: &'b solana_account_info::AccountInfo<'a>) -> Self { + pub fn new(__program: &'b solana_account_info::AccountInfo<'a>, my_argument: u64) -> Self { let instruction = Box::new(Instruction4CpiBuilderInstruction { - __program: program, - my_argument: None, + __program, + my_argument, __remaining_accounts: Vec::new(), }); Self { instruction } } - #[inline(always)] - pub fn my_argument(&mut self, my_argument: u64) -> &mut Self { - self.instruction.my_argument = Some(my_argument); - self - } /// Add an additional account to the instruction. #[inline(always)] pub fn add_remaining_account( @@ -245,11 +238,7 @@ impl<'a, 'b> Instruction4CpiBuilder<'a, 'b> { #[allow(clippy::vec_init_then_push)] pub fn invoke_signed(&self, signers_seeds: &[&[&[u8]]]) -> solana_program_error::ProgramResult { let args = Instruction4InstructionArgs { - my_argument: self - .instruction - .my_argument - .clone() - .expect("my_argument is not set"), + my_argument: self.instruction.my_argument.clone(), }; let instruction = Instruction4Cpi { __program: self.instruction.__program, @@ -265,7 +254,7 @@ impl<'a, 'b> Instruction4CpiBuilder<'a, 'b> { #[derive(Clone, Debug)] struct Instruction4CpiBuilderInstruction<'a, 'b> { __program: &'b solana_account_info::AccountInfo<'a>, - my_argument: Option, + my_argument: u64, /// Additional instruction accounts `(AccountInfo, is_writable, is_signer)`. __remaining_accounts: Vec<(&'b solana_account_info::AccountInfo<'a>, bool, bool)>, } diff --git a/e2e/dummy/src/generated/instructions/instruction5.rs b/e2e/dummy/src/generated/instructions/instruction5.rs index da1301e..2b335d6 100644 --- a/e2e/dummy/src/generated/instructions/instruction5.rs +++ b/e2e/dummy/src/generated/instructions/instruction5.rs @@ -198,9 +198,9 @@ pub struct Instruction5CpiBuilder<'a, 'b> { } impl<'a, 'b> Instruction5CpiBuilder<'a, 'b> { - pub fn new(program: &'b solana_account_info::AccountInfo<'a>) -> Self { + pub fn new(__program: &'b solana_account_info::AccountInfo<'a>) -> Self { let instruction = Box::new(Instruction5CpiBuilderInstruction { - __program: program, + __program, my_argument: None, __remaining_accounts: Vec::new(), }); diff --git a/e2e/dummy/src/generated/instructions/instruction6.rs b/e2e/dummy/src/generated/instructions/instruction6.rs index a6762bf..8d64e61 100644 --- a/e2e/dummy/src/generated/instructions/instruction6.rs +++ b/e2e/dummy/src/generated/instructions/instruction6.rs @@ -61,20 +61,18 @@ impl Default for Instruction6InstructionData { /// ### Accounts: /// /// 0. `[writable]` my_account -#[derive(Clone, Debug, Default)] +#[derive(Clone, Debug)] pub struct Instruction6Builder { - my_account: Option, + my_account: solana_address::Address, __remaining_accounts: Vec, } impl Instruction6Builder { - pub fn new() -> Self { - Self::default() - } - #[inline(always)] - pub fn my_account(&mut self, my_account: solana_address::Address) -> &mut Self { - self.my_account = Some(my_account); - self + pub fn new(my_account: solana_address::Address) -> Self { + Self { + my_account, + __remaining_accounts: Vec::new(), + } } /// Add an additional account to the instruction. #[inline(always)] @@ -93,9 +91,8 @@ impl Instruction6Builder { } #[allow(clippy::clone_on_copy)] pub fn instruction(&self) -> solana_instruction::Instruction { - let accounts = Instruction6 { - my_account: self.my_account.expect("my_account is not set"), - }; + let my_account = self.my_account; + let accounts = Instruction6 { my_account }; accounts.instruction_with_remaining_accounts(&self.__remaining_accounts) } @@ -192,22 +189,17 @@ pub struct Instruction6CpiBuilder<'a, 'b> { } impl<'a, 'b> Instruction6CpiBuilder<'a, 'b> { - pub fn new(program: &'b solana_account_info::AccountInfo<'a>) -> Self { + pub fn new( + __program: &'b solana_account_info::AccountInfo<'a>, + my_account: &'b solana_account_info::AccountInfo<'a>, + ) -> Self { let instruction = Box::new(Instruction6CpiBuilderInstruction { - __program: program, - my_account: None, + __program, + my_account, __remaining_accounts: Vec::new(), }); Self { instruction } } - #[inline(always)] - pub fn my_account( - &mut self, - my_account: &'b solana_account_info::AccountInfo<'a>, - ) -> &mut Self { - self.instruction.my_account = Some(my_account); - self - } /// Add an additional account to the instruction. #[inline(always)] pub fn add_remaining_account( @@ -244,8 +236,7 @@ impl<'a, 'b> Instruction6CpiBuilder<'a, 'b> { pub fn invoke_signed(&self, signers_seeds: &[&[&[u8]]]) -> solana_program_error::ProgramResult { let instruction = Instruction6Cpi { __program: self.instruction.__program, - - my_account: self.instruction.my_account.expect("my_account is not set"), + my_account: self.instruction.my_account, }; instruction.invoke_signed_with_remaining_accounts( signers_seeds, @@ -257,7 +248,7 @@ impl<'a, 'b> Instruction6CpiBuilder<'a, 'b> { #[derive(Clone, Debug)] struct Instruction6CpiBuilderInstruction<'a, 'b> { __program: &'b solana_account_info::AccountInfo<'a>, - my_account: Option<&'b solana_account_info::AccountInfo<'a>>, + my_account: &'b solana_account_info::AccountInfo<'a>, /// Additional instruction accounts `(AccountInfo, is_writable, is_signer)`. __remaining_accounts: Vec<(&'b solana_account_info::AccountInfo<'a>, bool, bool)>, } diff --git a/e2e/dummy/src/generated/instructions/instruction7.rs b/e2e/dummy/src/generated/instructions/instruction7.rs index fff4818..2cdcb36 100644 --- a/e2e/dummy/src/generated/instructions/instruction7.rs +++ b/e2e/dummy/src/generated/instructions/instruction7.rs @@ -101,9 +101,8 @@ impl Instruction7Builder { } #[allow(clippy::clone_on_copy)] pub fn instruction(&self) -> solana_instruction::Instruction { - let accounts = Instruction7 { - my_account: self.my_account, - }; + let my_account = self.my_account; + let accounts = Instruction7 { my_account }; accounts.instruction_with_remaining_accounts(&self.__remaining_accounts) } @@ -206,9 +205,9 @@ pub struct Instruction7CpiBuilder<'a, 'b> { } impl<'a, 'b> Instruction7CpiBuilder<'a, 'b> { - pub fn new(program: &'b solana_account_info::AccountInfo<'a>) -> Self { + pub fn new(__program: &'b solana_account_info::AccountInfo<'a>) -> Self { let instruction = Box::new(Instruction7CpiBuilderInstruction { - __program: program, + __program, my_account: None, __remaining_accounts: Vec::new(), }); @@ -259,7 +258,6 @@ impl<'a, 'b> Instruction7CpiBuilder<'a, 'b> { pub fn invoke_signed(&self, signers_seeds: &[&[&[u8]]]) -> solana_program_error::ProgramResult { let instruction = Instruction7Cpi { __program: self.instruction.__program, - my_account: self.instruction.my_account, }; instruction.invoke_signed_with_remaining_accounts( diff --git a/e2e/dummy/src/generated/instructions/instruction8.rs b/e2e/dummy/src/generated/instructions/instruction8.rs index 03d5eb9..fc926c5 100644 --- a/e2e/dummy/src/generated/instructions/instruction8.rs +++ b/e2e/dummy/src/generated/instructions/instruction8.rs @@ -77,22 +77,22 @@ impl Default for Instruction8InstructionData { /// 0. `[]` mint /// 1. `[optional]` token_program (default to `TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA`) /// 2. `[writable, optional]` derived_account (default to PDA derived from 'derivedAccount') -#[derive(Clone, Debug, Default)] +#[derive(Clone, Debug)] pub struct Instruction8Builder { - mint: Option, + mint: solana_address::Address, token_program: Option, derived_account: Option, __remaining_accounts: Vec, } impl Instruction8Builder { - pub fn new() -> Self { - Self::default() - } - #[inline(always)] - pub fn mint(&mut self, mint: solana_address::Address) -> &mut Self { - self.mint = Some(mint); - self + pub fn new(mint: solana_address::Address) -> Self { + Self { + mint, + token_program: None, + derived_account: None, + __remaining_accounts: Vec::new(), + } } /// `[optional account, default to 'TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA']` #[inline(always)] @@ -123,9 +123,13 @@ impl Instruction8Builder { } #[allow(clippy::clone_on_copy)] pub fn instruction(&self) -> solana_instruction::Instruction { + let mint = self.mint; + let token_program = self.token_program.unwrap_or(solana_address::address!( + "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA" + )); let derived_account = self.derived_account.unwrap_or_else(|| { crate::pdas::find_derived_account_pda( - &self.mint.expect("mint is needed for derived_account PDA"), + &self.mint, &self.token_program.unwrap_or(solana_address::address!( "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA" )), @@ -133,10 +137,8 @@ impl Instruction8Builder { .0 }); let accounts = Instruction8 { - mint: self.mint.expect("mint is not set"), - token_program: self.token_program.unwrap_or(solana_address::address!( - "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA" - )), + mint, + token_program, derived_account, }; @@ -257,37 +259,21 @@ pub struct Instruction8CpiBuilder<'a, 'b> { } impl<'a, 'b> Instruction8CpiBuilder<'a, 'b> { - pub fn new(program: &'b solana_account_info::AccountInfo<'a>) -> Self { + pub fn new( + __program: &'b solana_account_info::AccountInfo<'a>, + mint: &'b solana_account_info::AccountInfo<'a>, + token_program: &'b solana_account_info::AccountInfo<'a>, + derived_account: &'b solana_account_info::AccountInfo<'a>, + ) -> Self { let instruction = Box::new(Instruction8CpiBuilderInstruction { - __program: program, - mint: None, - token_program: None, - derived_account: None, + __program, + mint, + token_program, + derived_account, __remaining_accounts: Vec::new(), }); Self { instruction } } - #[inline(always)] - pub fn mint(&mut self, mint: &'b solana_account_info::AccountInfo<'a>) -> &mut Self { - self.instruction.mint = Some(mint); - self - } - #[inline(always)] - pub fn token_program( - &mut self, - token_program: &'b solana_account_info::AccountInfo<'a>, - ) -> &mut Self { - self.instruction.token_program = Some(token_program); - self - } - #[inline(always)] - pub fn derived_account( - &mut self, - derived_account: &'b solana_account_info::AccountInfo<'a>, - ) -> &mut Self { - self.instruction.derived_account = Some(derived_account); - self - } /// Add an additional account to the instruction. #[inline(always)] pub fn add_remaining_account( @@ -324,18 +310,9 @@ impl<'a, 'b> Instruction8CpiBuilder<'a, 'b> { pub fn invoke_signed(&self, signers_seeds: &[&[&[u8]]]) -> solana_program_error::ProgramResult { let instruction = Instruction8Cpi { __program: self.instruction.__program, - - mint: self.instruction.mint.expect("mint is not set"), - - token_program: self - .instruction - .token_program - .expect("token_program is not set"), - - derived_account: self - .instruction - .derived_account - .expect("derived_account is not set"), + mint: self.instruction.mint, + token_program: self.instruction.token_program, + derived_account: self.instruction.derived_account, }; instruction.invoke_signed_with_remaining_accounts( signers_seeds, @@ -347,9 +324,9 @@ impl<'a, 'b> Instruction8CpiBuilder<'a, 'b> { #[derive(Clone, Debug)] struct Instruction8CpiBuilderInstruction<'a, 'b> { __program: &'b solana_account_info::AccountInfo<'a>, - mint: Option<&'b solana_account_info::AccountInfo<'a>>, - token_program: Option<&'b solana_account_info::AccountInfo<'a>>, - derived_account: Option<&'b solana_account_info::AccountInfo<'a>>, + mint: &'b solana_account_info::AccountInfo<'a>, + token_program: &'b solana_account_info::AccountInfo<'a>, + derived_account: &'b solana_account_info::AccountInfo<'a>, /// Additional instruction accounts `(AccountInfo, is_writable, is_signer)`. __remaining_accounts: Vec<(&'b solana_account_info::AccountInfo<'a>, bool, bool)>, } diff --git a/e2e/dummy/src/generated/instructions/instruction9.rs b/e2e/dummy/src/generated/instructions/instruction9.rs index 95e628a..597ee5e 100644 --- a/e2e/dummy/src/generated/instructions/instruction9.rs +++ b/e2e/dummy/src/generated/instructions/instruction9.rs @@ -197,22 +197,17 @@ pub struct Instruction9CpiBuilder<'a, 'b> { } impl<'a, 'b> Instruction9CpiBuilder<'a, 'b> { - pub fn new(program: &'b solana_account_info::AccountInfo<'a>) -> Self { + pub fn new( + __program: &'b solana_account_info::AccountInfo<'a>, + global_config: &'b solana_account_info::AccountInfo<'a>, + ) -> Self { let instruction = Box::new(Instruction9CpiBuilderInstruction { - __program: program, - global_config: None, + __program, + global_config, __remaining_accounts: Vec::new(), }); Self { instruction } } - #[inline(always)] - pub fn global_config( - &mut self, - global_config: &'b solana_account_info::AccountInfo<'a>, - ) -> &mut Self { - self.instruction.global_config = Some(global_config); - self - } /// Add an additional account to the instruction. #[inline(always)] pub fn add_remaining_account( @@ -249,11 +244,7 @@ impl<'a, 'b> Instruction9CpiBuilder<'a, 'b> { pub fn invoke_signed(&self, signers_seeds: &[&[&[u8]]]) -> solana_program_error::ProgramResult { let instruction = Instruction9Cpi { __program: self.instruction.__program, - - global_config: self - .instruction - .global_config - .expect("global_config is not set"), + global_config: self.instruction.global_config, }; instruction.invoke_signed_with_remaining_accounts( signers_seeds, @@ -265,7 +256,7 @@ impl<'a, 'b> Instruction9CpiBuilder<'a, 'b> { #[derive(Clone, Debug)] struct Instruction9CpiBuilderInstruction<'a, 'b> { __program: &'b solana_account_info::AccountInfo<'a>, - global_config: Option<&'b solana_account_info::AccountInfo<'a>>, + global_config: &'b solana_account_info::AccountInfo<'a>, /// Additional instruction accounts `(AccountInfo, is_writable, is_signer)`. __remaining_accounts: Vec<(&'b solana_account_info::AccountInfo<'a>, bool, bool)>, } diff --git a/e2e/dummy/src/generated/instructions/mod.rs b/e2e/dummy/src/generated/instructions/mod.rs index 5f90c99..2fe4073 100644 --- a/e2e/dummy/src/generated/instructions/mod.rs +++ b/e2e/dummy/src/generated/instructions/mod.rs @@ -6,6 +6,7 @@ //! pub(crate) mod r#instruction1; +pub(crate) mod r#instruction10; pub(crate) mod r#instruction2; pub(crate) mod r#instruction3; pub(crate) mod r#instruction4; @@ -16,6 +17,7 @@ pub(crate) mod r#instruction8; pub(crate) mod r#instruction9; pub use self::r#instruction1::*; +pub use self::r#instruction10::*; pub use self::r#instruction2::*; pub use self::r#instruction3::*; pub use self::r#instruction4::*; diff --git a/e2e/governance/src/generated/instructions/add_required_signatory.rs b/e2e/governance/src/generated/instructions/add_required_signatory.rs index 90c1920..fb0627a 100644 --- a/e2e/governance/src/generated/instructions/add_required_signatory.rs +++ b/e2e/governance/src/generated/instructions/add_required_signatory.rs @@ -109,38 +109,31 @@ impl AddRequiredSignatoryInstructionArgs { /// 1. `[writable]` required_signatory_account /// 2. `[signer]` payer /// 3. `[optional]` system_program (default to `11111111111111111111111111111111`) -#[derive(Clone, Debug, Default)] +#[derive(Clone, Debug)] pub struct AddRequiredSignatoryBuilder { - governance_account: Option, - required_signatory_account: Option, - payer: Option, + governance_account: solana_address::Address, + required_signatory_account: solana_address::Address, + payer: solana_address::Address, system_program: Option, - signatory: Option
, + signatory: Address, __remaining_accounts: Vec, } impl AddRequiredSignatoryBuilder { - pub fn new() -> Self { - Self::default() - } - /// The Governance account the config is for - #[inline(always)] - pub fn governance_account(&mut self, governance_account: solana_address::Address) -> &mut Self { - self.governance_account = Some(governance_account); - self - } - #[inline(always)] - pub fn required_signatory_account( - &mut self, + pub fn new( + governance_account: solana_address::Address, required_signatory_account: solana_address::Address, - ) -> &mut Self { - self.required_signatory_account = Some(required_signatory_account); - self - } - #[inline(always)] - pub fn payer(&mut self, payer: solana_address::Address) -> &mut Self { - self.payer = Some(payer); - self + payer: solana_address::Address, + signatory: Address, + ) -> Self { + Self { + governance_account, + required_signatory_account, + payer, + system_program: None, + signatory, + __remaining_accounts: Vec::new(), + } } /// `[optional account, default to '11111111111111111111111111111111']` #[inline(always)] @@ -148,11 +141,6 @@ impl AddRequiredSignatoryBuilder { self.system_program = Some(system_program); self } - #[inline(always)] - pub fn signatory(&mut self, signatory: Address) -> &mut Self { - self.signatory = Some(signatory); - self - } /// Add an additional account to the instruction. #[inline(always)] pub fn add_remaining_account(&mut self, account: solana_instruction::AccountMeta) -> &mut Self { @@ -170,20 +158,20 @@ impl AddRequiredSignatoryBuilder { } #[allow(clippy::clone_on_copy)] pub fn instruction(&self) -> solana_instruction::Instruction { + let governance_account = self.governance_account; + let required_signatory_account = self.required_signatory_account; + let payer = self.payer; + let system_program = self + .system_program + .unwrap_or(solana_address::address!("11111111111111111111111111111111")); let accounts = AddRequiredSignatory { - governance_account: self - .governance_account - .expect("governance_account is not set"), - required_signatory_account: self - .required_signatory_account - .expect("required_signatory_account is not set"), - payer: self.payer.expect("payer is not set"), - system_program: self - .system_program - .unwrap_or(solana_address::address!("11111111111111111111111111111111")), + governance_account, + required_signatory_account, + payer, + system_program, }; let args = AddRequiredSignatoryInstructionArgs { - signatory: self.signatory.clone().expect("signatory is not set"), + signatory: self.signatory.clone(), }; accounts.instruction_with_remaining_accounts(args, &self.__remaining_accounts) @@ -323,53 +311,25 @@ pub struct AddRequiredSignatoryCpiBuilder<'a, 'b> { } impl<'a, 'b> AddRequiredSignatoryCpiBuilder<'a, 'b> { - pub fn new(program: &'b solana_account_info::AccountInfo<'a>) -> Self { + pub fn new( + __program: &'b solana_account_info::AccountInfo<'a>, + governance_account: &'b solana_account_info::AccountInfo<'a>, + required_signatory_account: &'b solana_account_info::AccountInfo<'a>, + payer: &'b solana_account_info::AccountInfo<'a>, + system_program: &'b solana_account_info::AccountInfo<'a>, + signatory: Address, + ) -> Self { let instruction = Box::new(AddRequiredSignatoryCpiBuilderInstruction { - __program: program, - governance_account: None, - required_signatory_account: None, - payer: None, - system_program: None, - signatory: None, + __program, + governance_account, + required_signatory_account, + payer, + system_program, + signatory, __remaining_accounts: Vec::new(), }); Self { instruction } } - /// The Governance account the config is for - #[inline(always)] - pub fn governance_account( - &mut self, - governance_account: &'b solana_account_info::AccountInfo<'a>, - ) -> &mut Self { - self.instruction.governance_account = Some(governance_account); - self - } - #[inline(always)] - pub fn required_signatory_account( - &mut self, - required_signatory_account: &'b solana_account_info::AccountInfo<'a>, - ) -> &mut Self { - self.instruction.required_signatory_account = Some(required_signatory_account); - self - } - #[inline(always)] - pub fn payer(&mut self, payer: &'b solana_account_info::AccountInfo<'a>) -> &mut Self { - self.instruction.payer = Some(payer); - self - } - #[inline(always)] - pub fn system_program( - &mut self, - system_program: &'b solana_account_info::AccountInfo<'a>, - ) -> &mut Self { - self.instruction.system_program = Some(system_program); - self - } - #[inline(always)] - pub fn signatory(&mut self, signatory: Address) -> &mut Self { - self.instruction.signatory = Some(signatory); - self - } /// Add an additional account to the instruction. #[inline(always)] pub fn add_remaining_account( @@ -405,31 +365,14 @@ impl<'a, 'b> AddRequiredSignatoryCpiBuilder<'a, 'b> { #[allow(clippy::vec_init_then_push)] pub fn invoke_signed(&self, signers_seeds: &[&[&[u8]]]) -> solana_program_error::ProgramResult { let args = AddRequiredSignatoryInstructionArgs { - signatory: self - .instruction - .signatory - .clone() - .expect("signatory is not set"), + signatory: self.instruction.signatory.clone(), }; let instruction = AddRequiredSignatoryCpi { __program: self.instruction.__program, - - governance_account: self - .instruction - .governance_account - .expect("governance_account is not set"), - - required_signatory_account: self - .instruction - .required_signatory_account - .expect("required_signatory_account is not set"), - - payer: self.instruction.payer.expect("payer is not set"), - - system_program: self - .instruction - .system_program - .expect("system_program is not set"), + governance_account: self.instruction.governance_account, + required_signatory_account: self.instruction.required_signatory_account, + payer: self.instruction.payer, + system_program: self.instruction.system_program, __args: args, }; instruction.invoke_signed_with_remaining_accounts( @@ -442,11 +385,11 @@ impl<'a, 'b> AddRequiredSignatoryCpiBuilder<'a, 'b> { #[derive(Clone, Debug)] struct AddRequiredSignatoryCpiBuilderInstruction<'a, 'b> { __program: &'b solana_account_info::AccountInfo<'a>, - governance_account: Option<&'b solana_account_info::AccountInfo<'a>>, - required_signatory_account: Option<&'b solana_account_info::AccountInfo<'a>>, - payer: Option<&'b solana_account_info::AccountInfo<'a>>, - system_program: Option<&'b solana_account_info::AccountInfo<'a>>, - signatory: Option
, + governance_account: &'b solana_account_info::AccountInfo<'a>, + required_signatory_account: &'b solana_account_info::AccountInfo<'a>, + payer: &'b solana_account_info::AccountInfo<'a>, + system_program: &'b solana_account_info::AccountInfo<'a>, + signatory: Address, /// Additional instruction accounts `(AccountInfo, is_writable, is_signer)`. __remaining_accounts: Vec<(&'b solana_account_info::AccountInfo<'a>, bool, bool)>, } diff --git a/e2e/governance/src/generated/instructions/add_signatory.rs b/e2e/governance/src/generated/instructions/add_signatory.rs index d55d00a..d1deb2e 100644 --- a/e2e/governance/src/generated/instructions/add_signatory.rs +++ b/e2e/governance/src/generated/instructions/add_signatory.rs @@ -121,56 +121,37 @@ impl AddSignatoryInstructionArgs { /// 3. `[writable]` signatory_record_account /// 4. `[signer]` payer /// 5. `[optional]` system_program (default to `11111111111111111111111111111111`) -#[derive(Clone, Debug, Default)] +#[derive(Clone, Debug)] pub struct AddSignatoryBuilder { - proposal_account: Option, - token_owner_record: Option, - governance_authority: Option, - signatory_record_account: Option, - payer: Option, + proposal_account: solana_address::Address, + token_owner_record: solana_address::Address, + governance_authority: solana_address::Address, + signatory_record_account: solana_address::Address, + payer: solana_address::Address, system_program: Option, - signatory: Option
, + signatory: Address, __remaining_accounts: Vec, } impl AddSignatoryBuilder { - pub fn new() -> Self { - Self::default() - } - /// Proposal Account associated with the governance - #[inline(always)] - pub fn proposal_account(&mut self, proposal_account: solana_address::Address) -> &mut Self { - self.proposal_account = Some(proposal_account); - self - } - /// TokenOwnerRecord account of the Proposal owner - #[inline(always)] - pub fn token_owner_record(&mut self, token_owner_record: solana_address::Address) -> &mut Self { - self.token_owner_record = Some(token_owner_record); - self - } - /// Governance Authority (Token Owner or Governance Delegate) - #[inline(always)] - pub fn governance_authority( - &mut self, + pub fn new( + proposal_account: solana_address::Address, + token_owner_record: solana_address::Address, governance_authority: solana_address::Address, - ) -> &mut Self { - self.governance_authority = Some(governance_authority); - self - } - /// Signatory Record Account - #[inline(always)] - pub fn signatory_record_account( - &mut self, signatory_record_account: solana_address::Address, - ) -> &mut Self { - self.signatory_record_account = Some(signatory_record_account); - self - } - #[inline(always)] - pub fn payer(&mut self, payer: solana_address::Address) -> &mut Self { - self.payer = Some(payer); - self + payer: solana_address::Address, + signatory: Address, + ) -> Self { + Self { + proposal_account, + token_owner_record, + governance_authority, + signatory_record_account, + payer, + system_program: None, + signatory, + __remaining_accounts: Vec::new(), + } } /// `[optional account, default to '11111111111111111111111111111111']` #[inline(always)] @@ -178,11 +159,6 @@ impl AddSignatoryBuilder { self.system_program = Some(system_program); self } - #[inline(always)] - pub fn signatory(&mut self, signatory: Address) -> &mut Self { - self.signatory = Some(signatory); - self - } /// Add an additional account to the instruction. #[inline(always)] pub fn add_remaining_account(&mut self, account: solana_instruction::AccountMeta) -> &mut Self { @@ -200,24 +176,24 @@ impl AddSignatoryBuilder { } #[allow(clippy::clone_on_copy)] pub fn instruction(&self) -> solana_instruction::Instruction { + let proposal_account = self.proposal_account; + let token_owner_record = self.token_owner_record; + let governance_authority = self.governance_authority; + let signatory_record_account = self.signatory_record_account; + let payer = self.payer; + let system_program = self + .system_program + .unwrap_or(solana_address::address!("11111111111111111111111111111111")); let accounts = AddSignatory { - proposal_account: self.proposal_account.expect("proposal_account is not set"), - token_owner_record: self - .token_owner_record - .expect("token_owner_record is not set"), - governance_authority: self - .governance_authority - .expect("governance_authority is not set"), - signatory_record_account: self - .signatory_record_account - .expect("signatory_record_account is not set"), - payer: self.payer.expect("payer is not set"), - system_program: self - .system_program - .unwrap_or(solana_address::address!("11111111111111111111111111111111")), + proposal_account, + token_owner_record, + governance_authority, + signatory_record_account, + payer, + system_program, }; let args = AddSignatoryInstructionArgs { - signatory: self.signatory.clone().expect("signatory is not set"), + signatory: self.signatory.clone(), }; accounts.instruction_with_remaining_accounts(args, &self.__remaining_accounts) @@ -377,73 +353,28 @@ pub struct AddSignatoryCpiBuilder<'a, 'b> { } impl<'a, 'b> AddSignatoryCpiBuilder<'a, 'b> { - pub fn new(program: &'b solana_account_info::AccountInfo<'a>) -> Self { - let instruction = Box::new(AddSignatoryCpiBuilderInstruction { - __program: program, - proposal_account: None, - token_owner_record: None, - governance_authority: None, - signatory_record_account: None, - payer: None, - system_program: None, - signatory: None, - __remaining_accounts: Vec::new(), - }); - Self { instruction } - } - /// Proposal Account associated with the governance - #[inline(always)] - pub fn proposal_account( - &mut self, + pub fn new( + __program: &'b solana_account_info::AccountInfo<'a>, proposal_account: &'b solana_account_info::AccountInfo<'a>, - ) -> &mut Self { - self.instruction.proposal_account = Some(proposal_account); - self - } - /// TokenOwnerRecord account of the Proposal owner - #[inline(always)] - pub fn token_owner_record( - &mut self, token_owner_record: &'b solana_account_info::AccountInfo<'a>, - ) -> &mut Self { - self.instruction.token_owner_record = Some(token_owner_record); - self - } - /// Governance Authority (Token Owner or Governance Delegate) - #[inline(always)] - pub fn governance_authority( - &mut self, governance_authority: &'b solana_account_info::AccountInfo<'a>, - ) -> &mut Self { - self.instruction.governance_authority = Some(governance_authority); - self - } - /// Signatory Record Account - #[inline(always)] - pub fn signatory_record_account( - &mut self, signatory_record_account: &'b solana_account_info::AccountInfo<'a>, - ) -> &mut Self { - self.instruction.signatory_record_account = Some(signatory_record_account); - self - } - #[inline(always)] - pub fn payer(&mut self, payer: &'b solana_account_info::AccountInfo<'a>) -> &mut Self { - self.instruction.payer = Some(payer); - self - } - #[inline(always)] - pub fn system_program( - &mut self, + payer: &'b solana_account_info::AccountInfo<'a>, system_program: &'b solana_account_info::AccountInfo<'a>, - ) -> &mut Self { - self.instruction.system_program = Some(system_program); - self - } - #[inline(always)] - pub fn signatory(&mut self, signatory: Address) -> &mut Self { - self.instruction.signatory = Some(signatory); - self + signatory: Address, + ) -> Self { + let instruction = Box::new(AddSignatoryCpiBuilderInstruction { + __program, + proposal_account, + token_owner_record, + governance_authority, + signatory_record_account, + payer, + system_program, + signatory, + __remaining_accounts: Vec::new(), + }); + Self { instruction } } /// Add an additional account to the instruction. #[inline(always)] @@ -480,41 +411,16 @@ impl<'a, 'b> AddSignatoryCpiBuilder<'a, 'b> { #[allow(clippy::vec_init_then_push)] pub fn invoke_signed(&self, signers_seeds: &[&[&[u8]]]) -> solana_program_error::ProgramResult { let args = AddSignatoryInstructionArgs { - signatory: self - .instruction - .signatory - .clone() - .expect("signatory is not set"), + signatory: self.instruction.signatory.clone(), }; let instruction = AddSignatoryCpi { __program: self.instruction.__program, - - proposal_account: self - .instruction - .proposal_account - .expect("proposal_account is not set"), - - token_owner_record: self - .instruction - .token_owner_record - .expect("token_owner_record is not set"), - - governance_authority: self - .instruction - .governance_authority - .expect("governance_authority is not set"), - - signatory_record_account: self - .instruction - .signatory_record_account - .expect("signatory_record_account is not set"), - - payer: self.instruction.payer.expect("payer is not set"), - - system_program: self - .instruction - .system_program - .expect("system_program is not set"), + proposal_account: self.instruction.proposal_account, + token_owner_record: self.instruction.token_owner_record, + governance_authority: self.instruction.governance_authority, + signatory_record_account: self.instruction.signatory_record_account, + payer: self.instruction.payer, + system_program: self.instruction.system_program, __args: args, }; instruction.invoke_signed_with_remaining_accounts( @@ -527,13 +433,13 @@ impl<'a, 'b> AddSignatoryCpiBuilder<'a, 'b> { #[derive(Clone, Debug)] struct AddSignatoryCpiBuilderInstruction<'a, 'b> { __program: &'b solana_account_info::AccountInfo<'a>, - proposal_account: Option<&'b solana_account_info::AccountInfo<'a>>, - token_owner_record: Option<&'b solana_account_info::AccountInfo<'a>>, - governance_authority: Option<&'b solana_account_info::AccountInfo<'a>>, - signatory_record_account: Option<&'b solana_account_info::AccountInfo<'a>>, - payer: Option<&'b solana_account_info::AccountInfo<'a>>, - system_program: Option<&'b solana_account_info::AccountInfo<'a>>, - signatory: Option
, + proposal_account: &'b solana_account_info::AccountInfo<'a>, + token_owner_record: &'b solana_account_info::AccountInfo<'a>, + governance_authority: &'b solana_account_info::AccountInfo<'a>, + signatory_record_account: &'b solana_account_info::AccountInfo<'a>, + payer: &'b solana_account_info::AccountInfo<'a>, + system_program: &'b solana_account_info::AccountInfo<'a>, + signatory: Address, /// Additional instruction accounts `(AccountInfo, is_writable, is_signer)`. __remaining_accounts: Vec<(&'b solana_account_info::AccountInfo<'a>, bool, bool)>, } diff --git a/e2e/governance/src/generated/instructions/cancel_proposal.rs b/e2e/governance/src/generated/instructions/cancel_proposal.rs index 7d8976d..a027923 100644 --- a/e2e/governance/src/generated/instructions/cancel_proposal.rs +++ b/e2e/governance/src/generated/instructions/cancel_proposal.rs @@ -96,49 +96,32 @@ impl Default for CancelProposalInstructionData { /// 2. `[writable]` proposal_account /// 3. `[writable]` token_owner_record /// 4. `[signer]` governance_authority -#[derive(Clone, Debug, Default)] +#[derive(Clone, Debug)] pub struct CancelProposalBuilder { - realm_account: Option, - governance_account: Option, - proposal_account: Option, - token_owner_record: Option, - governance_authority: Option, + realm_account: solana_address::Address, + governance_account: solana_address::Address, + proposal_account: solana_address::Address, + token_owner_record: solana_address::Address, + governance_authority: solana_address::Address, __remaining_accounts: Vec, } impl CancelProposalBuilder { - pub fn new() -> Self { - Self::default() - } - #[inline(always)] - pub fn realm_account(&mut self, realm_account: solana_address::Address) -> &mut Self { - self.realm_account = Some(realm_account); - self - } - #[inline(always)] - pub fn governance_account(&mut self, governance_account: solana_address::Address) -> &mut Self { - self.governance_account = Some(governance_account); - self - } - #[inline(always)] - pub fn proposal_account(&mut self, proposal_account: solana_address::Address) -> &mut Self { - self.proposal_account = Some(proposal_account); - self - } - /// TokenOwnerRecord account of the Proposal owner - #[inline(always)] - pub fn token_owner_record(&mut self, token_owner_record: solana_address::Address) -> &mut Self { - self.token_owner_record = Some(token_owner_record); - self - } - /// Governance authority (Token Owner or Governance Delegate) - #[inline(always)] - pub fn governance_authority( - &mut self, + pub fn new( + realm_account: solana_address::Address, + governance_account: solana_address::Address, + proposal_account: solana_address::Address, + token_owner_record: solana_address::Address, governance_authority: solana_address::Address, - ) -> &mut Self { - self.governance_authority = Some(governance_authority); - self + ) -> Self { + Self { + realm_account, + governance_account, + proposal_account, + token_owner_record, + governance_authority, + __remaining_accounts: Vec::new(), + } } /// Add an additional account to the instruction. #[inline(always)] @@ -157,18 +140,17 @@ impl CancelProposalBuilder { } #[allow(clippy::clone_on_copy)] pub fn instruction(&self) -> solana_instruction::Instruction { + let realm_account = self.realm_account; + let governance_account = self.governance_account; + let proposal_account = self.proposal_account; + let token_owner_record = self.token_owner_record; + let governance_authority = self.governance_authority; let accounts = CancelProposal { - realm_account: self.realm_account.expect("realm_account is not set"), - governance_account: self - .governance_account - .expect("governance_account is not set"), - proposal_account: self.proposal_account.expect("proposal_account is not set"), - token_owner_record: self - .token_owner_record - .expect("token_owner_record is not set"), - governance_authority: self - .governance_authority - .expect("governance_authority is not set"), + realm_account, + governance_account, + proposal_account, + token_owner_record, + governance_authority, }; accounts.instruction_with_remaining_accounts(&self.__remaining_accounts) @@ -310,59 +292,24 @@ pub struct CancelProposalCpiBuilder<'a, 'b> { } impl<'a, 'b> CancelProposalCpiBuilder<'a, 'b> { - pub fn new(program: &'b solana_account_info::AccountInfo<'a>) -> Self { - let instruction = Box::new(CancelProposalCpiBuilderInstruction { - __program: program, - realm_account: None, - governance_account: None, - proposal_account: None, - token_owner_record: None, - governance_authority: None, - __remaining_accounts: Vec::new(), - }); - Self { instruction } - } - #[inline(always)] - pub fn realm_account( - &mut self, + pub fn new( + __program: &'b solana_account_info::AccountInfo<'a>, realm_account: &'b solana_account_info::AccountInfo<'a>, - ) -> &mut Self { - self.instruction.realm_account = Some(realm_account); - self - } - #[inline(always)] - pub fn governance_account( - &mut self, governance_account: &'b solana_account_info::AccountInfo<'a>, - ) -> &mut Self { - self.instruction.governance_account = Some(governance_account); - self - } - #[inline(always)] - pub fn proposal_account( - &mut self, proposal_account: &'b solana_account_info::AccountInfo<'a>, - ) -> &mut Self { - self.instruction.proposal_account = Some(proposal_account); - self - } - /// TokenOwnerRecord account of the Proposal owner - #[inline(always)] - pub fn token_owner_record( - &mut self, token_owner_record: &'b solana_account_info::AccountInfo<'a>, - ) -> &mut Self { - self.instruction.token_owner_record = Some(token_owner_record); - self - } - /// Governance authority (Token Owner or Governance Delegate) - #[inline(always)] - pub fn governance_authority( - &mut self, governance_authority: &'b solana_account_info::AccountInfo<'a>, - ) -> &mut Self { - self.instruction.governance_authority = Some(governance_authority); - self + ) -> Self { + let instruction = Box::new(CancelProposalCpiBuilderInstruction { + __program, + realm_account, + governance_account, + proposal_account, + token_owner_record, + governance_authority, + __remaining_accounts: Vec::new(), + }); + Self { instruction } } /// Add an additional account to the instruction. #[inline(always)] @@ -400,31 +347,11 @@ impl<'a, 'b> CancelProposalCpiBuilder<'a, 'b> { pub fn invoke_signed(&self, signers_seeds: &[&[&[u8]]]) -> solana_program_error::ProgramResult { let instruction = CancelProposalCpi { __program: self.instruction.__program, - - realm_account: self - .instruction - .realm_account - .expect("realm_account is not set"), - - governance_account: self - .instruction - .governance_account - .expect("governance_account is not set"), - - proposal_account: self - .instruction - .proposal_account - .expect("proposal_account is not set"), - - token_owner_record: self - .instruction - .token_owner_record - .expect("token_owner_record is not set"), - - governance_authority: self - .instruction - .governance_authority - .expect("governance_authority is not set"), + realm_account: self.instruction.realm_account, + governance_account: self.instruction.governance_account, + proposal_account: self.instruction.proposal_account, + token_owner_record: self.instruction.token_owner_record, + governance_authority: self.instruction.governance_authority, }; instruction.invoke_signed_with_remaining_accounts( signers_seeds, @@ -436,11 +363,11 @@ impl<'a, 'b> CancelProposalCpiBuilder<'a, 'b> { #[derive(Clone, Debug)] struct CancelProposalCpiBuilderInstruction<'a, 'b> { __program: &'b solana_account_info::AccountInfo<'a>, - realm_account: Option<&'b solana_account_info::AccountInfo<'a>>, - governance_account: Option<&'b solana_account_info::AccountInfo<'a>>, - proposal_account: Option<&'b solana_account_info::AccountInfo<'a>>, - token_owner_record: Option<&'b solana_account_info::AccountInfo<'a>>, - governance_authority: Option<&'b solana_account_info::AccountInfo<'a>>, + realm_account: &'b solana_account_info::AccountInfo<'a>, + governance_account: &'b solana_account_info::AccountInfo<'a>, + proposal_account: &'b solana_account_info::AccountInfo<'a>, + token_owner_record: &'b solana_account_info::AccountInfo<'a>, + governance_authority: &'b solana_account_info::AccountInfo<'a>, /// Additional instruction accounts `(AccountInfo, is_writable, is_signer)`. __remaining_accounts: Vec<(&'b solana_account_info::AccountInfo<'a>, bool, bool)>, } diff --git a/e2e/governance/src/generated/instructions/cast_vote.rs b/e2e/governance/src/generated/instructions/cast_vote.rs index 8fd76a9..b7def36 100644 --- a/e2e/governance/src/generated/instructions/cast_vote.rs +++ b/e2e/governance/src/generated/instructions/cast_vote.rs @@ -184,97 +184,56 @@ impl CastVoteInstructionArgs { /// 10. `[]` realm_config_account /// 11. `[optional]` voter_weight_record /// 12. `[optional]` max_voter_weight_record -#[derive(Clone, Debug, Default)] +#[derive(Clone, Debug)] pub struct CastVoteBuilder { - realm_account: Option, - governance_account: Option, - proposal_account: Option, - proposal_token_owner_record: Option, - voter_token_owner_record: Option, - governance_authority: Option, - proposal_vote_record: Option, - governing_token_mint: Option, - payer: Option, + realm_account: solana_address::Address, + governance_account: solana_address::Address, + proposal_account: solana_address::Address, + proposal_token_owner_record: solana_address::Address, + voter_token_owner_record: solana_address::Address, + governance_authority: solana_address::Address, + proposal_vote_record: solana_address::Address, + governing_token_mint: solana_address::Address, + payer: solana_address::Address, system_program: Option, - realm_config_account: Option, + realm_config_account: solana_address::Address, voter_weight_record: Option, max_voter_weight_record: Option, - vote: Option, + vote: Vote, __remaining_accounts: Vec, } impl CastVoteBuilder { - pub fn new() -> Self { - Self::default() - } - #[inline(always)] - pub fn realm_account(&mut self, realm_account: solana_address::Address) -> &mut Self { - self.realm_account = Some(realm_account); - self - } - #[inline(always)] - pub fn governance_account(&mut self, governance_account: solana_address::Address) -> &mut Self { - self.governance_account = Some(governance_account); - self - } - #[inline(always)] - pub fn proposal_account(&mut self, proposal_account: solana_address::Address) -> &mut Self { - self.proposal_account = Some(proposal_account); - self - } - /// TokenOwnerRecord of the Proposal owner - #[inline(always)] - pub fn proposal_token_owner_record( - &mut self, + pub fn new( + realm_account: solana_address::Address, + governance_account: solana_address::Address, + proposal_account: solana_address::Address, proposal_token_owner_record: solana_address::Address, - ) -> &mut Self { - self.proposal_token_owner_record = Some(proposal_token_owner_record); - self - } - /// TokenOwnerRecord of the voter. PDA seeds: ['governance',realm, vote_governing_token_mint, governing_token_owner] - #[inline(always)] - pub fn voter_token_owner_record( - &mut self, voter_token_owner_record: solana_address::Address, - ) -> &mut Self { - self.voter_token_owner_record = Some(voter_token_owner_record); - self - } - /// Governance Authority (Token Owner or Governance Delegate) - #[inline(always)] - pub fn governance_authority( - &mut self, governance_authority: solana_address::Address, - ) -> &mut Self { - self.governance_authority = Some(governance_authority); - self - } - /// Proposal VoteRecord account. PDA seeds: ['governance',proposal,token_owner_record] - #[inline(always)] - pub fn proposal_vote_record( - &mut self, proposal_vote_record: solana_address::Address, - ) -> &mut Self { - self.proposal_vote_record = Some(proposal_vote_record); - self - } - /// The Governing Token Mint which is used to cast the vote (vote_governing_token_mint). - /// The voting token mint is the governing_token_mint of the Proposal for Approve, Deny and Abstain votes. - /// For Veto vote the voting token mint is the mint of the opposite voting population. - /// Council mint to veto Community proposals and Community mint to veto Council proposals - /// Note: In the current version only Council veto is supported - #[inline(always)] - pub fn governing_token_mint( - &mut self, governing_token_mint: solana_address::Address, - ) -> &mut Self { - self.governing_token_mint = Some(governing_token_mint); - self - } - #[inline(always)] - pub fn payer(&mut self, payer: solana_address::Address) -> &mut Self { - self.payer = Some(payer); - self + payer: solana_address::Address, + realm_config_account: solana_address::Address, + vote: Vote, + ) -> Self { + Self { + realm_account, + governance_account, + proposal_account, + proposal_token_owner_record, + voter_token_owner_record, + governance_authority, + proposal_vote_record, + governing_token_mint, + payer, + system_program: None, + realm_config_account, + voter_weight_record: None, + max_voter_weight_record: None, + vote, + __remaining_accounts: Vec::new(), + } } /// `[optional account, default to '11111111111111111111111111111111']` #[inline(always)] @@ -282,15 +241,6 @@ impl CastVoteBuilder { self.system_program = Some(system_program); self } - /// RealmConfig account. PDA seeds: ['realm-config', realm] - #[inline(always)] - pub fn realm_config_account( - &mut self, - realm_config_account: solana_address::Address, - ) -> &mut Self { - self.realm_config_account = Some(realm_config_account); - self - } /// `[optional account]` /// Optional Voter Weight Record #[inline(always)] @@ -311,11 +261,6 @@ impl CastVoteBuilder { self.max_voter_weight_record = max_voter_weight_record; self } - #[inline(always)] - pub fn vote(&mut self, vote: Vote) -> &mut Self { - self.vote = Some(vote); - self - } /// Add an additional account to the instruction. #[inline(always)] pub fn add_remaining_account(&mut self, account: solana_instruction::AccountMeta) -> &mut Self { @@ -333,39 +278,38 @@ impl CastVoteBuilder { } #[allow(clippy::clone_on_copy)] pub fn instruction(&self) -> solana_instruction::Instruction { + let realm_account = self.realm_account; + let governance_account = self.governance_account; + let proposal_account = self.proposal_account; + let proposal_token_owner_record = self.proposal_token_owner_record; + let voter_token_owner_record = self.voter_token_owner_record; + let governance_authority = self.governance_authority; + let proposal_vote_record = self.proposal_vote_record; + let governing_token_mint = self.governing_token_mint; + let payer = self.payer; + let system_program = self + .system_program + .unwrap_or(solana_address::address!("11111111111111111111111111111111")); + let realm_config_account = self.realm_config_account; + let voter_weight_record = self.voter_weight_record; + let max_voter_weight_record = self.max_voter_weight_record; let accounts = CastVote { - realm_account: self.realm_account.expect("realm_account is not set"), - governance_account: self - .governance_account - .expect("governance_account is not set"), - proposal_account: self.proposal_account.expect("proposal_account is not set"), - proposal_token_owner_record: self - .proposal_token_owner_record - .expect("proposal_token_owner_record is not set"), - voter_token_owner_record: self - .voter_token_owner_record - .expect("voter_token_owner_record is not set"), - governance_authority: self - .governance_authority - .expect("governance_authority is not set"), - proposal_vote_record: self - .proposal_vote_record - .expect("proposal_vote_record is not set"), - governing_token_mint: self - .governing_token_mint - .expect("governing_token_mint is not set"), - payer: self.payer.expect("payer is not set"), - system_program: self - .system_program - .unwrap_or(solana_address::address!("11111111111111111111111111111111")), - realm_config_account: self - .realm_config_account - .expect("realm_config_account is not set"), - voter_weight_record: self.voter_weight_record, - max_voter_weight_record: self.max_voter_weight_record, + realm_account, + governance_account, + proposal_account, + proposal_token_owner_record, + voter_token_owner_record, + governance_authority, + proposal_vote_record, + governing_token_mint, + payer, + system_program, + realm_config_account, + voter_weight_record, + max_voter_weight_record, }; let args = CastVoteInstructionArgs { - vote: self.vote.clone().expect("vote is not set"), + vote: self.vote.clone(), }; accounts.instruction_with_remaining_accounts(args, &self.__remaining_accounts) @@ -627,121 +571,40 @@ pub struct CastVoteCpiBuilder<'a, 'b> { } impl<'a, 'b> CastVoteCpiBuilder<'a, 'b> { - pub fn new(program: &'b solana_account_info::AccountInfo<'a>) -> Self { - let instruction = Box::new(CastVoteCpiBuilderInstruction { - __program: program, - realm_account: None, - governance_account: None, - proposal_account: None, - proposal_token_owner_record: None, - voter_token_owner_record: None, - governance_authority: None, - proposal_vote_record: None, - governing_token_mint: None, - payer: None, - system_program: None, - realm_config_account: None, - voter_weight_record: None, - max_voter_weight_record: None, - vote: None, - __remaining_accounts: Vec::new(), - }); - Self { instruction } - } - #[inline(always)] - pub fn realm_account( - &mut self, + pub fn new( + __program: &'b solana_account_info::AccountInfo<'a>, realm_account: &'b solana_account_info::AccountInfo<'a>, - ) -> &mut Self { - self.instruction.realm_account = Some(realm_account); - self - } - #[inline(always)] - pub fn governance_account( - &mut self, governance_account: &'b solana_account_info::AccountInfo<'a>, - ) -> &mut Self { - self.instruction.governance_account = Some(governance_account); - self - } - #[inline(always)] - pub fn proposal_account( - &mut self, proposal_account: &'b solana_account_info::AccountInfo<'a>, - ) -> &mut Self { - self.instruction.proposal_account = Some(proposal_account); - self - } - /// TokenOwnerRecord of the Proposal owner - #[inline(always)] - pub fn proposal_token_owner_record( - &mut self, proposal_token_owner_record: &'b solana_account_info::AccountInfo<'a>, - ) -> &mut Self { - self.instruction.proposal_token_owner_record = Some(proposal_token_owner_record); - self - } - /// TokenOwnerRecord of the voter. PDA seeds: ['governance',realm, vote_governing_token_mint, governing_token_owner] - #[inline(always)] - pub fn voter_token_owner_record( - &mut self, voter_token_owner_record: &'b solana_account_info::AccountInfo<'a>, - ) -> &mut Self { - self.instruction.voter_token_owner_record = Some(voter_token_owner_record); - self - } - /// Governance Authority (Token Owner or Governance Delegate) - #[inline(always)] - pub fn governance_authority( - &mut self, governance_authority: &'b solana_account_info::AccountInfo<'a>, - ) -> &mut Self { - self.instruction.governance_authority = Some(governance_authority); - self - } - /// Proposal VoteRecord account. PDA seeds: ['governance',proposal,token_owner_record] - #[inline(always)] - pub fn proposal_vote_record( - &mut self, proposal_vote_record: &'b solana_account_info::AccountInfo<'a>, - ) -> &mut Self { - self.instruction.proposal_vote_record = Some(proposal_vote_record); - self - } - /// The Governing Token Mint which is used to cast the vote (vote_governing_token_mint). - /// The voting token mint is the governing_token_mint of the Proposal for Approve, Deny and Abstain votes. - /// For Veto vote the voting token mint is the mint of the opposite voting population. - /// Council mint to veto Community proposals and Community mint to veto Council proposals - /// Note: In the current version only Council veto is supported - #[inline(always)] - pub fn governing_token_mint( - &mut self, governing_token_mint: &'b solana_account_info::AccountInfo<'a>, - ) -> &mut Self { - self.instruction.governing_token_mint = Some(governing_token_mint); - self - } - #[inline(always)] - pub fn payer(&mut self, payer: &'b solana_account_info::AccountInfo<'a>) -> &mut Self { - self.instruction.payer = Some(payer); - self - } - #[inline(always)] - pub fn system_program( - &mut self, + payer: &'b solana_account_info::AccountInfo<'a>, system_program: &'b solana_account_info::AccountInfo<'a>, - ) -> &mut Self { - self.instruction.system_program = Some(system_program); - self - } - /// RealmConfig account. PDA seeds: ['realm-config', realm] - #[inline(always)] - pub fn realm_config_account( - &mut self, realm_config_account: &'b solana_account_info::AccountInfo<'a>, - ) -> &mut Self { - self.instruction.realm_config_account = Some(realm_config_account); - self + vote: Vote, + ) -> Self { + let instruction = Box::new(CastVoteCpiBuilderInstruction { + __program, + realm_account, + governance_account, + proposal_account, + proposal_token_owner_record, + voter_token_owner_record, + governance_authority, + proposal_vote_record, + governing_token_mint, + payer, + system_program, + realm_config_account, + voter_weight_record: None, + max_voter_weight_record: None, + vote, + __remaining_accounts: Vec::new(), + }); + Self { instruction } } /// `[optional account]` /// Optional Voter Weight Record @@ -763,11 +626,6 @@ impl<'a, 'b> CastVoteCpiBuilder<'a, 'b> { self.instruction.max_voter_weight_record = max_voter_weight_record; self } - #[inline(always)] - pub fn vote(&mut self, vote: Vote) -> &mut Self { - self.instruction.vote = Some(vote); - self - } /// Add an additional account to the instruction. #[inline(always)] pub fn add_remaining_account( @@ -803,65 +661,22 @@ impl<'a, 'b> CastVoteCpiBuilder<'a, 'b> { #[allow(clippy::vec_init_then_push)] pub fn invoke_signed(&self, signers_seeds: &[&[&[u8]]]) -> solana_program_error::ProgramResult { let args = CastVoteInstructionArgs { - vote: self.instruction.vote.clone().expect("vote is not set"), + vote: self.instruction.vote.clone(), }; let instruction = CastVoteCpi { __program: self.instruction.__program, - - realm_account: self - .instruction - .realm_account - .expect("realm_account is not set"), - - governance_account: self - .instruction - .governance_account - .expect("governance_account is not set"), - - proposal_account: self - .instruction - .proposal_account - .expect("proposal_account is not set"), - - proposal_token_owner_record: self - .instruction - .proposal_token_owner_record - .expect("proposal_token_owner_record is not set"), - - voter_token_owner_record: self - .instruction - .voter_token_owner_record - .expect("voter_token_owner_record is not set"), - - governance_authority: self - .instruction - .governance_authority - .expect("governance_authority is not set"), - - proposal_vote_record: self - .instruction - .proposal_vote_record - .expect("proposal_vote_record is not set"), - - governing_token_mint: self - .instruction - .governing_token_mint - .expect("governing_token_mint is not set"), - - payer: self.instruction.payer.expect("payer is not set"), - - system_program: self - .instruction - .system_program - .expect("system_program is not set"), - - realm_config_account: self - .instruction - .realm_config_account - .expect("realm_config_account is not set"), - + realm_account: self.instruction.realm_account, + governance_account: self.instruction.governance_account, + proposal_account: self.instruction.proposal_account, + proposal_token_owner_record: self.instruction.proposal_token_owner_record, + voter_token_owner_record: self.instruction.voter_token_owner_record, + governance_authority: self.instruction.governance_authority, + proposal_vote_record: self.instruction.proposal_vote_record, + governing_token_mint: self.instruction.governing_token_mint, + payer: self.instruction.payer, + system_program: self.instruction.system_program, + realm_config_account: self.instruction.realm_config_account, voter_weight_record: self.instruction.voter_weight_record, - max_voter_weight_record: self.instruction.max_voter_weight_record, __args: args, }; @@ -875,20 +690,20 @@ impl<'a, 'b> CastVoteCpiBuilder<'a, 'b> { #[derive(Clone, Debug)] struct CastVoteCpiBuilderInstruction<'a, 'b> { __program: &'b solana_account_info::AccountInfo<'a>, - realm_account: Option<&'b solana_account_info::AccountInfo<'a>>, - governance_account: Option<&'b solana_account_info::AccountInfo<'a>>, - proposal_account: Option<&'b solana_account_info::AccountInfo<'a>>, - proposal_token_owner_record: Option<&'b solana_account_info::AccountInfo<'a>>, - voter_token_owner_record: Option<&'b solana_account_info::AccountInfo<'a>>, - governance_authority: Option<&'b solana_account_info::AccountInfo<'a>>, - proposal_vote_record: Option<&'b solana_account_info::AccountInfo<'a>>, - governing_token_mint: Option<&'b solana_account_info::AccountInfo<'a>>, - payer: Option<&'b solana_account_info::AccountInfo<'a>>, - system_program: Option<&'b solana_account_info::AccountInfo<'a>>, - realm_config_account: Option<&'b solana_account_info::AccountInfo<'a>>, + realm_account: &'b solana_account_info::AccountInfo<'a>, + governance_account: &'b solana_account_info::AccountInfo<'a>, + proposal_account: &'b solana_account_info::AccountInfo<'a>, + proposal_token_owner_record: &'b solana_account_info::AccountInfo<'a>, + voter_token_owner_record: &'b solana_account_info::AccountInfo<'a>, + governance_authority: &'b solana_account_info::AccountInfo<'a>, + proposal_vote_record: &'b solana_account_info::AccountInfo<'a>, + governing_token_mint: &'b solana_account_info::AccountInfo<'a>, + payer: &'b solana_account_info::AccountInfo<'a>, + system_program: &'b solana_account_info::AccountInfo<'a>, + realm_config_account: &'b solana_account_info::AccountInfo<'a>, voter_weight_record: Option<&'b solana_account_info::AccountInfo<'a>>, max_voter_weight_record: Option<&'b solana_account_info::AccountInfo<'a>>, - vote: Option, + vote: Vote, /// Additional instruction accounts `(AccountInfo, is_writable, is_signer)`. __remaining_accounts: Vec<(&'b solana_account_info::AccountInfo<'a>, bool, bool)>, } diff --git a/e2e/governance/src/generated/instructions/complete_proposal.rs b/e2e/governance/src/generated/instructions/complete_proposal.rs index 952555d..d731fe2 100644 --- a/e2e/governance/src/generated/instructions/complete_proposal.rs +++ b/e2e/governance/src/generated/instructions/complete_proposal.rs @@ -82,37 +82,26 @@ impl Default for CompleteProposalInstructionData { /// 0. `[writable]` proposal_account /// 1. `[]` token_owner_record /// 2. `[signer]` complete_proposal_authority -#[derive(Clone, Debug, Default)] +#[derive(Clone, Debug)] pub struct CompleteProposalBuilder { - proposal_account: Option, - token_owner_record: Option, - complete_proposal_authority: Option, + proposal_account: solana_address::Address, + token_owner_record: solana_address::Address, + complete_proposal_authority: solana_address::Address, __remaining_accounts: Vec, } impl CompleteProposalBuilder { - pub fn new() -> Self { - Self::default() - } - #[inline(always)] - pub fn proposal_account(&mut self, proposal_account: solana_address::Address) -> &mut Self { - self.proposal_account = Some(proposal_account); - self - } - /// TokenOwnerRecord account of the Proposal owner - #[inline(always)] - pub fn token_owner_record(&mut self, token_owner_record: solana_address::Address) -> &mut Self { - self.token_owner_record = Some(token_owner_record); - self - } - /// Token Owner or Delegate - #[inline(always)] - pub fn complete_proposal_authority( - &mut self, + pub fn new( + proposal_account: solana_address::Address, + token_owner_record: solana_address::Address, complete_proposal_authority: solana_address::Address, - ) -> &mut Self { - self.complete_proposal_authority = Some(complete_proposal_authority); - self + ) -> Self { + Self { + proposal_account, + token_owner_record, + complete_proposal_authority, + __remaining_accounts: Vec::new(), + } } /// Add an additional account to the instruction. #[inline(always)] @@ -131,14 +120,13 @@ impl CompleteProposalBuilder { } #[allow(clippy::clone_on_copy)] pub fn instruction(&self) -> solana_instruction::Instruction { + let proposal_account = self.proposal_account; + let token_owner_record = self.token_owner_record; + let complete_proposal_authority = self.complete_proposal_authority; let accounts = CompleteProposal { - proposal_account: self.proposal_account.expect("proposal_account is not set"), - token_owner_record: self - .token_owner_record - .expect("token_owner_record is not set"), - complete_proposal_authority: self - .complete_proposal_authority - .expect("complete_proposal_authority is not set"), + proposal_account, + token_owner_record, + complete_proposal_authority, }; accounts.instruction_with_remaining_accounts(&self.__remaining_accounts) @@ -258,42 +246,21 @@ pub struct CompleteProposalCpiBuilder<'a, 'b> { } impl<'a, 'b> CompleteProposalCpiBuilder<'a, 'b> { - pub fn new(program: &'b solana_account_info::AccountInfo<'a>) -> Self { + pub fn new( + __program: &'b solana_account_info::AccountInfo<'a>, + proposal_account: &'b solana_account_info::AccountInfo<'a>, + token_owner_record: &'b solana_account_info::AccountInfo<'a>, + complete_proposal_authority: &'b solana_account_info::AccountInfo<'a>, + ) -> Self { let instruction = Box::new(CompleteProposalCpiBuilderInstruction { - __program: program, - proposal_account: None, - token_owner_record: None, - complete_proposal_authority: None, + __program, + proposal_account, + token_owner_record, + complete_proposal_authority, __remaining_accounts: Vec::new(), }); Self { instruction } } - #[inline(always)] - pub fn proposal_account( - &mut self, - proposal_account: &'b solana_account_info::AccountInfo<'a>, - ) -> &mut Self { - self.instruction.proposal_account = Some(proposal_account); - self - } - /// TokenOwnerRecord account of the Proposal owner - #[inline(always)] - pub fn token_owner_record( - &mut self, - token_owner_record: &'b solana_account_info::AccountInfo<'a>, - ) -> &mut Self { - self.instruction.token_owner_record = Some(token_owner_record); - self - } - /// Token Owner or Delegate - #[inline(always)] - pub fn complete_proposal_authority( - &mut self, - complete_proposal_authority: &'b solana_account_info::AccountInfo<'a>, - ) -> &mut Self { - self.instruction.complete_proposal_authority = Some(complete_proposal_authority); - self - } /// Add an additional account to the instruction. #[inline(always)] pub fn add_remaining_account( @@ -330,21 +297,9 @@ impl<'a, 'b> CompleteProposalCpiBuilder<'a, 'b> { pub fn invoke_signed(&self, signers_seeds: &[&[&[u8]]]) -> solana_program_error::ProgramResult { let instruction = CompleteProposalCpi { __program: self.instruction.__program, - - proposal_account: self - .instruction - .proposal_account - .expect("proposal_account is not set"), - - token_owner_record: self - .instruction - .token_owner_record - .expect("token_owner_record is not set"), - - complete_proposal_authority: self - .instruction - .complete_proposal_authority - .expect("complete_proposal_authority is not set"), + proposal_account: self.instruction.proposal_account, + token_owner_record: self.instruction.token_owner_record, + complete_proposal_authority: self.instruction.complete_proposal_authority, }; instruction.invoke_signed_with_remaining_accounts( signers_seeds, @@ -356,9 +311,9 @@ impl<'a, 'b> CompleteProposalCpiBuilder<'a, 'b> { #[derive(Clone, Debug)] struct CompleteProposalCpiBuilderInstruction<'a, 'b> { __program: &'b solana_account_info::AccountInfo<'a>, - proposal_account: Option<&'b solana_account_info::AccountInfo<'a>>, - token_owner_record: Option<&'b solana_account_info::AccountInfo<'a>>, - complete_proposal_authority: Option<&'b solana_account_info::AccountInfo<'a>>, + proposal_account: &'b solana_account_info::AccountInfo<'a>, + token_owner_record: &'b solana_account_info::AccountInfo<'a>, + complete_proposal_authority: &'b solana_account_info::AccountInfo<'a>, /// Additional instruction accounts `(AccountInfo, is_writable, is_signer)`. __remaining_accounts: Vec<(&'b solana_account_info::AccountInfo<'a>, bool, bool)>, } diff --git a/e2e/governance/src/generated/instructions/create_governance.rs b/e2e/governance/src/generated/instructions/create_governance.rs index a419648..4a97a49 100644 --- a/e2e/governance/src/generated/instructions/create_governance.rs +++ b/e2e/governance/src/generated/instructions/create_governance.rs @@ -150,57 +150,45 @@ impl CreateGovernanceInstructionArgs { /// 6. `[signer]` governance_authority /// 7. `[]` realm_config_account /// 8. `[optional]` voter_weight_record -#[derive(Clone, Debug, Default)] +#[derive(Clone, Debug)] pub struct CreateGovernanceBuilder { - realm_account: Option, - governance_account: Option, - governed_account: Option, - governing_token_owner_record: Option, - payer: Option, + realm_account: solana_address::Address, + governance_account: solana_address::Address, + governed_account: solana_address::Address, + governing_token_owner_record: solana_address::Address, + payer: solana_address::Address, system_program: Option, - governance_authority: Option, - realm_config_account: Option, + governance_authority: solana_address::Address, + realm_config_account: solana_address::Address, voter_weight_record: Option, - config: Option, + config: GovernanceConfig, __remaining_accounts: Vec, } impl CreateGovernanceBuilder { - pub fn new() -> Self { - Self::default() - } - /// Realm account the created governance belongs to - #[inline(always)] - pub fn realm_account(&mut self, realm_account: solana_address::Address) -> &mut Self { - self.realm_account = Some(realm_account); - self - } - /// seeds=['account-governance', realm, governed_account] - #[inline(always)] - pub fn governance_account(&mut self, governance_account: solana_address::Address) -> &mut Self { - self.governance_account = Some(governance_account); - self - } - /// Account governed by this Governance (governing_account). - /// Note: the account doesn't have to exist and can be used only as a unique identified for the Governance account - #[inline(always)] - pub fn governed_account(&mut self, governed_account: solana_address::Address) -> &mut Self { - self.governed_account = Some(governed_account); - self - } - /// Used only if not signed by RealmAuthority - #[inline(always)] - pub fn governing_token_owner_record( - &mut self, + pub fn new( + realm_account: solana_address::Address, + governance_account: solana_address::Address, + governed_account: solana_address::Address, governing_token_owner_record: solana_address::Address, - ) -> &mut Self { - self.governing_token_owner_record = Some(governing_token_owner_record); - self - } - #[inline(always)] - pub fn payer(&mut self, payer: solana_address::Address) -> &mut Self { - self.payer = Some(payer); - self + payer: solana_address::Address, + governance_authority: solana_address::Address, + realm_config_account: solana_address::Address, + config: GovernanceConfig, + ) -> Self { + Self { + realm_account, + governance_account, + governed_account, + governing_token_owner_record, + payer, + system_program: None, + governance_authority, + realm_config_account, + voter_weight_record: None, + config, + __remaining_accounts: Vec::new(), + } } /// `[optional account, default to '11111111111111111111111111111111']` #[inline(always)] @@ -208,23 +196,6 @@ impl CreateGovernanceBuilder { self.system_program = Some(system_program); self } - #[inline(always)] - pub fn governance_authority( - &mut self, - governance_authority: solana_address::Address, - ) -> &mut Self { - self.governance_authority = Some(governance_authority); - self - } - /// seeds=['realm-config', realm] - #[inline(always)] - pub fn realm_config_account( - &mut self, - realm_config_account: solana_address::Address, - ) -> &mut Self { - self.realm_config_account = Some(realm_config_account); - self - } /// `[optional account]` /// Optional Voter Weight Record #[inline(always)] @@ -235,11 +206,6 @@ impl CreateGovernanceBuilder { self.voter_weight_record = voter_weight_record; self } - #[inline(always)] - pub fn config(&mut self, config: GovernanceConfig) -> &mut Self { - self.config = Some(config); - self - } /// Add an additional account to the instruction. #[inline(always)] pub fn add_remaining_account(&mut self, account: solana_instruction::AccountMeta) -> &mut Self { @@ -257,29 +223,30 @@ impl CreateGovernanceBuilder { } #[allow(clippy::clone_on_copy)] pub fn instruction(&self) -> solana_instruction::Instruction { + let realm_account = self.realm_account; + let governance_account = self.governance_account; + let governed_account = self.governed_account; + let governing_token_owner_record = self.governing_token_owner_record; + let payer = self.payer; + let system_program = self + .system_program + .unwrap_or(solana_address::address!("11111111111111111111111111111111")); + let governance_authority = self.governance_authority; + let realm_config_account = self.realm_config_account; + let voter_weight_record = self.voter_weight_record; let accounts = CreateGovernance { - realm_account: self.realm_account.expect("realm_account is not set"), - governance_account: self - .governance_account - .expect("governance_account is not set"), - governed_account: self.governed_account.expect("governed_account is not set"), - governing_token_owner_record: self - .governing_token_owner_record - .expect("governing_token_owner_record is not set"), - payer: self.payer.expect("payer is not set"), - system_program: self - .system_program - .unwrap_or(solana_address::address!("11111111111111111111111111111111")), - governance_authority: self - .governance_authority - .expect("governance_authority is not set"), - realm_config_account: self - .realm_config_account - .expect("realm_config_account is not set"), - voter_weight_record: self.voter_weight_record, + realm_account, + governance_account, + governed_account, + governing_token_owner_record, + payer, + system_program, + governance_authority, + realm_config_account, + voter_weight_record, }; let args = CreateGovernanceInstructionArgs { - config: self.config.clone().expect("config is not set"), + config: self.config.clone(), }; accounts.instruction_with_remaining_accounts(args, &self.__remaining_accounts) @@ -483,89 +450,33 @@ pub struct CreateGovernanceCpiBuilder<'a, 'b> { } impl<'a, 'b> CreateGovernanceCpiBuilder<'a, 'b> { - pub fn new(program: &'b solana_account_info::AccountInfo<'a>) -> Self { - let instruction = Box::new(CreateGovernanceCpiBuilderInstruction { - __program: program, - realm_account: None, - governance_account: None, - governed_account: None, - governing_token_owner_record: None, - payer: None, - system_program: None, - governance_authority: None, - realm_config_account: None, - voter_weight_record: None, - config: None, - __remaining_accounts: Vec::new(), - }); - Self { instruction } - } - /// Realm account the created governance belongs to - #[inline(always)] - pub fn realm_account( - &mut self, + pub fn new( + __program: &'b solana_account_info::AccountInfo<'a>, realm_account: &'b solana_account_info::AccountInfo<'a>, - ) -> &mut Self { - self.instruction.realm_account = Some(realm_account); - self - } - /// seeds=['account-governance', realm, governed_account] - #[inline(always)] - pub fn governance_account( - &mut self, governance_account: &'b solana_account_info::AccountInfo<'a>, - ) -> &mut Self { - self.instruction.governance_account = Some(governance_account); - self - } - /// Account governed by this Governance (governing_account). - /// Note: the account doesn't have to exist and can be used only as a unique identified for the Governance account - #[inline(always)] - pub fn governed_account( - &mut self, governed_account: &'b solana_account_info::AccountInfo<'a>, - ) -> &mut Self { - self.instruction.governed_account = Some(governed_account); - self - } - /// Used only if not signed by RealmAuthority - #[inline(always)] - pub fn governing_token_owner_record( - &mut self, governing_token_owner_record: &'b solana_account_info::AccountInfo<'a>, - ) -> &mut Self { - self.instruction.governing_token_owner_record = Some(governing_token_owner_record); - self - } - #[inline(always)] - pub fn payer(&mut self, payer: &'b solana_account_info::AccountInfo<'a>) -> &mut Self { - self.instruction.payer = Some(payer); - self - } - #[inline(always)] - pub fn system_program( - &mut self, + payer: &'b solana_account_info::AccountInfo<'a>, system_program: &'b solana_account_info::AccountInfo<'a>, - ) -> &mut Self { - self.instruction.system_program = Some(system_program); - self - } - #[inline(always)] - pub fn governance_authority( - &mut self, governance_authority: &'b solana_account_info::AccountInfo<'a>, - ) -> &mut Self { - self.instruction.governance_authority = Some(governance_authority); - self - } - /// seeds=['realm-config', realm] - #[inline(always)] - pub fn realm_config_account( - &mut self, realm_config_account: &'b solana_account_info::AccountInfo<'a>, - ) -> &mut Self { - self.instruction.realm_config_account = Some(realm_config_account); - self + config: GovernanceConfig, + ) -> Self { + let instruction = Box::new(CreateGovernanceCpiBuilderInstruction { + __program, + realm_account, + governance_account, + governed_account, + governing_token_owner_record, + payer, + system_program, + governance_authority, + realm_config_account, + voter_weight_record: None, + config, + __remaining_accounts: Vec::new(), + }); + Self { instruction } } /// `[optional account]` /// Optional Voter Weight Record @@ -577,11 +488,6 @@ impl<'a, 'b> CreateGovernanceCpiBuilder<'a, 'b> { self.instruction.voter_weight_record = voter_weight_record; self } - #[inline(always)] - pub fn config(&mut self, config: GovernanceConfig) -> &mut Self { - self.instruction.config = Some(config); - self - } /// Add an additional account to the instruction. #[inline(always)] pub fn add_remaining_account( @@ -617,48 +523,18 @@ impl<'a, 'b> CreateGovernanceCpiBuilder<'a, 'b> { #[allow(clippy::vec_init_then_push)] pub fn invoke_signed(&self, signers_seeds: &[&[&[u8]]]) -> solana_program_error::ProgramResult { let args = CreateGovernanceInstructionArgs { - config: self.instruction.config.clone().expect("config is not set"), + config: self.instruction.config.clone(), }; let instruction = CreateGovernanceCpi { __program: self.instruction.__program, - - realm_account: self - .instruction - .realm_account - .expect("realm_account is not set"), - - governance_account: self - .instruction - .governance_account - .expect("governance_account is not set"), - - governed_account: self - .instruction - .governed_account - .expect("governed_account is not set"), - - governing_token_owner_record: self - .instruction - .governing_token_owner_record - .expect("governing_token_owner_record is not set"), - - payer: self.instruction.payer.expect("payer is not set"), - - system_program: self - .instruction - .system_program - .expect("system_program is not set"), - - governance_authority: self - .instruction - .governance_authority - .expect("governance_authority is not set"), - - realm_config_account: self - .instruction - .realm_config_account - .expect("realm_config_account is not set"), - + realm_account: self.instruction.realm_account, + governance_account: self.instruction.governance_account, + governed_account: self.instruction.governed_account, + governing_token_owner_record: self.instruction.governing_token_owner_record, + payer: self.instruction.payer, + system_program: self.instruction.system_program, + governance_authority: self.instruction.governance_authority, + realm_config_account: self.instruction.realm_config_account, voter_weight_record: self.instruction.voter_weight_record, __args: args, }; @@ -672,16 +548,16 @@ impl<'a, 'b> CreateGovernanceCpiBuilder<'a, 'b> { #[derive(Clone, Debug)] struct CreateGovernanceCpiBuilderInstruction<'a, 'b> { __program: &'b solana_account_info::AccountInfo<'a>, - realm_account: Option<&'b solana_account_info::AccountInfo<'a>>, - governance_account: Option<&'b solana_account_info::AccountInfo<'a>>, - governed_account: Option<&'b solana_account_info::AccountInfo<'a>>, - governing_token_owner_record: Option<&'b solana_account_info::AccountInfo<'a>>, - payer: Option<&'b solana_account_info::AccountInfo<'a>>, - system_program: Option<&'b solana_account_info::AccountInfo<'a>>, - governance_authority: Option<&'b solana_account_info::AccountInfo<'a>>, - realm_config_account: Option<&'b solana_account_info::AccountInfo<'a>>, + realm_account: &'b solana_account_info::AccountInfo<'a>, + governance_account: &'b solana_account_info::AccountInfo<'a>, + governed_account: &'b solana_account_info::AccountInfo<'a>, + governing_token_owner_record: &'b solana_account_info::AccountInfo<'a>, + payer: &'b solana_account_info::AccountInfo<'a>, + system_program: &'b solana_account_info::AccountInfo<'a>, + governance_authority: &'b solana_account_info::AccountInfo<'a>, + realm_config_account: &'b solana_account_info::AccountInfo<'a>, voter_weight_record: Option<&'b solana_account_info::AccountInfo<'a>>, - config: Option, + config: GovernanceConfig, /// Additional instruction accounts `(AccountInfo, is_writable, is_signer)`. __remaining_accounts: Vec<(&'b solana_account_info::AccountInfo<'a>, bool, bool)>, } diff --git a/e2e/governance/src/generated/instructions/create_mint_governance.rs b/e2e/governance/src/generated/instructions/create_mint_governance.rs index c715de4..a4c3ed1 100644 --- a/e2e/governance/src/generated/instructions/create_mint_governance.rs +++ b/e2e/governance/src/generated/instructions/create_mint_governance.rs @@ -166,68 +166,53 @@ impl CreateMintGovernanceInstructionArgs { /// 8. `[signer]` governance_authority /// 9. `[]` realm_config /// 10. `[optional]` voter_weight_record -#[derive(Clone, Debug, Default)] +#[derive(Clone, Debug)] pub struct CreateMintGovernanceBuilder { - realm_account: Option, - mint_governance_account: Option, - governed_mint: Option, - mint_authority: Option, - governing_token_owner_record: Option, - payer: Option, + realm_account: solana_address::Address, + mint_governance_account: solana_address::Address, + governed_mint: solana_address::Address, + mint_authority: solana_address::Address, + governing_token_owner_record: solana_address::Address, + payer: solana_address::Address, token_program: Option, system_program: Option, - governance_authority: Option, - realm_config: Option, + governance_authority: solana_address::Address, + realm_config: solana_address::Address, voter_weight_record: Option, - config: Option, - transfer_mint_authorities: Option, + config: GovernanceConfig, + transfer_mint_authorities: bool, __remaining_accounts: Vec, } impl CreateMintGovernanceBuilder { - pub fn new() -> Self { - Self::default() - } - /// Realm account the created Governance belongs to - #[inline(always)] - pub fn realm_account(&mut self, realm_account: solana_address::Address) -> &mut Self { - self.realm_account = Some(realm_account); - self - } - /// Mint Governance account. seeds=['mint-governance', realm, governed_mint] - #[inline(always)] - pub fn mint_governance_account( - &mut self, + pub fn new( + realm_account: solana_address::Address, mint_governance_account: solana_address::Address, - ) -> &mut Self { - self.mint_governance_account = Some(mint_governance_account); - self - } - /// Mint governed by this Governance account - #[inline(always)] - pub fn governed_mint(&mut self, governed_mint: solana_address::Address) -> &mut Self { - self.governed_mint = Some(governed_mint); - self - } - /// Current Mint authority (MintTokens and optionally FreezeAccount) - #[inline(always)] - pub fn mint_authority(&mut self, mint_authority: solana_address::Address) -> &mut Self { - self.mint_authority = Some(mint_authority); - self - } - /// Governing TokenOwnerRecord account (Used only if not signed by RealmAuthority) - #[inline(always)] - pub fn governing_token_owner_record( - &mut self, + governed_mint: solana_address::Address, + mint_authority: solana_address::Address, governing_token_owner_record: solana_address::Address, - ) -> &mut Self { - self.governing_token_owner_record = Some(governing_token_owner_record); - self - } - #[inline(always)] - pub fn payer(&mut self, payer: solana_address::Address) -> &mut Self { - self.payer = Some(payer); - self + payer: solana_address::Address, + governance_authority: solana_address::Address, + realm_config: solana_address::Address, + config: GovernanceConfig, + transfer_mint_authorities: bool, + ) -> Self { + Self { + realm_account, + mint_governance_account, + governed_mint, + mint_authority, + governing_token_owner_record, + payer, + token_program: None, + system_program: None, + governance_authority, + realm_config, + voter_weight_record: None, + config, + transfer_mint_authorities, + __remaining_accounts: Vec::new(), + } } /// `[optional account, default to 'TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA']` #[inline(always)] @@ -241,20 +226,6 @@ impl CreateMintGovernanceBuilder { self.system_program = Some(system_program); self } - #[inline(always)] - pub fn governance_authority( - &mut self, - governance_authority: solana_address::Address, - ) -> &mut Self { - self.governance_authority = Some(governance_authority); - self - } - /// RealmConfig account. seeds=['realm-config', realm] - #[inline(always)] - pub fn realm_config(&mut self, realm_config: solana_address::Address) -> &mut Self { - self.realm_config = Some(realm_config); - self - } /// `[optional account]` /// Optional Voter Weight Record #[inline(always)] @@ -265,16 +236,6 @@ impl CreateMintGovernanceBuilder { self.voter_weight_record = voter_weight_record; self } - #[inline(always)] - pub fn config(&mut self, config: GovernanceConfig) -> &mut Self { - self.config = Some(config); - self - } - #[inline(always)] - pub fn transfer_mint_authorities(&mut self, transfer_mint_authorities: bool) -> &mut Self { - self.transfer_mint_authorities = Some(transfer_mint_authorities); - self - } /// Add an additional account to the instruction. #[inline(always)] pub fn add_remaining_account(&mut self, account: solana_instruction::AccountMeta) -> &mut Self { @@ -292,35 +253,37 @@ impl CreateMintGovernanceBuilder { } #[allow(clippy::clone_on_copy)] pub fn instruction(&self) -> solana_instruction::Instruction { + let realm_account = self.realm_account; + let mint_governance_account = self.mint_governance_account; + let governed_mint = self.governed_mint; + let mint_authority = self.mint_authority; + let governing_token_owner_record = self.governing_token_owner_record; + let payer = self.payer; + let token_program = self.token_program.unwrap_or(solana_address::address!( + "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA" + )); + let system_program = self + .system_program + .unwrap_or(solana_address::address!("11111111111111111111111111111111")); + let governance_authority = self.governance_authority; + let realm_config = self.realm_config; + let voter_weight_record = self.voter_weight_record; let accounts = CreateMintGovernance { - realm_account: self.realm_account.expect("realm_account is not set"), - mint_governance_account: self - .mint_governance_account - .expect("mint_governance_account is not set"), - governed_mint: self.governed_mint.expect("governed_mint is not set"), - mint_authority: self.mint_authority.expect("mint_authority is not set"), - governing_token_owner_record: self - .governing_token_owner_record - .expect("governing_token_owner_record is not set"), - payer: self.payer.expect("payer is not set"), - token_program: self.token_program.unwrap_or(solana_address::address!( - "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA" - )), - system_program: self - .system_program - .unwrap_or(solana_address::address!("11111111111111111111111111111111")), - governance_authority: self - .governance_authority - .expect("governance_authority is not set"), - realm_config: self.realm_config.expect("realm_config is not set"), - voter_weight_record: self.voter_weight_record, + realm_account, + mint_governance_account, + governed_mint, + mint_authority, + governing_token_owner_record, + payer, + token_program, + system_program, + governance_authority, + realm_config, + voter_weight_record, }; let args = CreateMintGovernanceInstructionArgs { - config: self.config.clone().expect("config is not set"), - transfer_mint_authorities: self - .transfer_mint_authorities - .clone() - .expect("transfer_mint_authorities is not set"), + config: self.config.clone(), + transfer_mint_authorities: self.transfer_mint_authorities.clone(), }; accounts.instruction_with_remaining_accounts(args, &self.__remaining_accounts) @@ -546,108 +509,39 @@ pub struct CreateMintGovernanceCpiBuilder<'a, 'b> { } impl<'a, 'b> CreateMintGovernanceCpiBuilder<'a, 'b> { - pub fn new(program: &'b solana_account_info::AccountInfo<'a>) -> Self { - let instruction = Box::new(CreateMintGovernanceCpiBuilderInstruction { - __program: program, - realm_account: None, - mint_governance_account: None, - governed_mint: None, - mint_authority: None, - governing_token_owner_record: None, - payer: None, - token_program: None, - system_program: None, - governance_authority: None, - realm_config: None, - voter_weight_record: None, - config: None, - transfer_mint_authorities: None, - __remaining_accounts: Vec::new(), - }); - Self { instruction } - } - /// Realm account the created Governance belongs to - #[inline(always)] - pub fn realm_account( - &mut self, + pub fn new( + __program: &'b solana_account_info::AccountInfo<'a>, realm_account: &'b solana_account_info::AccountInfo<'a>, - ) -> &mut Self { - self.instruction.realm_account = Some(realm_account); - self - } - /// Mint Governance account. seeds=['mint-governance', realm, governed_mint] - #[inline(always)] - pub fn mint_governance_account( - &mut self, mint_governance_account: &'b solana_account_info::AccountInfo<'a>, - ) -> &mut Self { - self.instruction.mint_governance_account = Some(mint_governance_account); - self - } - /// Mint governed by this Governance account - #[inline(always)] - pub fn governed_mint( - &mut self, governed_mint: &'b solana_account_info::AccountInfo<'a>, - ) -> &mut Self { - self.instruction.governed_mint = Some(governed_mint); - self - } - /// Current Mint authority (MintTokens and optionally FreezeAccount) - #[inline(always)] - pub fn mint_authority( - &mut self, mint_authority: &'b solana_account_info::AccountInfo<'a>, - ) -> &mut Self { - self.instruction.mint_authority = Some(mint_authority); - self - } - /// Governing TokenOwnerRecord account (Used only if not signed by RealmAuthority) - #[inline(always)] - pub fn governing_token_owner_record( - &mut self, governing_token_owner_record: &'b solana_account_info::AccountInfo<'a>, - ) -> &mut Self { - self.instruction.governing_token_owner_record = Some(governing_token_owner_record); - self - } - #[inline(always)] - pub fn payer(&mut self, payer: &'b solana_account_info::AccountInfo<'a>) -> &mut Self { - self.instruction.payer = Some(payer); - self - } - #[inline(always)] - pub fn token_program( - &mut self, + payer: &'b solana_account_info::AccountInfo<'a>, token_program: &'b solana_account_info::AccountInfo<'a>, - ) -> &mut Self { - self.instruction.token_program = Some(token_program); - self - } - #[inline(always)] - pub fn system_program( - &mut self, system_program: &'b solana_account_info::AccountInfo<'a>, - ) -> &mut Self { - self.instruction.system_program = Some(system_program); - self - } - #[inline(always)] - pub fn governance_authority( - &mut self, governance_authority: &'b solana_account_info::AccountInfo<'a>, - ) -> &mut Self { - self.instruction.governance_authority = Some(governance_authority); - self - } - /// RealmConfig account. seeds=['realm-config', realm] - #[inline(always)] - pub fn realm_config( - &mut self, realm_config: &'b solana_account_info::AccountInfo<'a>, - ) -> &mut Self { - self.instruction.realm_config = Some(realm_config); - self + config: GovernanceConfig, + transfer_mint_authorities: bool, + ) -> Self { + let instruction = Box::new(CreateMintGovernanceCpiBuilderInstruction { + __program, + realm_account, + mint_governance_account, + governed_mint, + mint_authority, + governing_token_owner_record, + payer, + token_program, + system_program, + governance_authority, + realm_config, + voter_weight_record: None, + config, + transfer_mint_authorities, + __remaining_accounts: Vec::new(), + }); + Self { instruction } } /// `[optional account]` /// Optional Voter Weight Record @@ -659,16 +553,6 @@ impl<'a, 'b> CreateMintGovernanceCpiBuilder<'a, 'b> { self.instruction.voter_weight_record = voter_weight_record; self } - #[inline(always)] - pub fn config(&mut self, config: GovernanceConfig) -> &mut Self { - self.instruction.config = Some(config); - self - } - #[inline(always)] - pub fn transfer_mint_authorities(&mut self, transfer_mint_authorities: bool) -> &mut Self { - self.instruction.transfer_mint_authorities = Some(transfer_mint_authorities); - self - } /// Add an additional account to the instruction. #[inline(always)] pub fn add_remaining_account( @@ -704,63 +588,21 @@ impl<'a, 'b> CreateMintGovernanceCpiBuilder<'a, 'b> { #[allow(clippy::vec_init_then_push)] pub fn invoke_signed(&self, signers_seeds: &[&[&[u8]]]) -> solana_program_error::ProgramResult { let args = CreateMintGovernanceInstructionArgs { - config: self.instruction.config.clone().expect("config is not set"), - transfer_mint_authorities: self - .instruction - .transfer_mint_authorities - .clone() - .expect("transfer_mint_authorities is not set"), + config: self.instruction.config.clone(), + transfer_mint_authorities: self.instruction.transfer_mint_authorities.clone(), }; let instruction = CreateMintGovernanceCpi { __program: self.instruction.__program, - - realm_account: self - .instruction - .realm_account - .expect("realm_account is not set"), - - mint_governance_account: self - .instruction - .mint_governance_account - .expect("mint_governance_account is not set"), - - governed_mint: self - .instruction - .governed_mint - .expect("governed_mint is not set"), - - mint_authority: self - .instruction - .mint_authority - .expect("mint_authority is not set"), - - governing_token_owner_record: self - .instruction - .governing_token_owner_record - .expect("governing_token_owner_record is not set"), - - payer: self.instruction.payer.expect("payer is not set"), - - token_program: self - .instruction - .token_program - .expect("token_program is not set"), - - system_program: self - .instruction - .system_program - .expect("system_program is not set"), - - governance_authority: self - .instruction - .governance_authority - .expect("governance_authority is not set"), - - realm_config: self - .instruction - .realm_config - .expect("realm_config is not set"), - + realm_account: self.instruction.realm_account, + mint_governance_account: self.instruction.mint_governance_account, + governed_mint: self.instruction.governed_mint, + mint_authority: self.instruction.mint_authority, + governing_token_owner_record: self.instruction.governing_token_owner_record, + payer: self.instruction.payer, + token_program: self.instruction.token_program, + system_program: self.instruction.system_program, + governance_authority: self.instruction.governance_authority, + realm_config: self.instruction.realm_config, voter_weight_record: self.instruction.voter_weight_record, __args: args, }; @@ -774,19 +616,19 @@ impl<'a, 'b> CreateMintGovernanceCpiBuilder<'a, 'b> { #[derive(Clone, Debug)] struct CreateMintGovernanceCpiBuilderInstruction<'a, 'b> { __program: &'b solana_account_info::AccountInfo<'a>, - realm_account: Option<&'b solana_account_info::AccountInfo<'a>>, - mint_governance_account: Option<&'b solana_account_info::AccountInfo<'a>>, - governed_mint: Option<&'b solana_account_info::AccountInfo<'a>>, - mint_authority: Option<&'b solana_account_info::AccountInfo<'a>>, - governing_token_owner_record: Option<&'b solana_account_info::AccountInfo<'a>>, - payer: Option<&'b solana_account_info::AccountInfo<'a>>, - token_program: Option<&'b solana_account_info::AccountInfo<'a>>, - system_program: Option<&'b solana_account_info::AccountInfo<'a>>, - governance_authority: Option<&'b solana_account_info::AccountInfo<'a>>, - realm_config: Option<&'b solana_account_info::AccountInfo<'a>>, + realm_account: &'b solana_account_info::AccountInfo<'a>, + mint_governance_account: &'b solana_account_info::AccountInfo<'a>, + governed_mint: &'b solana_account_info::AccountInfo<'a>, + mint_authority: &'b solana_account_info::AccountInfo<'a>, + governing_token_owner_record: &'b solana_account_info::AccountInfo<'a>, + payer: &'b solana_account_info::AccountInfo<'a>, + token_program: &'b solana_account_info::AccountInfo<'a>, + system_program: &'b solana_account_info::AccountInfo<'a>, + governance_authority: &'b solana_account_info::AccountInfo<'a>, + realm_config: &'b solana_account_info::AccountInfo<'a>, voter_weight_record: Option<&'b solana_account_info::AccountInfo<'a>>, - config: Option, - transfer_mint_authorities: Option, + config: GovernanceConfig, + transfer_mint_authorities: bool, /// Additional instruction accounts `(AccountInfo, is_writable, is_signer)`. __remaining_accounts: Vec<(&'b solana_account_info::AccountInfo<'a>, bool, bool)>, } diff --git a/e2e/governance/src/generated/instructions/create_native_treasury.rs b/e2e/governance/src/generated/instructions/create_native_treasury.rs index fa85864..58f6940 100644 --- a/e2e/governance/src/generated/instructions/create_native_treasury.rs +++ b/e2e/governance/src/generated/instructions/create_native_treasury.rs @@ -91,38 +91,28 @@ impl Default for CreateNativeTreasuryInstructionData { /// 1. `[writable]` native_treasury_account /// 2. `[signer]` payer /// 3. `[optional]` system_program (default to `11111111111111111111111111111111`) -#[derive(Clone, Debug, Default)] +#[derive(Clone, Debug)] pub struct CreateNativeTreasuryBuilder { - governance_account: Option, - native_treasury_account: Option, - payer: Option, + governance_account: solana_address::Address, + native_treasury_account: solana_address::Address, + payer: solana_address::Address, system_program: Option, __remaining_accounts: Vec, } impl CreateNativeTreasuryBuilder { - pub fn new() -> Self { - Self::default() - } - /// Governance account the treasury account is for - #[inline(always)] - pub fn governance_account(&mut self, governance_account: solana_address::Address) -> &mut Self { - self.governance_account = Some(governance_account); - self - } - /// seeds=['native-treasury', governance] - #[inline(always)] - pub fn native_treasury_account( - &mut self, + pub fn new( + governance_account: solana_address::Address, native_treasury_account: solana_address::Address, - ) -> &mut Self { - self.native_treasury_account = Some(native_treasury_account); - self - } - #[inline(always)] - pub fn payer(&mut self, payer: solana_address::Address) -> &mut Self { - self.payer = Some(payer); - self + payer: solana_address::Address, + ) -> Self { + Self { + governance_account, + native_treasury_account, + payer, + system_program: None, + __remaining_accounts: Vec::new(), + } } /// `[optional account, default to '11111111111111111111111111111111']` #[inline(always)] @@ -147,17 +137,17 @@ impl CreateNativeTreasuryBuilder { } #[allow(clippy::clone_on_copy)] pub fn instruction(&self) -> solana_instruction::Instruction { + let governance_account = self.governance_account; + let native_treasury_account = self.native_treasury_account; + let payer = self.payer; + let system_program = self + .system_program + .unwrap_or(solana_address::address!("11111111111111111111111111111111")); let accounts = CreateNativeTreasury { - governance_account: self - .governance_account - .expect("governance_account is not set"), - native_treasury_account: self - .native_treasury_account - .expect("native_treasury_account is not set"), - payer: self.payer.expect("payer is not set"), - system_program: self - .system_program - .unwrap_or(solana_address::address!("11111111111111111111111111111111")), + governance_account, + native_treasury_account, + payer, + system_program, }; accounts.instruction_with_remaining_accounts(&self.__remaining_accounts) @@ -291,48 +281,23 @@ pub struct CreateNativeTreasuryCpiBuilder<'a, 'b> { } impl<'a, 'b> CreateNativeTreasuryCpiBuilder<'a, 'b> { - pub fn new(program: &'b solana_account_info::AccountInfo<'a>) -> Self { + pub fn new( + __program: &'b solana_account_info::AccountInfo<'a>, + governance_account: &'b solana_account_info::AccountInfo<'a>, + native_treasury_account: &'b solana_account_info::AccountInfo<'a>, + payer: &'b solana_account_info::AccountInfo<'a>, + system_program: &'b solana_account_info::AccountInfo<'a>, + ) -> Self { let instruction = Box::new(CreateNativeTreasuryCpiBuilderInstruction { - __program: program, - governance_account: None, - native_treasury_account: None, - payer: None, - system_program: None, + __program, + governance_account, + native_treasury_account, + payer, + system_program, __remaining_accounts: Vec::new(), }); Self { instruction } } - /// Governance account the treasury account is for - #[inline(always)] - pub fn governance_account( - &mut self, - governance_account: &'b solana_account_info::AccountInfo<'a>, - ) -> &mut Self { - self.instruction.governance_account = Some(governance_account); - self - } - /// seeds=['native-treasury', governance] - #[inline(always)] - pub fn native_treasury_account( - &mut self, - native_treasury_account: &'b solana_account_info::AccountInfo<'a>, - ) -> &mut Self { - self.instruction.native_treasury_account = Some(native_treasury_account); - self - } - #[inline(always)] - pub fn payer(&mut self, payer: &'b solana_account_info::AccountInfo<'a>) -> &mut Self { - self.instruction.payer = Some(payer); - self - } - #[inline(always)] - pub fn system_program( - &mut self, - system_program: &'b solana_account_info::AccountInfo<'a>, - ) -> &mut Self { - self.instruction.system_program = Some(system_program); - self - } /// Add an additional account to the instruction. #[inline(always)] pub fn add_remaining_account( @@ -369,23 +334,10 @@ impl<'a, 'b> CreateNativeTreasuryCpiBuilder<'a, 'b> { pub fn invoke_signed(&self, signers_seeds: &[&[&[u8]]]) -> solana_program_error::ProgramResult { let instruction = CreateNativeTreasuryCpi { __program: self.instruction.__program, - - governance_account: self - .instruction - .governance_account - .expect("governance_account is not set"), - - native_treasury_account: self - .instruction - .native_treasury_account - .expect("native_treasury_account is not set"), - - payer: self.instruction.payer.expect("payer is not set"), - - system_program: self - .instruction - .system_program - .expect("system_program is not set"), + governance_account: self.instruction.governance_account, + native_treasury_account: self.instruction.native_treasury_account, + payer: self.instruction.payer, + system_program: self.instruction.system_program, }; instruction.invoke_signed_with_remaining_accounts( signers_seeds, @@ -397,10 +349,10 @@ impl<'a, 'b> CreateNativeTreasuryCpiBuilder<'a, 'b> { #[derive(Clone, Debug)] struct CreateNativeTreasuryCpiBuilderInstruction<'a, 'b> { __program: &'b solana_account_info::AccountInfo<'a>, - governance_account: Option<&'b solana_account_info::AccountInfo<'a>>, - native_treasury_account: Option<&'b solana_account_info::AccountInfo<'a>>, - payer: Option<&'b solana_account_info::AccountInfo<'a>>, - system_program: Option<&'b solana_account_info::AccountInfo<'a>>, + governance_account: &'b solana_account_info::AccountInfo<'a>, + native_treasury_account: &'b solana_account_info::AccountInfo<'a>, + payer: &'b solana_account_info::AccountInfo<'a>, + system_program: &'b solana_account_info::AccountInfo<'a>, /// Additional instruction accounts `(AccountInfo, is_writable, is_signer)`. __remaining_accounts: Vec<(&'b solana_account_info::AccountInfo<'a>, bool, bool)>, } diff --git a/e2e/governance/src/generated/instructions/create_program_governance.rs b/e2e/governance/src/generated/instructions/create_program_governance.rs index ec6f169..7a73cc0 100644 --- a/e2e/governance/src/generated/instructions/create_program_governance.rs +++ b/e2e/governance/src/generated/instructions/create_program_governance.rs @@ -173,87 +173,57 @@ impl CreateProgramGovernanceInstructionArgs { /// 9. `[signer]` governance_authority /// 10. `[]` realm_config /// 11. `[optional]` voter_weight_record -#[derive(Clone, Debug, Default)] +#[derive(Clone, Debug)] pub struct CreateProgramGovernanceBuilder { - realm_account: Option, - program_governance_account: Option, - governed_program: Option, - program_data: Option, - current_upgrade_authority: Option, - governing_token_owner_record: Option, - payer: Option, - bpf_upgradeable_loader_program: Option, + realm_account: solana_address::Address, + program_governance_account: solana_address::Address, + governed_program: solana_address::Address, + program_data: solana_address::Address, + current_upgrade_authority: solana_address::Address, + governing_token_owner_record: solana_address::Address, + payer: solana_address::Address, + bpf_upgradeable_loader_program: solana_address::Address, system_program: Option, - governance_authority: Option, - realm_config: Option, + governance_authority: solana_address::Address, + realm_config: solana_address::Address, voter_weight_record: Option, - config: Option, - transfer_upgrade_authority: Option, + config: GovernanceConfig, + transfer_upgrade_authority: bool, __remaining_accounts: Vec, } impl CreateProgramGovernanceBuilder { - pub fn new() -> Self { - Self::default() - } - /// Realm account the created Governance belongs to - #[inline(always)] - pub fn realm_account(&mut self, realm_account: solana_address::Address) -> &mut Self { - self.realm_account = Some(realm_account); - self - } - /// Program Governance account. seeds: ['program-governance', realm, governed_program] - #[inline(always)] - pub fn program_governance_account( - &mut self, + pub fn new( + realm_account: solana_address::Address, program_governance_account: solana_address::Address, - ) -> &mut Self { - self.program_governance_account = Some(program_governance_account); - self - } - /// Program governed by this Governance account - #[inline(always)] - pub fn governed_program(&mut self, governed_program: solana_address::Address) -> &mut Self { - self.governed_program = Some(governed_program); - self - } - /// Program Data account of the Program governed by this Governance account - #[inline(always)] - pub fn program_data(&mut self, program_data: solana_address::Address) -> &mut Self { - self.program_data = Some(program_data); - self - } - /// Current Upgrade Authority account of the Program governed by this Governance account - #[inline(always)] - pub fn current_upgrade_authority( - &mut self, + governed_program: solana_address::Address, + program_data: solana_address::Address, current_upgrade_authority: solana_address::Address, - ) -> &mut Self { - self.current_upgrade_authority = Some(current_upgrade_authority); - self - } - /// Governing TokenOwnerRecord account (Used only if not signed by RealmAuthority) - #[inline(always)] - pub fn governing_token_owner_record( - &mut self, governing_token_owner_record: solana_address::Address, - ) -> &mut Self { - self.governing_token_owner_record = Some(governing_token_owner_record); - self - } - #[inline(always)] - pub fn payer(&mut self, payer: solana_address::Address) -> &mut Self { - self.payer = Some(payer); - self - } - /// bpf_upgradeable_loader_program program - #[inline(always)] - pub fn bpf_upgradeable_loader_program( - &mut self, + payer: solana_address::Address, bpf_upgradeable_loader_program: solana_address::Address, - ) -> &mut Self { - self.bpf_upgradeable_loader_program = Some(bpf_upgradeable_loader_program); - self + governance_authority: solana_address::Address, + realm_config: solana_address::Address, + config: GovernanceConfig, + transfer_upgrade_authority: bool, + ) -> Self { + Self { + realm_account, + program_governance_account, + governed_program, + program_data, + current_upgrade_authority, + governing_token_owner_record, + payer, + bpf_upgradeable_loader_program, + system_program: None, + governance_authority, + realm_config, + voter_weight_record: None, + config, + transfer_upgrade_authority, + __remaining_accounts: Vec::new(), + } } /// `[optional account, default to '11111111111111111111111111111111']` #[inline(always)] @@ -261,20 +231,6 @@ impl CreateProgramGovernanceBuilder { self.system_program = Some(system_program); self } - #[inline(always)] - pub fn governance_authority( - &mut self, - governance_authority: solana_address::Address, - ) -> &mut Self { - self.governance_authority = Some(governance_authority); - self - } - /// RealmConfig account. seeds=['realm-config', realm] - #[inline(always)] - pub fn realm_config(&mut self, realm_config: solana_address::Address) -> &mut Self { - self.realm_config = Some(realm_config); - self - } /// `[optional account]` /// Optional Voter Weight Record #[inline(always)] @@ -285,16 +241,6 @@ impl CreateProgramGovernanceBuilder { self.voter_weight_record = voter_weight_record; self } - #[inline(always)] - pub fn config(&mut self, config: GovernanceConfig) -> &mut Self { - self.config = Some(config); - self - } - #[inline(always)] - pub fn transfer_upgrade_authority(&mut self, transfer_upgrade_authority: bool) -> &mut Self { - self.transfer_upgrade_authority = Some(transfer_upgrade_authority); - self - } /// Add an additional account to the instruction. #[inline(always)] pub fn add_remaining_account(&mut self, account: solana_instruction::AccountMeta) -> &mut Self { @@ -312,38 +258,37 @@ impl CreateProgramGovernanceBuilder { } #[allow(clippy::clone_on_copy)] pub fn instruction(&self) -> solana_instruction::Instruction { + let realm_account = self.realm_account; + let program_governance_account = self.program_governance_account; + let governed_program = self.governed_program; + let program_data = self.program_data; + let current_upgrade_authority = self.current_upgrade_authority; + let governing_token_owner_record = self.governing_token_owner_record; + let payer = self.payer; + let bpf_upgradeable_loader_program = self.bpf_upgradeable_loader_program; + let system_program = self + .system_program + .unwrap_or(solana_address::address!("11111111111111111111111111111111")); + let governance_authority = self.governance_authority; + let realm_config = self.realm_config; + let voter_weight_record = self.voter_weight_record; let accounts = CreateProgramGovernance { - realm_account: self.realm_account.expect("realm_account is not set"), - program_governance_account: self - .program_governance_account - .expect("program_governance_account is not set"), - governed_program: self.governed_program.expect("governed_program is not set"), - program_data: self.program_data.expect("program_data is not set"), - current_upgrade_authority: self - .current_upgrade_authority - .expect("current_upgrade_authority is not set"), - governing_token_owner_record: self - .governing_token_owner_record - .expect("governing_token_owner_record is not set"), - payer: self.payer.expect("payer is not set"), - bpf_upgradeable_loader_program: self - .bpf_upgradeable_loader_program - .expect("bpf_upgradeable_loader_program is not set"), - system_program: self - .system_program - .unwrap_or(solana_address::address!("11111111111111111111111111111111")), - governance_authority: self - .governance_authority - .expect("governance_authority is not set"), - realm_config: self.realm_config.expect("realm_config is not set"), - voter_weight_record: self.voter_weight_record, + realm_account, + program_governance_account, + governed_program, + program_data, + current_upgrade_authority, + governing_token_owner_record, + payer, + bpf_upgradeable_loader_program, + system_program, + governance_authority, + realm_config, + voter_weight_record, }; let args = CreateProgramGovernanceInstructionArgs { - config: self.config.clone().expect("config is not set"), - transfer_upgrade_authority: self - .transfer_upgrade_authority - .clone() - .expect("transfer_upgrade_authority is not set"), + config: self.config.clone(), + transfer_upgrade_authority: self.transfer_upgrade_authority.clone(), }; accounts.instruction_with_remaining_accounts(args, &self.__remaining_accounts) @@ -580,119 +525,41 @@ pub struct CreateProgramGovernanceCpiBuilder<'a, 'b> { } impl<'a, 'b> CreateProgramGovernanceCpiBuilder<'a, 'b> { - pub fn new(program: &'b solana_account_info::AccountInfo<'a>) -> Self { - let instruction = Box::new(CreateProgramGovernanceCpiBuilderInstruction { - __program: program, - realm_account: None, - program_governance_account: None, - governed_program: None, - program_data: None, - current_upgrade_authority: None, - governing_token_owner_record: None, - payer: None, - bpf_upgradeable_loader_program: None, - system_program: None, - governance_authority: None, - realm_config: None, - voter_weight_record: None, - config: None, - transfer_upgrade_authority: None, - __remaining_accounts: Vec::new(), - }); - Self { instruction } - } - /// Realm account the created Governance belongs to - #[inline(always)] - pub fn realm_account( - &mut self, + pub fn new( + __program: &'b solana_account_info::AccountInfo<'a>, realm_account: &'b solana_account_info::AccountInfo<'a>, - ) -> &mut Self { - self.instruction.realm_account = Some(realm_account); - self - } - /// Program Governance account. seeds: ['program-governance', realm, governed_program] - #[inline(always)] - pub fn program_governance_account( - &mut self, program_governance_account: &'b solana_account_info::AccountInfo<'a>, - ) -> &mut Self { - self.instruction.program_governance_account = Some(program_governance_account); - self - } - /// Program governed by this Governance account - #[inline(always)] - pub fn governed_program( - &mut self, governed_program: &'b solana_account_info::AccountInfo<'a>, - ) -> &mut Self { - self.instruction.governed_program = Some(governed_program); - self - } - /// Program Data account of the Program governed by this Governance account - #[inline(always)] - pub fn program_data( - &mut self, program_data: &'b solana_account_info::AccountInfo<'a>, - ) -> &mut Self { - self.instruction.program_data = Some(program_data); - self - } - /// Current Upgrade Authority account of the Program governed by this Governance account - #[inline(always)] - pub fn current_upgrade_authority( - &mut self, current_upgrade_authority: &'b solana_account_info::AccountInfo<'a>, - ) -> &mut Self { - self.instruction.current_upgrade_authority = Some(current_upgrade_authority); - self - } - /// Governing TokenOwnerRecord account (Used only if not signed by RealmAuthority) - #[inline(always)] - pub fn governing_token_owner_record( - &mut self, governing_token_owner_record: &'b solana_account_info::AccountInfo<'a>, - ) -> &mut Self { - self.instruction.governing_token_owner_record = Some(governing_token_owner_record); - self - } - #[inline(always)] - pub fn payer(&mut self, payer: &'b solana_account_info::AccountInfo<'a>) -> &mut Self { - self.instruction.payer = Some(payer); - self - } - /// bpf_upgradeable_loader_program program - #[inline(always)] - pub fn bpf_upgradeable_loader_program( - &mut self, + payer: &'b solana_account_info::AccountInfo<'a>, bpf_upgradeable_loader_program: &'b solana_account_info::AccountInfo<'a>, - ) -> &mut Self { - self.instruction.bpf_upgradeable_loader_program = Some(bpf_upgradeable_loader_program); - self - } - #[inline(always)] - pub fn system_program( - &mut self, system_program: &'b solana_account_info::AccountInfo<'a>, - ) -> &mut Self { - self.instruction.system_program = Some(system_program); - self - } - #[inline(always)] - pub fn governance_authority( - &mut self, governance_authority: &'b solana_account_info::AccountInfo<'a>, - ) -> &mut Self { - self.instruction.governance_authority = Some(governance_authority); - self - } - /// RealmConfig account. seeds=['realm-config', realm] - #[inline(always)] - pub fn realm_config( - &mut self, realm_config: &'b solana_account_info::AccountInfo<'a>, - ) -> &mut Self { - self.instruction.realm_config = Some(realm_config); - self + config: GovernanceConfig, + transfer_upgrade_authority: bool, + ) -> Self { + let instruction = Box::new(CreateProgramGovernanceCpiBuilderInstruction { + __program, + realm_account, + program_governance_account, + governed_program, + program_data, + current_upgrade_authority, + governing_token_owner_record, + payer, + bpf_upgradeable_loader_program, + system_program, + governance_authority, + realm_config, + voter_weight_record: None, + config, + transfer_upgrade_authority, + __remaining_accounts: Vec::new(), + }); + Self { instruction } } /// `[optional account]` /// Optional Voter Weight Record @@ -704,16 +571,6 @@ impl<'a, 'b> CreateProgramGovernanceCpiBuilder<'a, 'b> { self.instruction.voter_weight_record = voter_weight_record; self } - #[inline(always)] - pub fn config(&mut self, config: GovernanceConfig) -> &mut Self { - self.instruction.config = Some(config); - self - } - #[inline(always)] - pub fn transfer_upgrade_authority(&mut self, transfer_upgrade_authority: bool) -> &mut Self { - self.instruction.transfer_upgrade_authority = Some(transfer_upgrade_authority); - self - } /// Add an additional account to the instruction. #[inline(always)] pub fn add_remaining_account( @@ -749,68 +606,22 @@ impl<'a, 'b> CreateProgramGovernanceCpiBuilder<'a, 'b> { #[allow(clippy::vec_init_then_push)] pub fn invoke_signed(&self, signers_seeds: &[&[&[u8]]]) -> solana_program_error::ProgramResult { let args = CreateProgramGovernanceInstructionArgs { - config: self.instruction.config.clone().expect("config is not set"), - transfer_upgrade_authority: self - .instruction - .transfer_upgrade_authority - .clone() - .expect("transfer_upgrade_authority is not set"), + config: self.instruction.config.clone(), + transfer_upgrade_authority: self.instruction.transfer_upgrade_authority.clone(), }; let instruction = CreateProgramGovernanceCpi { __program: self.instruction.__program, - - realm_account: self - .instruction - .realm_account - .expect("realm_account is not set"), - - program_governance_account: self - .instruction - .program_governance_account - .expect("program_governance_account is not set"), - - governed_program: self - .instruction - .governed_program - .expect("governed_program is not set"), - - program_data: self - .instruction - .program_data - .expect("program_data is not set"), - - current_upgrade_authority: self - .instruction - .current_upgrade_authority - .expect("current_upgrade_authority is not set"), - - governing_token_owner_record: self - .instruction - .governing_token_owner_record - .expect("governing_token_owner_record is not set"), - - payer: self.instruction.payer.expect("payer is not set"), - - bpf_upgradeable_loader_program: self - .instruction - .bpf_upgradeable_loader_program - .expect("bpf_upgradeable_loader_program is not set"), - - system_program: self - .instruction - .system_program - .expect("system_program is not set"), - - governance_authority: self - .instruction - .governance_authority - .expect("governance_authority is not set"), - - realm_config: self - .instruction - .realm_config - .expect("realm_config is not set"), - + realm_account: self.instruction.realm_account, + program_governance_account: self.instruction.program_governance_account, + governed_program: self.instruction.governed_program, + program_data: self.instruction.program_data, + current_upgrade_authority: self.instruction.current_upgrade_authority, + governing_token_owner_record: self.instruction.governing_token_owner_record, + payer: self.instruction.payer, + bpf_upgradeable_loader_program: self.instruction.bpf_upgradeable_loader_program, + system_program: self.instruction.system_program, + governance_authority: self.instruction.governance_authority, + realm_config: self.instruction.realm_config, voter_weight_record: self.instruction.voter_weight_record, __args: args, }; @@ -824,20 +635,20 @@ impl<'a, 'b> CreateProgramGovernanceCpiBuilder<'a, 'b> { #[derive(Clone, Debug)] struct CreateProgramGovernanceCpiBuilderInstruction<'a, 'b> { __program: &'b solana_account_info::AccountInfo<'a>, - realm_account: Option<&'b solana_account_info::AccountInfo<'a>>, - program_governance_account: Option<&'b solana_account_info::AccountInfo<'a>>, - governed_program: Option<&'b solana_account_info::AccountInfo<'a>>, - program_data: Option<&'b solana_account_info::AccountInfo<'a>>, - current_upgrade_authority: Option<&'b solana_account_info::AccountInfo<'a>>, - governing_token_owner_record: Option<&'b solana_account_info::AccountInfo<'a>>, - payer: Option<&'b solana_account_info::AccountInfo<'a>>, - bpf_upgradeable_loader_program: Option<&'b solana_account_info::AccountInfo<'a>>, - system_program: Option<&'b solana_account_info::AccountInfo<'a>>, - governance_authority: Option<&'b solana_account_info::AccountInfo<'a>>, - realm_config: Option<&'b solana_account_info::AccountInfo<'a>>, + realm_account: &'b solana_account_info::AccountInfo<'a>, + program_governance_account: &'b solana_account_info::AccountInfo<'a>, + governed_program: &'b solana_account_info::AccountInfo<'a>, + program_data: &'b solana_account_info::AccountInfo<'a>, + current_upgrade_authority: &'b solana_account_info::AccountInfo<'a>, + governing_token_owner_record: &'b solana_account_info::AccountInfo<'a>, + payer: &'b solana_account_info::AccountInfo<'a>, + bpf_upgradeable_loader_program: &'b solana_account_info::AccountInfo<'a>, + system_program: &'b solana_account_info::AccountInfo<'a>, + governance_authority: &'b solana_account_info::AccountInfo<'a>, + realm_config: &'b solana_account_info::AccountInfo<'a>, voter_weight_record: Option<&'b solana_account_info::AccountInfo<'a>>, - config: Option, - transfer_upgrade_authority: Option, + config: GovernanceConfig, + transfer_upgrade_authority: bool, /// Additional instruction accounts `(AccountInfo, is_writable, is_signer)`. __remaining_accounts: Vec<(&'b solana_account_info::AccountInfo<'a>, bool, bool)>, } diff --git a/e2e/governance/src/generated/instructions/create_proposal.rs b/e2e/governance/src/generated/instructions/create_proposal.rs index c4f4184..d79f42c 100644 --- a/e2e/governance/src/generated/instructions/create_proposal.rs +++ b/e2e/governance/src/generated/instructions/create_proposal.rs @@ -178,78 +178,65 @@ impl CreateProposalInstructionArgs { /// 8. `[]` realm_config /// 9. `[writable, optional]` voter_weight_record /// 10. `[optional]` proposal_deposit_account -#[derive(Clone, Debug, Default)] +#[derive(Clone, Debug)] pub struct CreateProposalBuilder { - realm_account: Option, - proposal_account: Option, - governance_account: Option, - token_owner_record: Option, - governing_token_mint: Option, - governance_authority: Option, - payer: Option, + realm_account: solana_address::Address, + proposal_account: solana_address::Address, + governance_account: solana_address::Address, + token_owner_record: solana_address::Address, + governing_token_mint: solana_address::Address, + governance_authority: solana_address::Address, + payer: solana_address::Address, system_program: Option, - realm_config: Option, + realm_config: solana_address::Address, voter_weight_record: Option, proposal_deposit_account: Option, - name: Option, - description_link: Option, - vote_type: Option, - options: Option>, - use_deny_option: Option, - proposal_seed: Option
, + name: String, + description_link: String, + vote_type: VoteType, + options: Vec, + use_deny_option: bool, + proposal_seed: Address, __remaining_accounts: Vec, } impl CreateProposalBuilder { - pub fn new() -> Self { - Self::default() - } - /// Realm account the created Proposal belongs to - #[inline(always)] - pub fn realm_account(&mut self, realm_account: solana_address::Address) -> &mut Self { - self.realm_account = Some(realm_account); - self - } - /// Proposal account. PDA seeds ['governance',governance, governing_token_mint, proposal_index] - #[inline(always)] - pub fn proposal_account(&mut self, proposal_account: solana_address::Address) -> &mut Self { - self.proposal_account = Some(proposal_account); - self - } - /// Governance account - #[inline(always)] - pub fn governance_account(&mut self, governance_account: solana_address::Address) -> &mut Self { - self.governance_account = Some(governance_account); - self - } - /// TokenOwnerRecord account of the Proposal owner - #[inline(always)] - pub fn token_owner_record(&mut self, token_owner_record: solana_address::Address) -> &mut Self { - self.token_owner_record = Some(token_owner_record); - self - } - /// Token Mint the Proposal is created for - #[inline(always)] - pub fn governing_token_mint( - &mut self, + pub fn new( + realm_account: solana_address::Address, + proposal_account: solana_address::Address, + governance_account: solana_address::Address, + token_owner_record: solana_address::Address, governing_token_mint: solana_address::Address, - ) -> &mut Self { - self.governing_token_mint = Some(governing_token_mint); - self - } - /// Governance Authority (Token Owner or Governance Delegate) - #[inline(always)] - pub fn governance_authority( - &mut self, governance_authority: solana_address::Address, - ) -> &mut Self { - self.governance_authority = Some(governance_authority); - self - } - #[inline(always)] - pub fn payer(&mut self, payer: solana_address::Address) -> &mut Self { - self.payer = Some(payer); - self + payer: solana_address::Address, + realm_config: solana_address::Address, + name: String, + description_link: String, + vote_type: VoteType, + options: Vec, + use_deny_option: bool, + proposal_seed: Address, + ) -> Self { + Self { + realm_account, + proposal_account, + governance_account, + token_owner_record, + governing_token_mint, + governance_authority, + payer, + system_program: None, + realm_config, + voter_weight_record: None, + proposal_deposit_account: None, + name, + description_link, + vote_type, + options, + use_deny_option, + proposal_seed, + __remaining_accounts: Vec::new(), + } } /// `[optional account, default to '11111111111111111111111111111111']` #[inline(always)] @@ -257,12 +244,6 @@ impl CreateProposalBuilder { self.system_program = Some(system_program); self } - /// RealmConfig account. PDA seeds: ['realm-config', realm] - #[inline(always)] - pub fn realm_config(&mut self, realm_config: solana_address::Address) -> &mut Self { - self.realm_config = Some(realm_config); - self - } /// `[optional account]` /// Optional Voter Weight Record #[inline(always)] @@ -285,36 +266,6 @@ impl CreateProposalBuilder { self.proposal_deposit_account = proposal_deposit_account; self } - #[inline(always)] - pub fn name(&mut self, name: String) -> &mut Self { - self.name = Some(name); - self - } - #[inline(always)] - pub fn description_link(&mut self, description_link: String) -> &mut Self { - self.description_link = Some(description_link); - self - } - #[inline(always)] - pub fn vote_type(&mut self, vote_type: VoteType) -> &mut Self { - self.vote_type = Some(vote_type); - self - } - #[inline(always)] - pub fn options(&mut self, options: Vec) -> &mut Self { - self.options = Some(options); - self - } - #[inline(always)] - pub fn use_deny_option(&mut self, use_deny_option: bool) -> &mut Self { - self.use_deny_option = Some(use_deny_option); - self - } - #[inline(always)] - pub fn proposal_seed(&mut self, proposal_seed: Address) -> &mut Self { - self.proposal_seed = Some(proposal_seed); - self - } /// Add an additional account to the instruction. #[inline(always)] pub fn add_remaining_account(&mut self, account: solana_instruction::AccountMeta) -> &mut Self { @@ -332,45 +283,39 @@ impl CreateProposalBuilder { } #[allow(clippy::clone_on_copy)] pub fn instruction(&self) -> solana_instruction::Instruction { + let realm_account = self.realm_account; + let proposal_account = self.proposal_account; + let governance_account = self.governance_account; + let token_owner_record = self.token_owner_record; + let governing_token_mint = self.governing_token_mint; + let governance_authority = self.governance_authority; + let payer = self.payer; + let system_program = self + .system_program + .unwrap_or(solana_address::address!("11111111111111111111111111111111")); + let realm_config = self.realm_config; + let voter_weight_record = self.voter_weight_record; + let proposal_deposit_account = self.proposal_deposit_account; let accounts = CreateProposal { - realm_account: self.realm_account.expect("realm_account is not set"), - proposal_account: self.proposal_account.expect("proposal_account is not set"), - governance_account: self - .governance_account - .expect("governance_account is not set"), - token_owner_record: self - .token_owner_record - .expect("token_owner_record is not set"), - governing_token_mint: self - .governing_token_mint - .expect("governing_token_mint is not set"), - governance_authority: self - .governance_authority - .expect("governance_authority is not set"), - payer: self.payer.expect("payer is not set"), - system_program: self - .system_program - .unwrap_or(solana_address::address!("11111111111111111111111111111111")), - realm_config: self.realm_config.expect("realm_config is not set"), - voter_weight_record: self.voter_weight_record, - proposal_deposit_account: self.proposal_deposit_account, + realm_account, + proposal_account, + governance_account, + token_owner_record, + governing_token_mint, + governance_authority, + payer, + system_program, + realm_config, + voter_weight_record, + proposal_deposit_account, }; let args = CreateProposalInstructionArgs { - name: self.name.clone().expect("name is not set"), - description_link: self - .description_link - .clone() - .expect("description_link is not set"), - vote_type: self.vote_type.clone().expect("vote_type is not set"), - options: self.options.clone().expect("options is not set"), - use_deny_option: self - .use_deny_option - .clone() - .expect("use_deny_option is not set"), - proposal_seed: self - .proposal_seed - .clone() - .expect("proposal_seed is not set"), + name: self.name.clone(), + description_link: self.description_link.clone(), + vote_type: self.vote_type.clone(), + options: self.options.clone(), + use_deny_option: self.use_deny_option.clone(), + proposal_seed: self.proposal_seed.clone(), }; accounts.instruction_with_remaining_accounts(args, &self.__remaining_accounts) @@ -607,105 +552,46 @@ pub struct CreateProposalCpiBuilder<'a, 'b> { } impl<'a, 'b> CreateProposalCpiBuilder<'a, 'b> { - pub fn new(program: &'b solana_account_info::AccountInfo<'a>) -> Self { - let instruction = Box::new(CreateProposalCpiBuilderInstruction { - __program: program, - realm_account: None, - proposal_account: None, - governance_account: None, - token_owner_record: None, - governing_token_mint: None, - governance_authority: None, - payer: None, - system_program: None, - realm_config: None, - voter_weight_record: None, - proposal_deposit_account: None, - name: None, - description_link: None, - vote_type: None, - options: None, - use_deny_option: None, - proposal_seed: None, - __remaining_accounts: Vec::new(), - }); - Self { instruction } - } - /// Realm account the created Proposal belongs to - #[inline(always)] - pub fn realm_account( - &mut self, + pub fn new( + __program: &'b solana_account_info::AccountInfo<'a>, realm_account: &'b solana_account_info::AccountInfo<'a>, - ) -> &mut Self { - self.instruction.realm_account = Some(realm_account); - self - } - /// Proposal account. PDA seeds ['governance',governance, governing_token_mint, proposal_index] - #[inline(always)] - pub fn proposal_account( - &mut self, proposal_account: &'b solana_account_info::AccountInfo<'a>, - ) -> &mut Self { - self.instruction.proposal_account = Some(proposal_account); - self - } - /// Governance account - #[inline(always)] - pub fn governance_account( - &mut self, governance_account: &'b solana_account_info::AccountInfo<'a>, - ) -> &mut Self { - self.instruction.governance_account = Some(governance_account); - self - } - /// TokenOwnerRecord account of the Proposal owner - #[inline(always)] - pub fn token_owner_record( - &mut self, token_owner_record: &'b solana_account_info::AccountInfo<'a>, - ) -> &mut Self { - self.instruction.token_owner_record = Some(token_owner_record); - self - } - /// Token Mint the Proposal is created for - #[inline(always)] - pub fn governing_token_mint( - &mut self, governing_token_mint: &'b solana_account_info::AccountInfo<'a>, - ) -> &mut Self { - self.instruction.governing_token_mint = Some(governing_token_mint); - self - } - /// Governance Authority (Token Owner or Governance Delegate) - #[inline(always)] - pub fn governance_authority( - &mut self, governance_authority: &'b solana_account_info::AccountInfo<'a>, - ) -> &mut Self { - self.instruction.governance_authority = Some(governance_authority); - self - } - #[inline(always)] - pub fn payer(&mut self, payer: &'b solana_account_info::AccountInfo<'a>) -> &mut Self { - self.instruction.payer = Some(payer); - self - } - #[inline(always)] - pub fn system_program( - &mut self, + payer: &'b solana_account_info::AccountInfo<'a>, system_program: &'b solana_account_info::AccountInfo<'a>, - ) -> &mut Self { - self.instruction.system_program = Some(system_program); - self - } - /// RealmConfig account. PDA seeds: ['realm-config', realm] - #[inline(always)] - pub fn realm_config( - &mut self, realm_config: &'b solana_account_info::AccountInfo<'a>, - ) -> &mut Self { - self.instruction.realm_config = Some(realm_config); - self + name: String, + description_link: String, + vote_type: VoteType, + options: Vec, + use_deny_option: bool, + proposal_seed: Address, + ) -> Self { + let instruction = Box::new(CreateProposalCpiBuilderInstruction { + __program, + realm_account, + proposal_account, + governance_account, + token_owner_record, + governing_token_mint, + governance_authority, + payer, + system_program, + realm_config, + voter_weight_record: None, + proposal_deposit_account: None, + name, + description_link, + vote_type, + options, + use_deny_option, + proposal_seed, + __remaining_accounts: Vec::new(), + }); + Self { instruction } } /// `[optional account]` /// Optional Voter Weight Record @@ -729,36 +615,6 @@ impl<'a, 'b> CreateProposalCpiBuilder<'a, 'b> { self.instruction.proposal_deposit_account = proposal_deposit_account; self } - #[inline(always)] - pub fn name(&mut self, name: String) -> &mut Self { - self.instruction.name = Some(name); - self - } - #[inline(always)] - pub fn description_link(&mut self, description_link: String) -> &mut Self { - self.instruction.description_link = Some(description_link); - self - } - #[inline(always)] - pub fn vote_type(&mut self, vote_type: VoteType) -> &mut Self { - self.instruction.vote_type = Some(vote_type); - self - } - #[inline(always)] - pub fn options(&mut self, options: Vec) -> &mut Self { - self.instruction.options = Some(options); - self - } - #[inline(always)] - pub fn use_deny_option(&mut self, use_deny_option: bool) -> &mut Self { - self.instruction.use_deny_option = Some(use_deny_option); - self - } - #[inline(always)] - pub fn proposal_seed(&mut self, proposal_seed: Address) -> &mut Self { - self.instruction.proposal_seed = Some(proposal_seed); - self - } /// Add an additional account to the instruction. #[inline(always)] pub fn add_remaining_account( @@ -794,80 +650,25 @@ impl<'a, 'b> CreateProposalCpiBuilder<'a, 'b> { #[allow(clippy::vec_init_then_push)] pub fn invoke_signed(&self, signers_seeds: &[&[&[u8]]]) -> solana_program_error::ProgramResult { let args = CreateProposalInstructionArgs { - name: self.instruction.name.clone().expect("name is not set"), - description_link: self - .instruction - .description_link - .clone() - .expect("description_link is not set"), - vote_type: self - .instruction - .vote_type - .clone() - .expect("vote_type is not set"), - options: self - .instruction - .options - .clone() - .expect("options is not set"), - use_deny_option: self - .instruction - .use_deny_option - .clone() - .expect("use_deny_option is not set"), - proposal_seed: self - .instruction - .proposal_seed - .clone() - .expect("proposal_seed is not set"), + name: self.instruction.name.clone(), + description_link: self.instruction.description_link.clone(), + vote_type: self.instruction.vote_type.clone(), + options: self.instruction.options.clone(), + use_deny_option: self.instruction.use_deny_option.clone(), + proposal_seed: self.instruction.proposal_seed.clone(), }; let instruction = CreateProposalCpi { __program: self.instruction.__program, - - realm_account: self - .instruction - .realm_account - .expect("realm_account is not set"), - - proposal_account: self - .instruction - .proposal_account - .expect("proposal_account is not set"), - - governance_account: self - .instruction - .governance_account - .expect("governance_account is not set"), - - token_owner_record: self - .instruction - .token_owner_record - .expect("token_owner_record is not set"), - - governing_token_mint: self - .instruction - .governing_token_mint - .expect("governing_token_mint is not set"), - - governance_authority: self - .instruction - .governance_authority - .expect("governance_authority is not set"), - - payer: self.instruction.payer.expect("payer is not set"), - - system_program: self - .instruction - .system_program - .expect("system_program is not set"), - - realm_config: self - .instruction - .realm_config - .expect("realm_config is not set"), - + realm_account: self.instruction.realm_account, + proposal_account: self.instruction.proposal_account, + governance_account: self.instruction.governance_account, + token_owner_record: self.instruction.token_owner_record, + governing_token_mint: self.instruction.governing_token_mint, + governance_authority: self.instruction.governance_authority, + payer: self.instruction.payer, + system_program: self.instruction.system_program, + realm_config: self.instruction.realm_config, voter_weight_record: self.instruction.voter_weight_record, - proposal_deposit_account: self.instruction.proposal_deposit_account, __args: args, }; @@ -881,23 +682,23 @@ impl<'a, 'b> CreateProposalCpiBuilder<'a, 'b> { #[derive(Clone, Debug)] struct CreateProposalCpiBuilderInstruction<'a, 'b> { __program: &'b solana_account_info::AccountInfo<'a>, - realm_account: Option<&'b solana_account_info::AccountInfo<'a>>, - proposal_account: Option<&'b solana_account_info::AccountInfo<'a>>, - governance_account: Option<&'b solana_account_info::AccountInfo<'a>>, - token_owner_record: Option<&'b solana_account_info::AccountInfo<'a>>, - governing_token_mint: Option<&'b solana_account_info::AccountInfo<'a>>, - governance_authority: Option<&'b solana_account_info::AccountInfo<'a>>, - payer: Option<&'b solana_account_info::AccountInfo<'a>>, - system_program: Option<&'b solana_account_info::AccountInfo<'a>>, - realm_config: Option<&'b solana_account_info::AccountInfo<'a>>, + realm_account: &'b solana_account_info::AccountInfo<'a>, + proposal_account: &'b solana_account_info::AccountInfo<'a>, + governance_account: &'b solana_account_info::AccountInfo<'a>, + token_owner_record: &'b solana_account_info::AccountInfo<'a>, + governing_token_mint: &'b solana_account_info::AccountInfo<'a>, + governance_authority: &'b solana_account_info::AccountInfo<'a>, + payer: &'b solana_account_info::AccountInfo<'a>, + system_program: &'b solana_account_info::AccountInfo<'a>, + realm_config: &'b solana_account_info::AccountInfo<'a>, voter_weight_record: Option<&'b solana_account_info::AccountInfo<'a>>, proposal_deposit_account: Option<&'b solana_account_info::AccountInfo<'a>>, - name: Option, - description_link: Option, - vote_type: Option, - options: Option>, - use_deny_option: Option, - proposal_seed: Option
, + name: String, + description_link: String, + vote_type: VoteType, + options: Vec, + use_deny_option: bool, + proposal_seed: Address, /// Additional instruction accounts `(AccountInfo, is_writable, is_signer)`. __remaining_accounts: Vec<(&'b solana_account_info::AccountInfo<'a>, bool, bool)>, } diff --git a/e2e/governance/src/generated/instructions/create_realm.rs b/e2e/governance/src/generated/instructions/create_realm.rs index 395868f..a597d1c 100644 --- a/e2e/governance/src/generated/instructions/create_realm.rs +++ b/e2e/governance/src/generated/instructions/create_realm.rs @@ -224,68 +224,59 @@ impl CreateRealmInstructionArgs { /// 12. `[optional]` max_community_voter_weight_addin /// 13. `[optional]` council_voter_weight_addin /// 14. `[optional]` max_council_voter_weight_addin -#[derive(Clone, Debug, Default)] +#[derive(Clone, Debug)] pub struct CreateRealmBuilder { - realm_account: Option, - realm_authority: Option, - community_token_mint: Option, - community_token_holding_account: Option, - payer: Option, + realm_account: solana_address::Address, + realm_authority: solana_address::Address, + community_token_mint: solana_address::Address, + community_token_holding_account: solana_address::Address, + payer: solana_address::Address, system_program: Option, token_program: Option, rent: Option, council_token_mint: Option, council_token_holding_account: Option, - realm_config: Option, + realm_config: solana_address::Address, community_voter_weight_addin: Option, max_community_voter_weight_addin: Option, council_voter_weight_addin: Option, max_council_voter_weight_addin: Option, - name: Option, - config_args: Option, + name: String, + config_args: RealmConfigParams, __remaining_accounts: Vec, } impl CreateRealmBuilder { - pub fn new() -> Self { - Self::default() - } - /// Governance Realm account - #[inline(always)] - pub fn realm_account(&mut self, realm_account: solana_address::Address) -> &mut Self { - self.realm_account = Some(realm_account); - self - } - /// The authority of the Realm - #[inline(always)] - pub fn realm_authority(&mut self, realm_authority: solana_address::Address) -> &mut Self { - self.realm_authority = Some(realm_authority); - self - } - /// The mint address of the token to be used as the community mint - #[inline(always)] - pub fn community_token_mint( - &mut self, + pub fn new( + realm_account: solana_address::Address, + realm_authority: solana_address::Address, community_token_mint: solana_address::Address, - ) -> &mut Self { - self.community_token_mint = Some(community_token_mint); - self - } - /// The account to hold the community tokens. - /// PDA seeds=['governance', realm, community_mint] - #[inline(always)] - pub fn community_token_holding_account( - &mut self, community_token_holding_account: solana_address::Address, - ) -> &mut Self { - self.community_token_holding_account = Some(community_token_holding_account); - self - } - /// the payer of this transaction - #[inline(always)] - pub fn payer(&mut self, payer: solana_address::Address) -> &mut Self { - self.payer = Some(payer); - self + payer: solana_address::Address, + realm_config: solana_address::Address, + name: String, + config_args: RealmConfigParams, + ) -> Self { + Self { + realm_account, + realm_authority, + community_token_mint, + community_token_holding_account, + payer, + system_program: None, + token_program: None, + rent: None, + council_token_mint: None, + council_token_holding_account: None, + realm_config, + community_voter_weight_addin: None, + max_community_voter_weight_addin: None, + council_voter_weight_addin: None, + max_council_voter_weight_addin: None, + name, + config_args, + __remaining_accounts: Vec::new(), + } } /// `[optional account, default to '11111111111111111111111111111111']` /// System Program @@ -330,12 +321,6 @@ impl CreateRealmBuilder { self.council_token_holding_account = council_token_holding_account; self } - /// Realm Config account - #[inline(always)] - pub fn realm_config(&mut self, realm_config: solana_address::Address) -> &mut Self { - self.realm_config = Some(realm_config); - self - } /// `[optional account]` /// Optional Community Voter Weight Addin Program Id #[inline(always)] @@ -376,16 +361,6 @@ impl CreateRealmBuilder { self.max_council_voter_weight_addin = max_council_voter_weight_addin; self } - #[inline(always)] - pub fn name(&mut self, name: String) -> &mut Self { - self.name = Some(name); - self - } - #[inline(always)] - pub fn config_args(&mut self, config_args: RealmConfigParams) -> &mut Self { - self.config_args = Some(config_args); - self - } /// Add an additional account to the instruction. #[inline(always)] pub fn add_remaining_account(&mut self, account: solana_instruction::AccountMeta) -> &mut Self { @@ -403,36 +378,47 @@ impl CreateRealmBuilder { } #[allow(clippy::clone_on_copy)] pub fn instruction(&self) -> solana_instruction::Instruction { + let realm_account = self.realm_account; + let realm_authority = self.realm_authority; + let community_token_mint = self.community_token_mint; + let community_token_holding_account = self.community_token_holding_account; + let payer = self.payer; + let system_program = self + .system_program + .unwrap_or(solana_address::address!("11111111111111111111111111111111")); + let token_program = self.token_program.unwrap_or(solana_address::address!( + "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA" + )); + let rent = self.rent.unwrap_or(solana_address::address!( + "SysvarRent111111111111111111111111111111111" + )); + let council_token_mint = self.council_token_mint; + let council_token_holding_account = self.council_token_holding_account; + let realm_config = self.realm_config; + let community_voter_weight_addin = self.community_voter_weight_addin; + let max_community_voter_weight_addin = self.max_community_voter_weight_addin; + let council_voter_weight_addin = self.council_voter_weight_addin; + let max_council_voter_weight_addin = self.max_council_voter_weight_addin; let accounts = CreateRealm { - realm_account: self.realm_account.expect("realm_account is not set"), - realm_authority: self.realm_authority.expect("realm_authority is not set"), - community_token_mint: self - .community_token_mint - .expect("community_token_mint is not set"), - community_token_holding_account: self - .community_token_holding_account - .expect("community_token_holding_account is not set"), - payer: self.payer.expect("payer is not set"), - system_program: self - .system_program - .unwrap_or(solana_address::address!("11111111111111111111111111111111")), - token_program: self.token_program.unwrap_or(solana_address::address!( - "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA" - )), - rent: self.rent.unwrap_or(solana_address::address!( - "SysvarRent111111111111111111111111111111111" - )), - council_token_mint: self.council_token_mint, - council_token_holding_account: self.council_token_holding_account, - realm_config: self.realm_config.expect("realm_config is not set"), - community_voter_weight_addin: self.community_voter_weight_addin, - max_community_voter_weight_addin: self.max_community_voter_weight_addin, - council_voter_weight_addin: self.council_voter_weight_addin, - max_council_voter_weight_addin: self.max_council_voter_weight_addin, + realm_account, + realm_authority, + community_token_mint, + community_token_holding_account, + payer, + system_program, + token_program, + rent, + council_token_mint, + council_token_holding_account, + realm_config, + community_voter_weight_addin, + max_community_voter_weight_addin, + council_voter_weight_addin, + max_council_voter_weight_addin, }; let args = CreateRealmInstructionArgs { - name: self.name.clone().expect("name is not set"), - config_args: self.config_args.clone().expect("config_args is not set"), + name: self.name.clone(), + config_args: self.config_args.clone(), }; accounts.instruction_with_remaining_accounts(args, &self.__remaining_accounts) @@ -748,97 +734,43 @@ pub struct CreateRealmCpiBuilder<'a, 'b> { } impl<'a, 'b> CreateRealmCpiBuilder<'a, 'b> { - pub fn new(program: &'b solana_account_info::AccountInfo<'a>) -> Self { + pub fn new( + __program: &'b solana_account_info::AccountInfo<'a>, + realm_account: &'b solana_account_info::AccountInfo<'a>, + realm_authority: &'b solana_account_info::AccountInfo<'a>, + community_token_mint: &'b solana_account_info::AccountInfo<'a>, + community_token_holding_account: &'b solana_account_info::AccountInfo<'a>, + payer: &'b solana_account_info::AccountInfo<'a>, + system_program: &'b solana_account_info::AccountInfo<'a>, + token_program: &'b solana_account_info::AccountInfo<'a>, + rent: &'b solana_account_info::AccountInfo<'a>, + realm_config: &'b solana_account_info::AccountInfo<'a>, + name: String, + config_args: RealmConfigParams, + ) -> Self { let instruction = Box::new(CreateRealmCpiBuilderInstruction { - __program: program, - realm_account: None, - realm_authority: None, - community_token_mint: None, - community_token_holding_account: None, - payer: None, - system_program: None, - token_program: None, - rent: None, + __program, + realm_account, + realm_authority, + community_token_mint, + community_token_holding_account, + payer, + system_program, + token_program, + rent, council_token_mint: None, council_token_holding_account: None, - realm_config: None, + realm_config, community_voter_weight_addin: None, max_community_voter_weight_addin: None, council_voter_weight_addin: None, max_council_voter_weight_addin: None, - name: None, - config_args: None, + name, + config_args, __remaining_accounts: Vec::new(), }); Self { instruction } } - /// Governance Realm account - #[inline(always)] - pub fn realm_account( - &mut self, - realm_account: &'b solana_account_info::AccountInfo<'a>, - ) -> &mut Self { - self.instruction.realm_account = Some(realm_account); - self - } - /// The authority of the Realm - #[inline(always)] - pub fn realm_authority( - &mut self, - realm_authority: &'b solana_account_info::AccountInfo<'a>, - ) -> &mut Self { - self.instruction.realm_authority = Some(realm_authority); - self - } - /// The mint address of the token to be used as the community mint - #[inline(always)] - pub fn community_token_mint( - &mut self, - community_token_mint: &'b solana_account_info::AccountInfo<'a>, - ) -> &mut Self { - self.instruction.community_token_mint = Some(community_token_mint); - self - } - /// The account to hold the community tokens. - /// PDA seeds=['governance', realm, community_mint] - #[inline(always)] - pub fn community_token_holding_account( - &mut self, - community_token_holding_account: &'b solana_account_info::AccountInfo<'a>, - ) -> &mut Self { - self.instruction.community_token_holding_account = Some(community_token_holding_account); - self - } - /// the payer of this transaction - #[inline(always)] - pub fn payer(&mut self, payer: &'b solana_account_info::AccountInfo<'a>) -> &mut Self { - self.instruction.payer = Some(payer); - self - } - /// System Program - #[inline(always)] - pub fn system_program( - &mut self, - system_program: &'b solana_account_info::AccountInfo<'a>, - ) -> &mut Self { - self.instruction.system_program = Some(system_program); - self - } - /// SPL Token Program - #[inline(always)] - pub fn token_program( - &mut self, - token_program: &'b solana_account_info::AccountInfo<'a>, - ) -> &mut Self { - self.instruction.token_program = Some(token_program); - self - } - /// SysVar Rent - #[inline(always)] - pub fn rent(&mut self, rent: &'b solana_account_info::AccountInfo<'a>) -> &mut Self { - self.instruction.rent = Some(rent); - self - } /// `[optional account]` /// The mint address of the token to be used as the council mint #[inline(always)] @@ -861,15 +793,6 @@ impl<'a, 'b> CreateRealmCpiBuilder<'a, 'b> { self.instruction.council_token_holding_account = council_token_holding_account; self } - /// Realm Config account - #[inline(always)] - pub fn realm_config( - &mut self, - realm_config: &'b solana_account_info::AccountInfo<'a>, - ) -> &mut Self { - self.instruction.realm_config = Some(realm_config); - self - } /// `[optional account]` /// Optional Community Voter Weight Addin Program Id #[inline(always)] @@ -910,16 +833,6 @@ impl<'a, 'b> CreateRealmCpiBuilder<'a, 'b> { self.instruction.max_council_voter_weight_addin = max_council_voter_weight_addin; self } - #[inline(always)] - pub fn name(&mut self, name: String) -> &mut Self { - self.instruction.name = Some(name); - self - } - #[inline(always)] - pub fn config_args(&mut self, config_args: RealmConfigParams) -> &mut Self { - self.instruction.config_args = Some(config_args); - self - } /// Add an additional account to the instruction. #[inline(always)] pub fn add_remaining_account( @@ -955,65 +868,25 @@ impl<'a, 'b> CreateRealmCpiBuilder<'a, 'b> { #[allow(clippy::vec_init_then_push)] pub fn invoke_signed(&self, signers_seeds: &[&[&[u8]]]) -> solana_program_error::ProgramResult { let args = CreateRealmInstructionArgs { - name: self.instruction.name.clone().expect("name is not set"), - config_args: self - .instruction - .config_args - .clone() - .expect("config_args is not set"), + name: self.instruction.name.clone(), + config_args: self.instruction.config_args.clone(), }; let instruction = CreateRealmCpi { __program: self.instruction.__program, - - realm_account: self - .instruction - .realm_account - .expect("realm_account is not set"), - - realm_authority: self - .instruction - .realm_authority - .expect("realm_authority is not set"), - - community_token_mint: self - .instruction - .community_token_mint - .expect("community_token_mint is not set"), - - community_token_holding_account: self - .instruction - .community_token_holding_account - .expect("community_token_holding_account is not set"), - - payer: self.instruction.payer.expect("payer is not set"), - - system_program: self - .instruction - .system_program - .expect("system_program is not set"), - - token_program: self - .instruction - .token_program - .expect("token_program is not set"), - - rent: self.instruction.rent.expect("rent is not set"), - + realm_account: self.instruction.realm_account, + realm_authority: self.instruction.realm_authority, + community_token_mint: self.instruction.community_token_mint, + community_token_holding_account: self.instruction.community_token_holding_account, + payer: self.instruction.payer, + system_program: self.instruction.system_program, + token_program: self.instruction.token_program, + rent: self.instruction.rent, council_token_mint: self.instruction.council_token_mint, - council_token_holding_account: self.instruction.council_token_holding_account, - - realm_config: self - .instruction - .realm_config - .expect("realm_config is not set"), - + realm_config: self.instruction.realm_config, community_voter_weight_addin: self.instruction.community_voter_weight_addin, - max_community_voter_weight_addin: self.instruction.max_community_voter_weight_addin, - council_voter_weight_addin: self.instruction.council_voter_weight_addin, - max_council_voter_weight_addin: self.instruction.max_council_voter_weight_addin, __args: args, }; @@ -1027,23 +900,23 @@ impl<'a, 'b> CreateRealmCpiBuilder<'a, 'b> { #[derive(Clone, Debug)] struct CreateRealmCpiBuilderInstruction<'a, 'b> { __program: &'b solana_account_info::AccountInfo<'a>, - realm_account: Option<&'b solana_account_info::AccountInfo<'a>>, - realm_authority: Option<&'b solana_account_info::AccountInfo<'a>>, - community_token_mint: Option<&'b solana_account_info::AccountInfo<'a>>, - community_token_holding_account: Option<&'b solana_account_info::AccountInfo<'a>>, - payer: Option<&'b solana_account_info::AccountInfo<'a>>, - system_program: Option<&'b solana_account_info::AccountInfo<'a>>, - token_program: Option<&'b solana_account_info::AccountInfo<'a>>, - rent: Option<&'b solana_account_info::AccountInfo<'a>>, + realm_account: &'b solana_account_info::AccountInfo<'a>, + realm_authority: &'b solana_account_info::AccountInfo<'a>, + community_token_mint: &'b solana_account_info::AccountInfo<'a>, + community_token_holding_account: &'b solana_account_info::AccountInfo<'a>, + payer: &'b solana_account_info::AccountInfo<'a>, + system_program: &'b solana_account_info::AccountInfo<'a>, + token_program: &'b solana_account_info::AccountInfo<'a>, + rent: &'b solana_account_info::AccountInfo<'a>, council_token_mint: Option<&'b solana_account_info::AccountInfo<'a>>, council_token_holding_account: Option<&'b solana_account_info::AccountInfo<'a>>, - realm_config: Option<&'b solana_account_info::AccountInfo<'a>>, + realm_config: &'b solana_account_info::AccountInfo<'a>, community_voter_weight_addin: Option<&'b solana_account_info::AccountInfo<'a>>, max_community_voter_weight_addin: Option<&'b solana_account_info::AccountInfo<'a>>, council_voter_weight_addin: Option<&'b solana_account_info::AccountInfo<'a>>, max_council_voter_weight_addin: Option<&'b solana_account_info::AccountInfo<'a>>, - name: Option, - config_args: Option, + name: String, + config_args: RealmConfigParams, /// Additional instruction accounts `(AccountInfo, is_writable, is_signer)`. __remaining_accounts: Vec<(&'b solana_account_info::AccountInfo<'a>, bool, bool)>, } diff --git a/e2e/governance/src/generated/instructions/create_token_governance.rs b/e2e/governance/src/generated/instructions/create_token_governance.rs index a63a4b0..1d610f4 100644 --- a/e2e/governance/src/generated/instructions/create_token_governance.rs +++ b/e2e/governance/src/generated/instructions/create_token_governance.rs @@ -166,71 +166,53 @@ impl CreateTokenGovernanceInstructionArgs { /// 8. `[signer]` governance_authority /// 9. `[]` realm_config /// 10. `[optional]` voter_weight_record -#[derive(Clone, Debug, Default)] +#[derive(Clone, Debug)] pub struct CreateTokenGovernanceBuilder { - realm_account: Option, - token_governance_account: Option, - token_account: Option, - token_account_authority: Option, - governing_token_owner_record: Option, - payer: Option, + realm_account: solana_address::Address, + token_governance_account: solana_address::Address, + token_account: solana_address::Address, + token_account_authority: solana_address::Address, + governing_token_owner_record: solana_address::Address, + payer: solana_address::Address, token_program: Option, system_program: Option, - governance_authority: Option, - realm_config: Option, + governance_authority: solana_address::Address, + realm_config: solana_address::Address, voter_weight_record: Option, - config: Option, - transfer_account_authorities: Option, + config: GovernanceConfig, + transfer_account_authorities: bool, __remaining_accounts: Vec, } impl CreateTokenGovernanceBuilder { - pub fn new() -> Self { - Self::default() - } - /// Realm account the created Governance belongs to - #[inline(always)] - pub fn realm_account(&mut self, realm_account: solana_address::Address) -> &mut Self { - self.realm_account = Some(realm_account); - self - } - /// Token Governance account. seeds=['token-governance', realm, governed_token] - #[inline(always)] - pub fn token_governance_account( - &mut self, + pub fn new( + realm_account: solana_address::Address, token_governance_account: solana_address::Address, - ) -> &mut Self { - self.token_governance_account = Some(token_governance_account); - self - } - /// Token account governed by this Governance account - #[inline(always)] - pub fn token_account(&mut self, token_account: solana_address::Address) -> &mut Self { - self.token_account = Some(token_account); - self - } - /// Current token account authority (AccountOwner and optionally CloseAccount - #[inline(always)] - pub fn token_account_authority( - &mut self, + token_account: solana_address::Address, token_account_authority: solana_address::Address, - ) -> &mut Self { - self.token_account_authority = Some(token_account_authority); - self - } - /// Governing TokenOwnerRecord account (Used only if not signed by RealmAuthority - #[inline(always)] - pub fn governing_token_owner_record( - &mut self, governing_token_owner_record: solana_address::Address, - ) -> &mut Self { - self.governing_token_owner_record = Some(governing_token_owner_record); - self - } - #[inline(always)] - pub fn payer(&mut self, payer: solana_address::Address) -> &mut Self { - self.payer = Some(payer); - self + payer: solana_address::Address, + governance_authority: solana_address::Address, + realm_config: solana_address::Address, + config: GovernanceConfig, + transfer_account_authorities: bool, + ) -> Self { + Self { + realm_account, + token_governance_account, + token_account, + token_account_authority, + governing_token_owner_record, + payer, + token_program: None, + system_program: None, + governance_authority, + realm_config, + voter_weight_record: None, + config, + transfer_account_authorities, + __remaining_accounts: Vec::new(), + } } /// `[optional account, default to 'TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA']` #[inline(always)] @@ -244,20 +226,6 @@ impl CreateTokenGovernanceBuilder { self.system_program = Some(system_program); self } - #[inline(always)] - pub fn governance_authority( - &mut self, - governance_authority: solana_address::Address, - ) -> &mut Self { - self.governance_authority = Some(governance_authority); - self - } - /// seeds=['realm-config', realm] - #[inline(always)] - pub fn realm_config(&mut self, realm_config: solana_address::Address) -> &mut Self { - self.realm_config = Some(realm_config); - self - } /// `[optional account]` /// Optional Voter Weight Record #[inline(always)] @@ -268,19 +236,6 @@ impl CreateTokenGovernanceBuilder { self.voter_weight_record = voter_weight_record; self } - #[inline(always)] - pub fn config(&mut self, config: GovernanceConfig) -> &mut Self { - self.config = Some(config); - self - } - #[inline(always)] - pub fn transfer_account_authorities( - &mut self, - transfer_account_authorities: bool, - ) -> &mut Self { - self.transfer_account_authorities = Some(transfer_account_authorities); - self - } /// Add an additional account to the instruction. #[inline(always)] pub fn add_remaining_account(&mut self, account: solana_instruction::AccountMeta) -> &mut Self { @@ -298,37 +253,37 @@ impl CreateTokenGovernanceBuilder { } #[allow(clippy::clone_on_copy)] pub fn instruction(&self) -> solana_instruction::Instruction { + let realm_account = self.realm_account; + let token_governance_account = self.token_governance_account; + let token_account = self.token_account; + let token_account_authority = self.token_account_authority; + let governing_token_owner_record = self.governing_token_owner_record; + let payer = self.payer; + let token_program = self.token_program.unwrap_or(solana_address::address!( + "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA" + )); + let system_program = self + .system_program + .unwrap_or(solana_address::address!("11111111111111111111111111111111")); + let governance_authority = self.governance_authority; + let realm_config = self.realm_config; + let voter_weight_record = self.voter_weight_record; let accounts = CreateTokenGovernance { - realm_account: self.realm_account.expect("realm_account is not set"), - token_governance_account: self - .token_governance_account - .expect("token_governance_account is not set"), - token_account: self.token_account.expect("token_account is not set"), - token_account_authority: self - .token_account_authority - .expect("token_account_authority is not set"), - governing_token_owner_record: self - .governing_token_owner_record - .expect("governing_token_owner_record is not set"), - payer: self.payer.expect("payer is not set"), - token_program: self.token_program.unwrap_or(solana_address::address!( - "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA" - )), - system_program: self - .system_program - .unwrap_or(solana_address::address!("11111111111111111111111111111111")), - governance_authority: self - .governance_authority - .expect("governance_authority is not set"), - realm_config: self.realm_config.expect("realm_config is not set"), - voter_weight_record: self.voter_weight_record, + realm_account, + token_governance_account, + token_account, + token_account_authority, + governing_token_owner_record, + payer, + token_program, + system_program, + governance_authority, + realm_config, + voter_weight_record, }; let args = CreateTokenGovernanceInstructionArgs { - config: self.config.clone().expect("config is not set"), - transfer_account_authorities: self - .transfer_account_authorities - .clone() - .expect("transfer_account_authorities is not set"), + config: self.config.clone(), + transfer_account_authorities: self.transfer_account_authorities.clone(), }; accounts.instruction_with_remaining_accounts(args, &self.__remaining_accounts) @@ -554,108 +509,39 @@ pub struct CreateTokenGovernanceCpiBuilder<'a, 'b> { } impl<'a, 'b> CreateTokenGovernanceCpiBuilder<'a, 'b> { - pub fn new(program: &'b solana_account_info::AccountInfo<'a>) -> Self { - let instruction = Box::new(CreateTokenGovernanceCpiBuilderInstruction { - __program: program, - realm_account: None, - token_governance_account: None, - token_account: None, - token_account_authority: None, - governing_token_owner_record: None, - payer: None, - token_program: None, - system_program: None, - governance_authority: None, - realm_config: None, - voter_weight_record: None, - config: None, - transfer_account_authorities: None, - __remaining_accounts: Vec::new(), - }); - Self { instruction } - } - /// Realm account the created Governance belongs to - #[inline(always)] - pub fn realm_account( - &mut self, + pub fn new( + __program: &'b solana_account_info::AccountInfo<'a>, realm_account: &'b solana_account_info::AccountInfo<'a>, - ) -> &mut Self { - self.instruction.realm_account = Some(realm_account); - self - } - /// Token Governance account. seeds=['token-governance', realm, governed_token] - #[inline(always)] - pub fn token_governance_account( - &mut self, token_governance_account: &'b solana_account_info::AccountInfo<'a>, - ) -> &mut Self { - self.instruction.token_governance_account = Some(token_governance_account); - self - } - /// Token account governed by this Governance account - #[inline(always)] - pub fn token_account( - &mut self, token_account: &'b solana_account_info::AccountInfo<'a>, - ) -> &mut Self { - self.instruction.token_account = Some(token_account); - self - } - /// Current token account authority (AccountOwner and optionally CloseAccount - #[inline(always)] - pub fn token_account_authority( - &mut self, token_account_authority: &'b solana_account_info::AccountInfo<'a>, - ) -> &mut Self { - self.instruction.token_account_authority = Some(token_account_authority); - self - } - /// Governing TokenOwnerRecord account (Used only if not signed by RealmAuthority - #[inline(always)] - pub fn governing_token_owner_record( - &mut self, governing_token_owner_record: &'b solana_account_info::AccountInfo<'a>, - ) -> &mut Self { - self.instruction.governing_token_owner_record = Some(governing_token_owner_record); - self - } - #[inline(always)] - pub fn payer(&mut self, payer: &'b solana_account_info::AccountInfo<'a>) -> &mut Self { - self.instruction.payer = Some(payer); - self - } - #[inline(always)] - pub fn token_program( - &mut self, + payer: &'b solana_account_info::AccountInfo<'a>, token_program: &'b solana_account_info::AccountInfo<'a>, - ) -> &mut Self { - self.instruction.token_program = Some(token_program); - self - } - #[inline(always)] - pub fn system_program( - &mut self, system_program: &'b solana_account_info::AccountInfo<'a>, - ) -> &mut Self { - self.instruction.system_program = Some(system_program); - self - } - #[inline(always)] - pub fn governance_authority( - &mut self, governance_authority: &'b solana_account_info::AccountInfo<'a>, - ) -> &mut Self { - self.instruction.governance_authority = Some(governance_authority); - self - } - /// seeds=['realm-config', realm] - #[inline(always)] - pub fn realm_config( - &mut self, realm_config: &'b solana_account_info::AccountInfo<'a>, - ) -> &mut Self { - self.instruction.realm_config = Some(realm_config); - self + config: GovernanceConfig, + transfer_account_authorities: bool, + ) -> Self { + let instruction = Box::new(CreateTokenGovernanceCpiBuilderInstruction { + __program, + realm_account, + token_governance_account, + token_account, + token_account_authority, + governing_token_owner_record, + payer, + token_program, + system_program, + governance_authority, + realm_config, + voter_weight_record: None, + config, + transfer_account_authorities, + __remaining_accounts: Vec::new(), + }); + Self { instruction } } /// `[optional account]` /// Optional Voter Weight Record @@ -667,19 +553,6 @@ impl<'a, 'b> CreateTokenGovernanceCpiBuilder<'a, 'b> { self.instruction.voter_weight_record = voter_weight_record; self } - #[inline(always)] - pub fn config(&mut self, config: GovernanceConfig) -> &mut Self { - self.instruction.config = Some(config); - self - } - #[inline(always)] - pub fn transfer_account_authorities( - &mut self, - transfer_account_authorities: bool, - ) -> &mut Self { - self.instruction.transfer_account_authorities = Some(transfer_account_authorities); - self - } /// Add an additional account to the instruction. #[inline(always)] pub fn add_remaining_account( @@ -715,63 +588,21 @@ impl<'a, 'b> CreateTokenGovernanceCpiBuilder<'a, 'b> { #[allow(clippy::vec_init_then_push)] pub fn invoke_signed(&self, signers_seeds: &[&[&[u8]]]) -> solana_program_error::ProgramResult { let args = CreateTokenGovernanceInstructionArgs { - config: self.instruction.config.clone().expect("config is not set"), - transfer_account_authorities: self - .instruction - .transfer_account_authorities - .clone() - .expect("transfer_account_authorities is not set"), + config: self.instruction.config.clone(), + transfer_account_authorities: self.instruction.transfer_account_authorities.clone(), }; let instruction = CreateTokenGovernanceCpi { __program: self.instruction.__program, - - realm_account: self - .instruction - .realm_account - .expect("realm_account is not set"), - - token_governance_account: self - .instruction - .token_governance_account - .expect("token_governance_account is not set"), - - token_account: self - .instruction - .token_account - .expect("token_account is not set"), - - token_account_authority: self - .instruction - .token_account_authority - .expect("token_account_authority is not set"), - - governing_token_owner_record: self - .instruction - .governing_token_owner_record - .expect("governing_token_owner_record is not set"), - - payer: self.instruction.payer.expect("payer is not set"), - - token_program: self - .instruction - .token_program - .expect("token_program is not set"), - - system_program: self - .instruction - .system_program - .expect("system_program is not set"), - - governance_authority: self - .instruction - .governance_authority - .expect("governance_authority is not set"), - - realm_config: self - .instruction - .realm_config - .expect("realm_config is not set"), - + realm_account: self.instruction.realm_account, + token_governance_account: self.instruction.token_governance_account, + token_account: self.instruction.token_account, + token_account_authority: self.instruction.token_account_authority, + governing_token_owner_record: self.instruction.governing_token_owner_record, + payer: self.instruction.payer, + token_program: self.instruction.token_program, + system_program: self.instruction.system_program, + governance_authority: self.instruction.governance_authority, + realm_config: self.instruction.realm_config, voter_weight_record: self.instruction.voter_weight_record, __args: args, }; @@ -785,19 +616,19 @@ impl<'a, 'b> CreateTokenGovernanceCpiBuilder<'a, 'b> { #[derive(Clone, Debug)] struct CreateTokenGovernanceCpiBuilderInstruction<'a, 'b> { __program: &'b solana_account_info::AccountInfo<'a>, - realm_account: Option<&'b solana_account_info::AccountInfo<'a>>, - token_governance_account: Option<&'b solana_account_info::AccountInfo<'a>>, - token_account: Option<&'b solana_account_info::AccountInfo<'a>>, - token_account_authority: Option<&'b solana_account_info::AccountInfo<'a>>, - governing_token_owner_record: Option<&'b solana_account_info::AccountInfo<'a>>, - payer: Option<&'b solana_account_info::AccountInfo<'a>>, - token_program: Option<&'b solana_account_info::AccountInfo<'a>>, - system_program: Option<&'b solana_account_info::AccountInfo<'a>>, - governance_authority: Option<&'b solana_account_info::AccountInfo<'a>>, - realm_config: Option<&'b solana_account_info::AccountInfo<'a>>, + realm_account: &'b solana_account_info::AccountInfo<'a>, + token_governance_account: &'b solana_account_info::AccountInfo<'a>, + token_account: &'b solana_account_info::AccountInfo<'a>, + token_account_authority: &'b solana_account_info::AccountInfo<'a>, + governing_token_owner_record: &'b solana_account_info::AccountInfo<'a>, + payer: &'b solana_account_info::AccountInfo<'a>, + token_program: &'b solana_account_info::AccountInfo<'a>, + system_program: &'b solana_account_info::AccountInfo<'a>, + governance_authority: &'b solana_account_info::AccountInfo<'a>, + realm_config: &'b solana_account_info::AccountInfo<'a>, voter_weight_record: Option<&'b solana_account_info::AccountInfo<'a>>, - config: Option, - transfer_account_authorities: Option, + config: GovernanceConfig, + transfer_account_authorities: bool, /// Additional instruction accounts `(AccountInfo, is_writable, is_signer)`. __remaining_accounts: Vec<(&'b solana_account_info::AccountInfo<'a>, bool, bool)>, } diff --git a/e2e/governance/src/generated/instructions/create_token_owner_record.rs b/e2e/governance/src/generated/instructions/create_token_owner_record.rs index 92fb4b7..bc91af5 100644 --- a/e2e/governance/src/generated/instructions/create_token_owner_record.rs +++ b/e2e/governance/src/generated/instructions/create_token_owner_record.rs @@ -104,33 +104,33 @@ impl Default for CreateTokenOwnerRecordInstructionData { /// 3. `[]` governing_token_mint /// 4. `[signer]` payer /// 5. `[optional]` system_program (default to `11111111111111111111111111111111`) -#[derive(Clone, Debug, Default)] +#[derive(Clone, Debug)] pub struct CreateTokenOwnerRecordBuilder { - realm_account: Option, - governing_token_owner_account: Option, + realm_account: solana_address::Address, + governing_token_owner_account: solana_address::Address, token_owner_record: Option, - governing_token_mint: Option, - payer: Option, + governing_token_mint: solana_address::Address, + payer: solana_address::Address, system_program: Option, __remaining_accounts: Vec, } impl CreateTokenOwnerRecordBuilder { - pub fn new() -> Self { - Self::default() - } - #[inline(always)] - pub fn realm_account(&mut self, realm_account: solana_address::Address) -> &mut Self { - self.realm_account = Some(realm_account); - self - } - #[inline(always)] - pub fn governing_token_owner_account( - &mut self, + pub fn new( + realm_account: solana_address::Address, governing_token_owner_account: solana_address::Address, - ) -> &mut Self { - self.governing_token_owner_account = Some(governing_token_owner_account); - self + governing_token_mint: solana_address::Address, + payer: solana_address::Address, + ) -> Self { + Self { + realm_account, + governing_token_owner_account, + token_owner_record: None, + governing_token_mint, + payer, + system_program: None, + __remaining_accounts: Vec::new(), + } } /// `[optional account, default to PDA derived from 'tokenOwnerRecord']` /// seeds=['governance', realm, governing_token_mint, governing_token_owner] @@ -139,19 +139,6 @@ impl CreateTokenOwnerRecordBuilder { self.token_owner_record = Some(token_owner_record); self } - #[inline(always)] - pub fn governing_token_mint( - &mut self, - governing_token_mint: solana_address::Address, - ) -> &mut Self { - self.governing_token_mint = Some(governing_token_mint); - self - } - #[inline(always)] - pub fn payer(&mut self, payer: solana_address::Address) -> &mut Self { - self.payer = Some(payer); - self - } /// `[optional account, default to '11111111111111111111111111111111']` #[inline(always)] pub fn system_program(&mut self, system_program: solana_address::Address) -> &mut Self { @@ -175,33 +162,28 @@ impl CreateTokenOwnerRecordBuilder { } #[allow(clippy::clone_on_copy)] pub fn instruction(&self) -> solana_instruction::Instruction { + let realm_account = self.realm_account; + let governing_token_owner_account = self.governing_token_owner_account; let token_owner_record = self.token_owner_record.unwrap_or_else(|| { crate::pdas::find_token_owner_record_pda( - &self - .realm_account - .expect("realm_account is needed for token_owner_record PDA"), - &self - .governing_token_mint - .expect("governing_token_mint is needed for token_owner_record PDA"), - &self - .governing_token_owner_account - .expect("governing_token_owner_account is needed for token_owner_record PDA"), + &self.realm_account, + &self.governing_token_mint, + &self.governing_token_owner_account, ) .0 }); + let governing_token_mint = self.governing_token_mint; + let payer = self.payer; + let system_program = self + .system_program + .unwrap_or(solana_address::address!("11111111111111111111111111111111")); let accounts = CreateTokenOwnerRecord { - realm_account: self.realm_account.expect("realm_account is not set"), - governing_token_owner_account: self - .governing_token_owner_account - .expect("governing_token_owner_account is not set"), + realm_account, + governing_token_owner_account, token_owner_record, - governing_token_mint: self - .governing_token_mint - .expect("governing_token_mint is not set"), - payer: self.payer.expect("payer is not set"), - system_program: self - .system_program - .unwrap_or(solana_address::address!("11111111111111111111111111111111")), + governing_token_mint, + payer, + system_program, }; accounts.instruction_with_remaining_accounts(&self.__remaining_accounts) @@ -356,64 +338,26 @@ pub struct CreateTokenOwnerRecordCpiBuilder<'a, 'b> { } impl<'a, 'b> CreateTokenOwnerRecordCpiBuilder<'a, 'b> { - pub fn new(program: &'b solana_account_info::AccountInfo<'a>) -> Self { - let instruction = Box::new(CreateTokenOwnerRecordCpiBuilderInstruction { - __program: program, - realm_account: None, - governing_token_owner_account: None, - token_owner_record: None, - governing_token_mint: None, - payer: None, - system_program: None, - __remaining_accounts: Vec::new(), - }); - Self { instruction } - } - #[inline(always)] - pub fn realm_account( - &mut self, + pub fn new( + __program: &'b solana_account_info::AccountInfo<'a>, realm_account: &'b solana_account_info::AccountInfo<'a>, - ) -> &mut Self { - self.instruction.realm_account = Some(realm_account); - self - } - #[inline(always)] - pub fn governing_token_owner_account( - &mut self, governing_token_owner_account: &'b solana_account_info::AccountInfo<'a>, - ) -> &mut Self { - self.instruction.governing_token_owner_account = Some(governing_token_owner_account); - self - } - /// seeds=['governance', realm, governing_token_mint, governing_token_owner] - #[inline(always)] - pub fn token_owner_record( - &mut self, token_owner_record: &'b solana_account_info::AccountInfo<'a>, - ) -> &mut Self { - self.instruction.token_owner_record = Some(token_owner_record); - self - } - #[inline(always)] - pub fn governing_token_mint( - &mut self, governing_token_mint: &'b solana_account_info::AccountInfo<'a>, - ) -> &mut Self { - self.instruction.governing_token_mint = Some(governing_token_mint); - self - } - #[inline(always)] - pub fn payer(&mut self, payer: &'b solana_account_info::AccountInfo<'a>) -> &mut Self { - self.instruction.payer = Some(payer); - self - } - #[inline(always)] - pub fn system_program( - &mut self, + payer: &'b solana_account_info::AccountInfo<'a>, system_program: &'b solana_account_info::AccountInfo<'a>, - ) -> &mut Self { - self.instruction.system_program = Some(system_program); - self + ) -> Self { + let instruction = Box::new(CreateTokenOwnerRecordCpiBuilderInstruction { + __program, + realm_account, + governing_token_owner_account, + token_owner_record, + governing_token_mint, + payer, + system_program, + __remaining_accounts: Vec::new(), + }); + Self { instruction } } /// Add an additional account to the instruction. #[inline(always)] @@ -451,33 +395,12 @@ impl<'a, 'b> CreateTokenOwnerRecordCpiBuilder<'a, 'b> { pub fn invoke_signed(&self, signers_seeds: &[&[&[u8]]]) -> solana_program_error::ProgramResult { let instruction = CreateTokenOwnerRecordCpi { __program: self.instruction.__program, - - realm_account: self - .instruction - .realm_account - .expect("realm_account is not set"), - - governing_token_owner_account: self - .instruction - .governing_token_owner_account - .expect("governing_token_owner_account is not set"), - - token_owner_record: self - .instruction - .token_owner_record - .expect("token_owner_record is not set"), - - governing_token_mint: self - .instruction - .governing_token_mint - .expect("governing_token_mint is not set"), - - payer: self.instruction.payer.expect("payer is not set"), - - system_program: self - .instruction - .system_program - .expect("system_program is not set"), + realm_account: self.instruction.realm_account, + governing_token_owner_account: self.instruction.governing_token_owner_account, + token_owner_record: self.instruction.token_owner_record, + governing_token_mint: self.instruction.governing_token_mint, + payer: self.instruction.payer, + system_program: self.instruction.system_program, }; instruction.invoke_signed_with_remaining_accounts( signers_seeds, @@ -489,12 +412,12 @@ impl<'a, 'b> CreateTokenOwnerRecordCpiBuilder<'a, 'b> { #[derive(Clone, Debug)] struct CreateTokenOwnerRecordCpiBuilderInstruction<'a, 'b> { __program: &'b solana_account_info::AccountInfo<'a>, - realm_account: Option<&'b solana_account_info::AccountInfo<'a>>, - governing_token_owner_account: Option<&'b solana_account_info::AccountInfo<'a>>, - token_owner_record: Option<&'b solana_account_info::AccountInfo<'a>>, - governing_token_mint: Option<&'b solana_account_info::AccountInfo<'a>>, - payer: Option<&'b solana_account_info::AccountInfo<'a>>, - system_program: Option<&'b solana_account_info::AccountInfo<'a>>, + realm_account: &'b solana_account_info::AccountInfo<'a>, + governing_token_owner_account: &'b solana_account_info::AccountInfo<'a>, + token_owner_record: &'b solana_account_info::AccountInfo<'a>, + governing_token_mint: &'b solana_account_info::AccountInfo<'a>, + payer: &'b solana_account_info::AccountInfo<'a>, + system_program: &'b solana_account_info::AccountInfo<'a>, /// Additional instruction accounts `(AccountInfo, is_writable, is_signer)`. __remaining_accounts: Vec<(&'b solana_account_info::AccountInfo<'a>, bool, bool)>, } diff --git a/e2e/governance/src/generated/instructions/deposit_governing_tokens.rs b/e2e/governance/src/generated/instructions/deposit_governing_tokens.rs index 5ef3ce3..e6c2be4 100644 --- a/e2e/governance/src/generated/instructions/deposit_governing_tokens.rs +++ b/e2e/governance/src/generated/instructions/deposit_governing_tokens.rs @@ -147,77 +147,48 @@ impl DepositGoverningTokensInstructionArgs { /// 7. `[optional]` system_program (default to `11111111111111111111111111111111`) /// 8. `[optional]` token_program (default to `TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA`) /// 9. `[]` realm_config_account -#[derive(Clone, Debug, Default)] +#[derive(Clone, Debug)] pub struct DepositGoverningTokensBuilder { - realm_account: Option, - governing_token_holding_account: Option, - governing_token_source_account: Option, - governing_token_owner_account: Option, - governing_token_source_account_authority: Option, - token_owner_record: Option, - payer: Option, + realm_account: solana_address::Address, + governing_token_holding_account: solana_address::Address, + governing_token_source_account: solana_address::Address, + governing_token_owner_account: solana_address::Address, + governing_token_source_account_authority: solana_address::Address, + token_owner_record: solana_address::Address, + payer: solana_address::Address, system_program: Option, token_program: Option, - realm_config_account: Option, - amount: Option, + realm_config_account: solana_address::Address, + amount: u64, __remaining_accounts: Vec, } impl DepositGoverningTokensBuilder { - pub fn new() -> Self { - Self::default() - } - #[inline(always)] - pub fn realm_account(&mut self, realm_account: solana_address::Address) -> &mut Self { - self.realm_account = Some(realm_account); - self - } - /// seeds=['governance', realm, governing_token_mint] - #[inline(always)] - pub fn governing_token_holding_account( - &mut self, + pub fn new( + realm_account: solana_address::Address, governing_token_holding_account: solana_address::Address, - ) -> &mut Self { - self.governing_token_holding_account = Some(governing_token_holding_account); - self - } - /// It can either be spl-token TokenAccount or MintAccount. Tokens will be transferred or minted to the holding account - #[inline(always)] - pub fn governing_token_source_account( - &mut self, governing_token_source_account: solana_address::Address, - ) -> &mut Self { - self.governing_token_source_account = Some(governing_token_source_account); - self - } - #[inline(always)] - pub fn governing_token_owner_account( - &mut self, governing_token_owner_account: solana_address::Address, - ) -> &mut Self { - self.governing_token_owner_account = Some(governing_token_owner_account); - self - } - /// It should be owner for TokenAccount and mint_authority for MintAccount - #[inline(always)] - pub fn governing_token_source_account_authority( - &mut self, governing_token_source_account_authority: solana_address::Address, - ) -> &mut Self { - self.governing_token_source_account_authority = - Some(governing_token_source_account_authority); - self - } - /// seeds=['governance', realm, governing_token_mint, governing_token_owner] - #[inline(always)] - pub fn token_owner_record(&mut self, token_owner_record: solana_address::Address) -> &mut Self { - self.token_owner_record = Some(token_owner_record); - self - } - #[inline(always)] - pub fn payer(&mut self, payer: solana_address::Address) -> &mut Self { - self.payer = Some(payer); - self + token_owner_record: solana_address::Address, + payer: solana_address::Address, + realm_config_account: solana_address::Address, + amount: u64, + ) -> Self { + Self { + realm_account, + governing_token_holding_account, + governing_token_source_account, + governing_token_owner_account, + governing_token_source_account_authority, + token_owner_record, + payer, + system_program: None, + token_program: None, + realm_config_account, + amount, + __remaining_accounts: Vec::new(), + } } /// `[optional account, default to '11111111111111111111111111111111']` #[inline(always)] @@ -231,20 +202,6 @@ impl DepositGoverningTokensBuilder { self.token_program = Some(token_program); self } - /// seeds=['realm-config', realm] - #[inline(always)] - pub fn realm_config_account( - &mut self, - realm_config_account: solana_address::Address, - ) -> &mut Self { - self.realm_config_account = Some(realm_config_account); - self - } - #[inline(always)] - pub fn amount(&mut self, amount: u64) -> &mut Self { - self.amount = Some(amount); - self - } /// Add an additional account to the instruction. #[inline(always)] pub fn add_remaining_account(&mut self, account: solana_instruction::AccountMeta) -> &mut Self { @@ -262,36 +219,35 @@ impl DepositGoverningTokensBuilder { } #[allow(clippy::clone_on_copy)] pub fn instruction(&self) -> solana_instruction::Instruction { + let realm_account = self.realm_account; + let governing_token_holding_account = self.governing_token_holding_account; + let governing_token_source_account = self.governing_token_source_account; + let governing_token_owner_account = self.governing_token_owner_account; + let governing_token_source_account_authority = + self.governing_token_source_account_authority; + let token_owner_record = self.token_owner_record; + let payer = self.payer; + let system_program = self + .system_program + .unwrap_or(solana_address::address!("11111111111111111111111111111111")); + let token_program = self.token_program.unwrap_or(solana_address::address!( + "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA" + )); + let realm_config_account = self.realm_config_account; let accounts = DepositGoverningTokens { - realm_account: self.realm_account.expect("realm_account is not set"), - governing_token_holding_account: self - .governing_token_holding_account - .expect("governing_token_holding_account is not set"), - governing_token_source_account: self - .governing_token_source_account - .expect("governing_token_source_account is not set"), - governing_token_owner_account: self - .governing_token_owner_account - .expect("governing_token_owner_account is not set"), - governing_token_source_account_authority: self - .governing_token_source_account_authority - .expect("governing_token_source_account_authority is not set"), - token_owner_record: self - .token_owner_record - .expect("token_owner_record is not set"), - payer: self.payer.expect("payer is not set"), - system_program: self - .system_program - .unwrap_or(solana_address::address!("11111111111111111111111111111111")), - token_program: self.token_program.unwrap_or(solana_address::address!( - "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA" - )), - realm_config_account: self - .realm_config_account - .expect("realm_config_account is not set"), + realm_account, + governing_token_holding_account, + governing_token_source_account, + governing_token_owner_account, + governing_token_source_account_authority, + token_owner_record, + payer, + system_program, + token_program, + realm_config_account, }; let args = DepositGoverningTokensInstructionArgs { - amount: self.amount.clone().expect("amount is not set"), + amount: self.amount.clone(), }; accounts.instruction_with_remaining_accounts(args, &self.__remaining_accounts) @@ -494,111 +450,36 @@ pub struct DepositGoverningTokensCpiBuilder<'a, 'b> { } impl<'a, 'b> DepositGoverningTokensCpiBuilder<'a, 'b> { - pub fn new(program: &'b solana_account_info::AccountInfo<'a>) -> Self { - let instruction = Box::new(DepositGoverningTokensCpiBuilderInstruction { - __program: program, - realm_account: None, - governing_token_holding_account: None, - governing_token_source_account: None, - governing_token_owner_account: None, - governing_token_source_account_authority: None, - token_owner_record: None, - payer: None, - system_program: None, - token_program: None, - realm_config_account: None, - amount: None, - __remaining_accounts: Vec::new(), - }); - Self { instruction } - } - #[inline(always)] - pub fn realm_account( - &mut self, + pub fn new( + __program: &'b solana_account_info::AccountInfo<'a>, realm_account: &'b solana_account_info::AccountInfo<'a>, - ) -> &mut Self { - self.instruction.realm_account = Some(realm_account); - self - } - /// seeds=['governance', realm, governing_token_mint] - #[inline(always)] - pub fn governing_token_holding_account( - &mut self, governing_token_holding_account: &'b solana_account_info::AccountInfo<'a>, - ) -> &mut Self { - self.instruction.governing_token_holding_account = Some(governing_token_holding_account); - self - } - /// It can either be spl-token TokenAccount or MintAccount. Tokens will be transferred or minted to the holding account - #[inline(always)] - pub fn governing_token_source_account( - &mut self, governing_token_source_account: &'b solana_account_info::AccountInfo<'a>, - ) -> &mut Self { - self.instruction.governing_token_source_account = Some(governing_token_source_account); - self - } - #[inline(always)] - pub fn governing_token_owner_account( - &mut self, governing_token_owner_account: &'b solana_account_info::AccountInfo<'a>, - ) -> &mut Self { - self.instruction.governing_token_owner_account = Some(governing_token_owner_account); - self - } - /// It should be owner for TokenAccount and mint_authority for MintAccount - #[inline(always)] - pub fn governing_token_source_account_authority( - &mut self, governing_token_source_account_authority: &'b solana_account_info::AccountInfo<'a>, - ) -> &mut Self { - self.instruction.governing_token_source_account_authority = - Some(governing_token_source_account_authority); - self - } - /// seeds=['governance', realm, governing_token_mint, governing_token_owner] - #[inline(always)] - pub fn token_owner_record( - &mut self, token_owner_record: &'b solana_account_info::AccountInfo<'a>, - ) -> &mut Self { - self.instruction.token_owner_record = Some(token_owner_record); - self - } - #[inline(always)] - pub fn payer(&mut self, payer: &'b solana_account_info::AccountInfo<'a>) -> &mut Self { - self.instruction.payer = Some(payer); - self - } - #[inline(always)] - pub fn system_program( - &mut self, + payer: &'b solana_account_info::AccountInfo<'a>, system_program: &'b solana_account_info::AccountInfo<'a>, - ) -> &mut Self { - self.instruction.system_program = Some(system_program); - self - } - #[inline(always)] - pub fn token_program( - &mut self, token_program: &'b solana_account_info::AccountInfo<'a>, - ) -> &mut Self { - self.instruction.token_program = Some(token_program); - self - } - /// seeds=['realm-config', realm] - #[inline(always)] - pub fn realm_config_account( - &mut self, realm_config_account: &'b solana_account_info::AccountInfo<'a>, - ) -> &mut Self { - self.instruction.realm_config_account = Some(realm_config_account); - self - } - #[inline(always)] - pub fn amount(&mut self, amount: u64) -> &mut Self { - self.instruction.amount = Some(amount); - self + amount: u64, + ) -> Self { + let instruction = Box::new(DepositGoverningTokensCpiBuilderInstruction { + __program, + realm_account, + governing_token_holding_account, + governing_token_source_account, + governing_token_owner_account, + governing_token_source_account_authority, + token_owner_record, + payer, + system_program, + token_program, + realm_config_account, + amount, + __remaining_accounts: Vec::new(), + }); + Self { instruction } } /// Add an additional account to the instruction. #[inline(always)] @@ -635,57 +516,22 @@ impl<'a, 'b> DepositGoverningTokensCpiBuilder<'a, 'b> { #[allow(clippy::vec_init_then_push)] pub fn invoke_signed(&self, signers_seeds: &[&[&[u8]]]) -> solana_program_error::ProgramResult { let args = DepositGoverningTokensInstructionArgs { - amount: self.instruction.amount.clone().expect("amount is not set"), + amount: self.instruction.amount.clone(), }; let instruction = DepositGoverningTokensCpi { __program: self.instruction.__program, - - realm_account: self - .instruction - .realm_account - .expect("realm_account is not set"), - - governing_token_holding_account: self - .instruction - .governing_token_holding_account - .expect("governing_token_holding_account is not set"), - - governing_token_source_account: self - .instruction - .governing_token_source_account - .expect("governing_token_source_account is not set"), - - governing_token_owner_account: self - .instruction - .governing_token_owner_account - .expect("governing_token_owner_account is not set"), - + realm_account: self.instruction.realm_account, + governing_token_holding_account: self.instruction.governing_token_holding_account, + governing_token_source_account: self.instruction.governing_token_source_account, + governing_token_owner_account: self.instruction.governing_token_owner_account, governing_token_source_account_authority: self .instruction - .governing_token_source_account_authority - .expect("governing_token_source_account_authority is not set"), - - token_owner_record: self - .instruction - .token_owner_record - .expect("token_owner_record is not set"), - - payer: self.instruction.payer.expect("payer is not set"), - - system_program: self - .instruction - .system_program - .expect("system_program is not set"), - - token_program: self - .instruction - .token_program - .expect("token_program is not set"), - - realm_config_account: self - .instruction - .realm_config_account - .expect("realm_config_account is not set"), + .governing_token_source_account_authority, + token_owner_record: self.instruction.token_owner_record, + payer: self.instruction.payer, + system_program: self.instruction.system_program, + token_program: self.instruction.token_program, + realm_config_account: self.instruction.realm_config_account, __args: args, }; instruction.invoke_signed_with_remaining_accounts( @@ -698,17 +544,17 @@ impl<'a, 'b> DepositGoverningTokensCpiBuilder<'a, 'b> { #[derive(Clone, Debug)] struct DepositGoverningTokensCpiBuilderInstruction<'a, 'b> { __program: &'b solana_account_info::AccountInfo<'a>, - realm_account: Option<&'b solana_account_info::AccountInfo<'a>>, - governing_token_holding_account: Option<&'b solana_account_info::AccountInfo<'a>>, - governing_token_source_account: Option<&'b solana_account_info::AccountInfo<'a>>, - governing_token_owner_account: Option<&'b solana_account_info::AccountInfo<'a>>, - governing_token_source_account_authority: Option<&'b solana_account_info::AccountInfo<'a>>, - token_owner_record: Option<&'b solana_account_info::AccountInfo<'a>>, - payer: Option<&'b solana_account_info::AccountInfo<'a>>, - system_program: Option<&'b solana_account_info::AccountInfo<'a>>, - token_program: Option<&'b solana_account_info::AccountInfo<'a>>, - realm_config_account: Option<&'b solana_account_info::AccountInfo<'a>>, - amount: Option, + realm_account: &'b solana_account_info::AccountInfo<'a>, + governing_token_holding_account: &'b solana_account_info::AccountInfo<'a>, + governing_token_source_account: &'b solana_account_info::AccountInfo<'a>, + governing_token_owner_account: &'b solana_account_info::AccountInfo<'a>, + governing_token_source_account_authority: &'b solana_account_info::AccountInfo<'a>, + token_owner_record: &'b solana_account_info::AccountInfo<'a>, + payer: &'b solana_account_info::AccountInfo<'a>, + system_program: &'b solana_account_info::AccountInfo<'a>, + token_program: &'b solana_account_info::AccountInfo<'a>, + realm_config_account: &'b solana_account_info::AccountInfo<'a>, + amount: u64, /// Additional instruction accounts `(AccountInfo, is_writable, is_signer)`. __remaining_accounts: Vec<(&'b solana_account_info::AccountInfo<'a>, bool, bool)>, } diff --git a/e2e/governance/src/generated/instructions/execute_transaction.rs b/e2e/governance/src/generated/instructions/execute_transaction.rs index 25bb355..a71279f 100644 --- a/e2e/governance/src/generated/instructions/execute_transaction.rs +++ b/e2e/governance/src/generated/instructions/execute_transaction.rs @@ -84,35 +84,26 @@ impl Default for ExecuteTransactionInstructionData { /// 0. `[]` governance_account /// 1. `[writable]` proposal_account /// 2. `[writable]` proposal_transaction_account -#[derive(Clone, Debug, Default)] +#[derive(Clone, Debug)] pub struct ExecuteTransactionBuilder { - governance_account: Option, - proposal_account: Option, - proposal_transaction_account: Option, + governance_account: solana_address::Address, + proposal_account: solana_address::Address, + proposal_transaction_account: solana_address::Address, __remaining_accounts: Vec, } impl ExecuteTransactionBuilder { - pub fn new() -> Self { - Self::default() - } - #[inline(always)] - pub fn governance_account(&mut self, governance_account: solana_address::Address) -> &mut Self { - self.governance_account = Some(governance_account); - self - } - #[inline(always)] - pub fn proposal_account(&mut self, proposal_account: solana_address::Address) -> &mut Self { - self.proposal_account = Some(proposal_account); - self - } - #[inline(always)] - pub fn proposal_transaction_account( - &mut self, + pub fn new( + governance_account: solana_address::Address, + proposal_account: solana_address::Address, proposal_transaction_account: solana_address::Address, - ) -> &mut Self { - self.proposal_transaction_account = Some(proposal_transaction_account); - self + ) -> Self { + Self { + governance_account, + proposal_account, + proposal_transaction_account, + __remaining_accounts: Vec::new(), + } } /// Add an additional account to the instruction. #[inline(always)] @@ -131,14 +122,13 @@ impl ExecuteTransactionBuilder { } #[allow(clippy::clone_on_copy)] pub fn instruction(&self) -> solana_instruction::Instruction { + let governance_account = self.governance_account; + let proposal_account = self.proposal_account; + let proposal_transaction_account = self.proposal_transaction_account; let accounts = ExecuteTransaction { - governance_account: self - .governance_account - .expect("governance_account is not set"), - proposal_account: self.proposal_account.expect("proposal_account is not set"), - proposal_transaction_account: self - .proposal_transaction_account - .expect("proposal_transaction_account is not set"), + governance_account, + proposal_account, + proposal_transaction_account, }; accounts.instruction_with_remaining_accounts(&self.__remaining_accounts) @@ -260,40 +250,21 @@ pub struct ExecuteTransactionCpiBuilder<'a, 'b> { } impl<'a, 'b> ExecuteTransactionCpiBuilder<'a, 'b> { - pub fn new(program: &'b solana_account_info::AccountInfo<'a>) -> Self { + pub fn new( + __program: &'b solana_account_info::AccountInfo<'a>, + governance_account: &'b solana_account_info::AccountInfo<'a>, + proposal_account: &'b solana_account_info::AccountInfo<'a>, + proposal_transaction_account: &'b solana_account_info::AccountInfo<'a>, + ) -> Self { let instruction = Box::new(ExecuteTransactionCpiBuilderInstruction { - __program: program, - governance_account: None, - proposal_account: None, - proposal_transaction_account: None, + __program, + governance_account, + proposal_account, + proposal_transaction_account, __remaining_accounts: Vec::new(), }); Self { instruction } } - #[inline(always)] - pub fn governance_account( - &mut self, - governance_account: &'b solana_account_info::AccountInfo<'a>, - ) -> &mut Self { - self.instruction.governance_account = Some(governance_account); - self - } - #[inline(always)] - pub fn proposal_account( - &mut self, - proposal_account: &'b solana_account_info::AccountInfo<'a>, - ) -> &mut Self { - self.instruction.proposal_account = Some(proposal_account); - self - } - #[inline(always)] - pub fn proposal_transaction_account( - &mut self, - proposal_transaction_account: &'b solana_account_info::AccountInfo<'a>, - ) -> &mut Self { - self.instruction.proposal_transaction_account = Some(proposal_transaction_account); - self - } /// Add an additional account to the instruction. #[inline(always)] pub fn add_remaining_account( @@ -330,21 +301,9 @@ impl<'a, 'b> ExecuteTransactionCpiBuilder<'a, 'b> { pub fn invoke_signed(&self, signers_seeds: &[&[&[u8]]]) -> solana_program_error::ProgramResult { let instruction = ExecuteTransactionCpi { __program: self.instruction.__program, - - governance_account: self - .instruction - .governance_account - .expect("governance_account is not set"), - - proposal_account: self - .instruction - .proposal_account - .expect("proposal_account is not set"), - - proposal_transaction_account: self - .instruction - .proposal_transaction_account - .expect("proposal_transaction_account is not set"), + governance_account: self.instruction.governance_account, + proposal_account: self.instruction.proposal_account, + proposal_transaction_account: self.instruction.proposal_transaction_account, }; instruction.invoke_signed_with_remaining_accounts( signers_seeds, @@ -356,9 +315,9 @@ impl<'a, 'b> ExecuteTransactionCpiBuilder<'a, 'b> { #[derive(Clone, Debug)] struct ExecuteTransactionCpiBuilderInstruction<'a, 'b> { __program: &'b solana_account_info::AccountInfo<'a>, - governance_account: Option<&'b solana_account_info::AccountInfo<'a>>, - proposal_account: Option<&'b solana_account_info::AccountInfo<'a>>, - proposal_transaction_account: Option<&'b solana_account_info::AccountInfo<'a>>, + governance_account: &'b solana_account_info::AccountInfo<'a>, + proposal_account: &'b solana_account_info::AccountInfo<'a>, + proposal_transaction_account: &'b solana_account_info::AccountInfo<'a>, /// Additional instruction accounts `(AccountInfo, is_writable, is_signer)`. __remaining_accounts: Vec<(&'b solana_account_info::AccountInfo<'a>, bool, bool)>, } diff --git a/e2e/governance/src/generated/instructions/finalize_vote.rs b/e2e/governance/src/generated/instructions/finalize_vote.rs index 2615d9e..fd7a1e5 100644 --- a/e2e/governance/src/generated/instructions/finalize_vote.rs +++ b/e2e/governance/src/generated/instructions/finalize_vote.rs @@ -117,56 +117,37 @@ impl Default for FinalizeVoteInstructionData { /// 4. `[]` governing_token_mint /// 5. `[]` realm_config /// 6. `[optional]` max_voter_weight_record -#[derive(Clone, Debug, Default)] +#[derive(Clone, Debug)] pub struct FinalizeVoteBuilder { - realm_account: Option, - governance_account: Option, - proposal_account: Option, - token_owner_record: Option, - governing_token_mint: Option, - realm_config: Option, + realm_account: solana_address::Address, + governance_account: solana_address::Address, + proposal_account: solana_address::Address, + token_owner_record: solana_address::Address, + governing_token_mint: solana_address::Address, + realm_config: solana_address::Address, max_voter_weight_record: Option, __remaining_accounts: Vec, } impl FinalizeVoteBuilder { - pub fn new() -> Self { - Self::default() - } - #[inline(always)] - pub fn realm_account(&mut self, realm_account: solana_address::Address) -> &mut Self { - self.realm_account = Some(realm_account); - self - } - #[inline(always)] - pub fn governance_account(&mut self, governance_account: solana_address::Address) -> &mut Self { - self.governance_account = Some(governance_account); - self - } - #[inline(always)] - pub fn proposal_account(&mut self, proposal_account: solana_address::Address) -> &mut Self { - self.proposal_account = Some(proposal_account); - self - } - /// TokenOwnerRecord of the Proposal owner - #[inline(always)] - pub fn token_owner_record(&mut self, token_owner_record: solana_address::Address) -> &mut Self { - self.token_owner_record = Some(token_owner_record); - self - } - #[inline(always)] - pub fn governing_token_mint( - &mut self, + pub fn new( + realm_account: solana_address::Address, + governance_account: solana_address::Address, + proposal_account: solana_address::Address, + token_owner_record: solana_address::Address, governing_token_mint: solana_address::Address, - ) -> &mut Self { - self.governing_token_mint = Some(governing_token_mint); - self - } - /// RealmConfig account. PDA seeds: ['realm-config', realm] - #[inline(always)] - pub fn realm_config(&mut self, realm_config: solana_address::Address) -> &mut Self { - self.realm_config = Some(realm_config); - self + realm_config: solana_address::Address, + ) -> Self { + Self { + realm_account, + governance_account, + proposal_account, + token_owner_record, + governing_token_mint, + realm_config, + max_voter_weight_record: None, + __remaining_accounts: Vec::new(), + } } /// `[optional account]` /// Optional Max Voter Weight Record @@ -195,20 +176,21 @@ impl FinalizeVoteBuilder { } #[allow(clippy::clone_on_copy)] pub fn instruction(&self) -> solana_instruction::Instruction { + let realm_account = self.realm_account; + let governance_account = self.governance_account; + let proposal_account = self.proposal_account; + let token_owner_record = self.token_owner_record; + let governing_token_mint = self.governing_token_mint; + let realm_config = self.realm_config; + let max_voter_weight_record = self.max_voter_weight_record; let accounts = FinalizeVote { - realm_account: self.realm_account.expect("realm_account is not set"), - governance_account: self - .governance_account - .expect("governance_account is not set"), - proposal_account: self.proposal_account.expect("proposal_account is not set"), - token_owner_record: self - .token_owner_record - .expect("token_owner_record is not set"), - governing_token_mint: self - .governing_token_mint - .expect("governing_token_mint is not set"), - realm_config: self.realm_config.expect("realm_config is not set"), - max_voter_weight_record: self.max_voter_weight_record, + realm_account, + governance_account, + proposal_account, + token_owner_record, + governing_token_mint, + realm_config, + max_voter_weight_record, }; accounts.instruction_with_remaining_accounts(&self.__remaining_accounts) @@ -381,69 +363,27 @@ pub struct FinalizeVoteCpiBuilder<'a, 'b> { } impl<'a, 'b> FinalizeVoteCpiBuilder<'a, 'b> { - pub fn new(program: &'b solana_account_info::AccountInfo<'a>) -> Self { - let instruction = Box::new(FinalizeVoteCpiBuilderInstruction { - __program: program, - realm_account: None, - governance_account: None, - proposal_account: None, - token_owner_record: None, - governing_token_mint: None, - realm_config: None, - max_voter_weight_record: None, - __remaining_accounts: Vec::new(), - }); - Self { instruction } - } - #[inline(always)] - pub fn realm_account( - &mut self, + pub fn new( + __program: &'b solana_account_info::AccountInfo<'a>, realm_account: &'b solana_account_info::AccountInfo<'a>, - ) -> &mut Self { - self.instruction.realm_account = Some(realm_account); - self - } - #[inline(always)] - pub fn governance_account( - &mut self, governance_account: &'b solana_account_info::AccountInfo<'a>, - ) -> &mut Self { - self.instruction.governance_account = Some(governance_account); - self - } - #[inline(always)] - pub fn proposal_account( - &mut self, proposal_account: &'b solana_account_info::AccountInfo<'a>, - ) -> &mut Self { - self.instruction.proposal_account = Some(proposal_account); - self - } - /// TokenOwnerRecord of the Proposal owner - #[inline(always)] - pub fn token_owner_record( - &mut self, token_owner_record: &'b solana_account_info::AccountInfo<'a>, - ) -> &mut Self { - self.instruction.token_owner_record = Some(token_owner_record); - self - } - #[inline(always)] - pub fn governing_token_mint( - &mut self, governing_token_mint: &'b solana_account_info::AccountInfo<'a>, - ) -> &mut Self { - self.instruction.governing_token_mint = Some(governing_token_mint); - self - } - /// RealmConfig account. PDA seeds: ['realm-config', realm] - #[inline(always)] - pub fn realm_config( - &mut self, realm_config: &'b solana_account_info::AccountInfo<'a>, - ) -> &mut Self { - self.instruction.realm_config = Some(realm_config); - self + ) -> Self { + let instruction = Box::new(FinalizeVoteCpiBuilderInstruction { + __program, + realm_account, + governance_account, + proposal_account, + token_owner_record, + governing_token_mint, + realm_config, + max_voter_weight_record: None, + __remaining_accounts: Vec::new(), + }); + Self { instruction } } /// `[optional account]` /// Optional Max Voter Weight Record @@ -491,37 +431,12 @@ impl<'a, 'b> FinalizeVoteCpiBuilder<'a, 'b> { pub fn invoke_signed(&self, signers_seeds: &[&[&[u8]]]) -> solana_program_error::ProgramResult { let instruction = FinalizeVoteCpi { __program: self.instruction.__program, - - realm_account: self - .instruction - .realm_account - .expect("realm_account is not set"), - - governance_account: self - .instruction - .governance_account - .expect("governance_account is not set"), - - proposal_account: self - .instruction - .proposal_account - .expect("proposal_account is not set"), - - token_owner_record: self - .instruction - .token_owner_record - .expect("token_owner_record is not set"), - - governing_token_mint: self - .instruction - .governing_token_mint - .expect("governing_token_mint is not set"), - - realm_config: self - .instruction - .realm_config - .expect("realm_config is not set"), - + realm_account: self.instruction.realm_account, + governance_account: self.instruction.governance_account, + proposal_account: self.instruction.proposal_account, + token_owner_record: self.instruction.token_owner_record, + governing_token_mint: self.instruction.governing_token_mint, + realm_config: self.instruction.realm_config, max_voter_weight_record: self.instruction.max_voter_weight_record, }; instruction.invoke_signed_with_remaining_accounts( @@ -534,12 +449,12 @@ impl<'a, 'b> FinalizeVoteCpiBuilder<'a, 'b> { #[derive(Clone, Debug)] struct FinalizeVoteCpiBuilderInstruction<'a, 'b> { __program: &'b solana_account_info::AccountInfo<'a>, - realm_account: Option<&'b solana_account_info::AccountInfo<'a>>, - governance_account: Option<&'b solana_account_info::AccountInfo<'a>>, - proposal_account: Option<&'b solana_account_info::AccountInfo<'a>>, - token_owner_record: Option<&'b solana_account_info::AccountInfo<'a>>, - governing_token_mint: Option<&'b solana_account_info::AccountInfo<'a>>, - realm_config: Option<&'b solana_account_info::AccountInfo<'a>>, + realm_account: &'b solana_account_info::AccountInfo<'a>, + governance_account: &'b solana_account_info::AccountInfo<'a>, + proposal_account: &'b solana_account_info::AccountInfo<'a>, + token_owner_record: &'b solana_account_info::AccountInfo<'a>, + governing_token_mint: &'b solana_account_info::AccountInfo<'a>, + realm_config: &'b solana_account_info::AccountInfo<'a>, max_voter_weight_record: Option<&'b solana_account_info::AccountInfo<'a>>, /// Additional instruction accounts `(AccountInfo, is_writable, is_signer)`. __remaining_accounts: Vec<(&'b solana_account_info::AccountInfo<'a>, bool, bool)>, diff --git a/e2e/governance/src/generated/instructions/flag_transaction_error.rs b/e2e/governance/src/generated/instructions/flag_transaction_error.rs index 0216457..3289f49 100644 --- a/e2e/governance/src/generated/instructions/flag_transaction_error.rs +++ b/e2e/governance/src/generated/instructions/flag_transaction_error.rs @@ -91,47 +91,29 @@ impl Default for FlagTransactionErrorInstructionData { /// 1. `[]` token_owner_record /// 2. `[signer]` governance_authority /// 3. `[writable]` proposal_transaction_account -#[derive(Clone, Debug, Default)] +#[derive(Clone, Debug)] pub struct FlagTransactionErrorBuilder { - proposal_account: Option, - token_owner_record: Option, - governance_authority: Option, - proposal_transaction_account: Option, + proposal_account: solana_address::Address, + token_owner_record: solana_address::Address, + governance_authority: solana_address::Address, + proposal_transaction_account: solana_address::Address, __remaining_accounts: Vec, } impl FlagTransactionErrorBuilder { - pub fn new() -> Self { - Self::default() - } - #[inline(always)] - pub fn proposal_account(&mut self, proposal_account: solana_address::Address) -> &mut Self { - self.proposal_account = Some(proposal_account); - self - } - /// TokenOwnerRecord account of the Proposal owner - #[inline(always)] - pub fn token_owner_record(&mut self, token_owner_record: solana_address::Address) -> &mut Self { - self.token_owner_record = Some(token_owner_record); - self - } - /// Governance Authority (Token Owner or Governance Delegate) - #[inline(always)] - pub fn governance_authority( - &mut self, + pub fn new( + proposal_account: solana_address::Address, + token_owner_record: solana_address::Address, governance_authority: solana_address::Address, - ) -> &mut Self { - self.governance_authority = Some(governance_authority); - self - } - /// ProposalTransaction account to flag - #[inline(always)] - pub fn proposal_transaction_account( - &mut self, proposal_transaction_account: solana_address::Address, - ) -> &mut Self { - self.proposal_transaction_account = Some(proposal_transaction_account); - self + ) -> Self { + Self { + proposal_account, + token_owner_record, + governance_authority, + proposal_transaction_account, + __remaining_accounts: Vec::new(), + } } /// Add an additional account to the instruction. #[inline(always)] @@ -150,17 +132,15 @@ impl FlagTransactionErrorBuilder { } #[allow(clippy::clone_on_copy)] pub fn instruction(&self) -> solana_instruction::Instruction { + let proposal_account = self.proposal_account; + let token_owner_record = self.token_owner_record; + let governance_authority = self.governance_authority; + let proposal_transaction_account = self.proposal_transaction_account; let accounts = FlagTransactionError { - proposal_account: self.proposal_account.expect("proposal_account is not set"), - token_owner_record: self - .token_owner_record - .expect("token_owner_record is not set"), - governance_authority: self - .governance_authority - .expect("governance_authority is not set"), - proposal_transaction_account: self - .proposal_transaction_account - .expect("proposal_transaction_account is not set"), + proposal_account, + token_owner_record, + governance_authority, + proposal_transaction_account, }; accounts.instruction_with_remaining_accounts(&self.__remaining_accounts) @@ -293,51 +273,22 @@ pub struct FlagTransactionErrorCpiBuilder<'a, 'b> { } impl<'a, 'b> FlagTransactionErrorCpiBuilder<'a, 'b> { - pub fn new(program: &'b solana_account_info::AccountInfo<'a>) -> Self { - let instruction = Box::new(FlagTransactionErrorCpiBuilderInstruction { - __program: program, - proposal_account: None, - token_owner_record: None, - governance_authority: None, - proposal_transaction_account: None, - __remaining_accounts: Vec::new(), - }); - Self { instruction } - } - #[inline(always)] - pub fn proposal_account( - &mut self, + pub fn new( + __program: &'b solana_account_info::AccountInfo<'a>, proposal_account: &'b solana_account_info::AccountInfo<'a>, - ) -> &mut Self { - self.instruction.proposal_account = Some(proposal_account); - self - } - /// TokenOwnerRecord account of the Proposal owner - #[inline(always)] - pub fn token_owner_record( - &mut self, token_owner_record: &'b solana_account_info::AccountInfo<'a>, - ) -> &mut Self { - self.instruction.token_owner_record = Some(token_owner_record); - self - } - /// Governance Authority (Token Owner or Governance Delegate) - #[inline(always)] - pub fn governance_authority( - &mut self, governance_authority: &'b solana_account_info::AccountInfo<'a>, - ) -> &mut Self { - self.instruction.governance_authority = Some(governance_authority); - self - } - /// ProposalTransaction account to flag - #[inline(always)] - pub fn proposal_transaction_account( - &mut self, proposal_transaction_account: &'b solana_account_info::AccountInfo<'a>, - ) -> &mut Self { - self.instruction.proposal_transaction_account = Some(proposal_transaction_account); - self + ) -> Self { + let instruction = Box::new(FlagTransactionErrorCpiBuilderInstruction { + __program, + proposal_account, + token_owner_record, + governance_authority, + proposal_transaction_account, + __remaining_accounts: Vec::new(), + }); + Self { instruction } } /// Add an additional account to the instruction. #[inline(always)] @@ -375,26 +326,10 @@ impl<'a, 'b> FlagTransactionErrorCpiBuilder<'a, 'b> { pub fn invoke_signed(&self, signers_seeds: &[&[&[u8]]]) -> solana_program_error::ProgramResult { let instruction = FlagTransactionErrorCpi { __program: self.instruction.__program, - - proposal_account: self - .instruction - .proposal_account - .expect("proposal_account is not set"), - - token_owner_record: self - .instruction - .token_owner_record - .expect("token_owner_record is not set"), - - governance_authority: self - .instruction - .governance_authority - .expect("governance_authority is not set"), - - proposal_transaction_account: self - .instruction - .proposal_transaction_account - .expect("proposal_transaction_account is not set"), + proposal_account: self.instruction.proposal_account, + token_owner_record: self.instruction.token_owner_record, + governance_authority: self.instruction.governance_authority, + proposal_transaction_account: self.instruction.proposal_transaction_account, }; instruction.invoke_signed_with_remaining_accounts( signers_seeds, @@ -406,10 +341,10 @@ impl<'a, 'b> FlagTransactionErrorCpiBuilder<'a, 'b> { #[derive(Clone, Debug)] struct FlagTransactionErrorCpiBuilderInstruction<'a, 'b> { __program: &'b solana_account_info::AccountInfo<'a>, - proposal_account: Option<&'b solana_account_info::AccountInfo<'a>>, - token_owner_record: Option<&'b solana_account_info::AccountInfo<'a>>, - governance_authority: Option<&'b solana_account_info::AccountInfo<'a>>, - proposal_transaction_account: Option<&'b solana_account_info::AccountInfo<'a>>, + proposal_account: &'b solana_account_info::AccountInfo<'a>, + token_owner_record: &'b solana_account_info::AccountInfo<'a>, + governance_authority: &'b solana_account_info::AccountInfo<'a>, + proposal_transaction_account: &'b solana_account_info::AccountInfo<'a>, /// Additional instruction accounts `(AccountInfo, is_writable, is_signer)`. __remaining_accounts: Vec<(&'b solana_account_info::AccountInfo<'a>, bool, bool)>, } diff --git a/e2e/governance/src/generated/instructions/insert_transaction.rs b/e2e/governance/src/generated/instructions/insert_transaction.rs index 574fa62..6a6c777 100644 --- a/e2e/governance/src/generated/instructions/insert_transaction.rs +++ b/e2e/governance/src/generated/instructions/insert_transaction.rs @@ -138,65 +138,51 @@ impl InsertTransactionInstructionArgs { /// 5. `[signer]` payer /// 6. `[optional]` system_program (default to `11111111111111111111111111111111`) /// 7. `[optional]` rent (default to `SysvarRent111111111111111111111111111111111`) -#[derive(Clone, Debug, Default)] +#[derive(Clone, Debug)] pub struct InsertTransactionBuilder { - governance_account: Option, - proposal_account: Option, - token_owner_record: Option, - governance_authority: Option, - proposal_transaction_account: Option, - payer: Option, + governance_account: solana_address::Address, + proposal_account: solana_address::Address, + token_owner_record: solana_address::Address, + governance_authority: solana_address::Address, + proposal_transaction_account: solana_address::Address, + payer: solana_address::Address, system_program: Option, rent: Option, - option_index: Option, - index: Option, - hold_up_time: Option, - instructions: Option>, + option_index: u8, + index: u16, + hold_up_time: u32, + instructions: Vec, __remaining_accounts: Vec, } impl InsertTransactionBuilder { - pub fn new() -> Self { - Self::default() - } - #[inline(always)] - pub fn governance_account(&mut self, governance_account: solana_address::Address) -> &mut Self { - self.governance_account = Some(governance_account); - self - } - #[inline(always)] - pub fn proposal_account(&mut self, proposal_account: solana_address::Address) -> &mut Self { - self.proposal_account = Some(proposal_account); - self - } - /// TokenOwnerRecord account of the Proposal owner - #[inline(always)] - pub fn token_owner_record(&mut self, token_owner_record: solana_address::Address) -> &mut Self { - self.token_owner_record = Some(token_owner_record); - self - } - /// Governance Authority (Token Owner or Governance Delegate) - #[inline(always)] - pub fn governance_authority( - &mut self, + pub fn new( + governance_account: solana_address::Address, + proposal_account: solana_address::Address, + token_owner_record: solana_address::Address, governance_authority: solana_address::Address, - ) -> &mut Self { - self.governance_authority = Some(governance_authority); - self - } - /// ProposalTransaction, account. PDA seeds: ['governance', proposal, option_index, index] - #[inline(always)] - pub fn proposal_transaction_account( - &mut self, proposal_transaction_account: solana_address::Address, - ) -> &mut Self { - self.proposal_transaction_account = Some(proposal_transaction_account); - self - } - #[inline(always)] - pub fn payer(&mut self, payer: solana_address::Address) -> &mut Self { - self.payer = Some(payer); - self + payer: solana_address::Address, + option_index: u8, + index: u16, + hold_up_time: u32, + instructions: Vec, + ) -> Self { + Self { + governance_account, + proposal_account, + token_owner_record, + governance_authority, + proposal_transaction_account, + payer, + system_program: None, + rent: None, + option_index, + index, + hold_up_time, + instructions, + __remaining_accounts: Vec::new(), + } } /// `[optional account, default to '11111111111111111111111111111111']` #[inline(always)] @@ -210,26 +196,6 @@ impl InsertTransactionBuilder { self.rent = Some(rent); self } - #[inline(always)] - pub fn option_index(&mut self, option_index: u8) -> &mut Self { - self.option_index = Some(option_index); - self - } - #[inline(always)] - pub fn index(&mut self, index: u16) -> &mut Self { - self.index = Some(index); - self - } - #[inline(always)] - pub fn hold_up_time(&mut self, hold_up_time: u32) -> &mut Self { - self.hold_up_time = Some(hold_up_time); - self - } - #[inline(always)] - pub fn instructions(&mut self, instructions: Vec) -> &mut Self { - self.instructions = Some(instructions); - self - } /// Add an additional account to the instruction. #[inline(always)] pub fn add_remaining_account(&mut self, account: solana_instruction::AccountMeta) -> &mut Self { @@ -247,33 +213,33 @@ impl InsertTransactionBuilder { } #[allow(clippy::clone_on_copy)] pub fn instruction(&self) -> solana_instruction::Instruction { + let governance_account = self.governance_account; + let proposal_account = self.proposal_account; + let token_owner_record = self.token_owner_record; + let governance_authority = self.governance_authority; + let proposal_transaction_account = self.proposal_transaction_account; + let payer = self.payer; + let system_program = self + .system_program + .unwrap_or(solana_address::address!("11111111111111111111111111111111")); + let rent = self.rent.unwrap_or(solana_address::address!( + "SysvarRent111111111111111111111111111111111" + )); let accounts = InsertTransaction { - governance_account: self - .governance_account - .expect("governance_account is not set"), - proposal_account: self.proposal_account.expect("proposal_account is not set"), - token_owner_record: self - .token_owner_record - .expect("token_owner_record is not set"), - governance_authority: self - .governance_authority - .expect("governance_authority is not set"), - proposal_transaction_account: self - .proposal_transaction_account - .expect("proposal_transaction_account is not set"), - payer: self.payer.expect("payer is not set"), - system_program: self - .system_program - .unwrap_or(solana_address::address!("11111111111111111111111111111111")), - rent: self.rent.unwrap_or(solana_address::address!( - "SysvarRent111111111111111111111111111111111" - )), + governance_account, + proposal_account, + token_owner_record, + governance_authority, + proposal_transaction_account, + payer, + system_program, + rent, }; let args = InsertTransactionInstructionArgs { - option_index: self.option_index.clone().expect("option_index is not set"), - index: self.index.clone().expect("index is not set"), - hold_up_time: self.hold_up_time.clone().expect("hold_up_time is not set"), - instructions: self.instructions.clone().expect("instructions is not set"), + option_index: self.option_index.clone(), + index: self.index.clone(), + hold_up_time: self.hold_up_time.clone(), + instructions: self.instructions.clone(), }; accounts.instruction_with_remaining_accounts(args, &self.__remaining_accounts) @@ -456,105 +422,38 @@ pub struct InsertTransactionCpiBuilder<'a, 'b> { } impl<'a, 'b> InsertTransactionCpiBuilder<'a, 'b> { - pub fn new(program: &'b solana_account_info::AccountInfo<'a>) -> Self { - let instruction = Box::new(InsertTransactionCpiBuilderInstruction { - __program: program, - governance_account: None, - proposal_account: None, - token_owner_record: None, - governance_authority: None, - proposal_transaction_account: None, - payer: None, - system_program: None, - rent: None, - option_index: None, - index: None, - hold_up_time: None, - instructions: None, - __remaining_accounts: Vec::new(), - }); - Self { instruction } - } - #[inline(always)] - pub fn governance_account( - &mut self, + pub fn new( + __program: &'b solana_account_info::AccountInfo<'a>, governance_account: &'b solana_account_info::AccountInfo<'a>, - ) -> &mut Self { - self.instruction.governance_account = Some(governance_account); - self - } - #[inline(always)] - pub fn proposal_account( - &mut self, proposal_account: &'b solana_account_info::AccountInfo<'a>, - ) -> &mut Self { - self.instruction.proposal_account = Some(proposal_account); - self - } - /// TokenOwnerRecord account of the Proposal owner - #[inline(always)] - pub fn token_owner_record( - &mut self, token_owner_record: &'b solana_account_info::AccountInfo<'a>, - ) -> &mut Self { - self.instruction.token_owner_record = Some(token_owner_record); - self - } - /// Governance Authority (Token Owner or Governance Delegate) - #[inline(always)] - pub fn governance_authority( - &mut self, governance_authority: &'b solana_account_info::AccountInfo<'a>, - ) -> &mut Self { - self.instruction.governance_authority = Some(governance_authority); - self - } - /// ProposalTransaction, account. PDA seeds: ['governance', proposal, option_index, index] - #[inline(always)] - pub fn proposal_transaction_account( - &mut self, proposal_transaction_account: &'b solana_account_info::AccountInfo<'a>, - ) -> &mut Self { - self.instruction.proposal_transaction_account = Some(proposal_transaction_account); - self - } - #[inline(always)] - pub fn payer(&mut self, payer: &'b solana_account_info::AccountInfo<'a>) -> &mut Self { - self.instruction.payer = Some(payer); - self - } - #[inline(always)] - pub fn system_program( - &mut self, + payer: &'b solana_account_info::AccountInfo<'a>, system_program: &'b solana_account_info::AccountInfo<'a>, - ) -> &mut Self { - self.instruction.system_program = Some(system_program); - self - } - #[inline(always)] - pub fn rent(&mut self, rent: &'b solana_account_info::AccountInfo<'a>) -> &mut Self { - self.instruction.rent = Some(rent); - self - } - #[inline(always)] - pub fn option_index(&mut self, option_index: u8) -> &mut Self { - self.instruction.option_index = Some(option_index); - self - } - #[inline(always)] - pub fn index(&mut self, index: u16) -> &mut Self { - self.instruction.index = Some(index); - self - } - #[inline(always)] - pub fn hold_up_time(&mut self, hold_up_time: u32) -> &mut Self { - self.instruction.hold_up_time = Some(hold_up_time); - self - } - #[inline(always)] - pub fn instructions(&mut self, instructions: Vec) -> &mut Self { - self.instruction.instructions = Some(instructions); - self + rent: &'b solana_account_info::AccountInfo<'a>, + option_index: u8, + index: u16, + hold_up_time: u32, + instructions: Vec, + ) -> Self { + let instruction = Box::new(InsertTransactionCpiBuilderInstruction { + __program, + governance_account, + proposal_account, + token_owner_record, + governance_authority, + proposal_transaction_account, + payer, + system_program, + rent, + option_index, + index, + hold_up_time, + instructions, + __remaining_accounts: Vec::new(), + }); + Self { instruction } } /// Add an additional account to the instruction. #[inline(always)] @@ -591,59 +490,21 @@ impl<'a, 'b> InsertTransactionCpiBuilder<'a, 'b> { #[allow(clippy::vec_init_then_push)] pub fn invoke_signed(&self, signers_seeds: &[&[&[u8]]]) -> solana_program_error::ProgramResult { let args = InsertTransactionInstructionArgs { - option_index: self - .instruction - .option_index - .clone() - .expect("option_index is not set"), - index: self.instruction.index.clone().expect("index is not set"), - hold_up_time: self - .instruction - .hold_up_time - .clone() - .expect("hold_up_time is not set"), - instructions: self - .instruction - .instructions - .clone() - .expect("instructions is not set"), + option_index: self.instruction.option_index.clone(), + index: self.instruction.index.clone(), + hold_up_time: self.instruction.hold_up_time.clone(), + instructions: self.instruction.instructions.clone(), }; let instruction = InsertTransactionCpi { __program: self.instruction.__program, - - governance_account: self - .instruction - .governance_account - .expect("governance_account is not set"), - - proposal_account: self - .instruction - .proposal_account - .expect("proposal_account is not set"), - - token_owner_record: self - .instruction - .token_owner_record - .expect("token_owner_record is not set"), - - governance_authority: self - .instruction - .governance_authority - .expect("governance_authority is not set"), - - proposal_transaction_account: self - .instruction - .proposal_transaction_account - .expect("proposal_transaction_account is not set"), - - payer: self.instruction.payer.expect("payer is not set"), - - system_program: self - .instruction - .system_program - .expect("system_program is not set"), - - rent: self.instruction.rent.expect("rent is not set"), + governance_account: self.instruction.governance_account, + proposal_account: self.instruction.proposal_account, + token_owner_record: self.instruction.token_owner_record, + governance_authority: self.instruction.governance_authority, + proposal_transaction_account: self.instruction.proposal_transaction_account, + payer: self.instruction.payer, + system_program: self.instruction.system_program, + rent: self.instruction.rent, __args: args, }; instruction.invoke_signed_with_remaining_accounts( @@ -656,18 +517,18 @@ impl<'a, 'b> InsertTransactionCpiBuilder<'a, 'b> { #[derive(Clone, Debug)] struct InsertTransactionCpiBuilderInstruction<'a, 'b> { __program: &'b solana_account_info::AccountInfo<'a>, - governance_account: Option<&'b solana_account_info::AccountInfo<'a>>, - proposal_account: Option<&'b solana_account_info::AccountInfo<'a>>, - token_owner_record: Option<&'b solana_account_info::AccountInfo<'a>>, - governance_authority: Option<&'b solana_account_info::AccountInfo<'a>>, - proposal_transaction_account: Option<&'b solana_account_info::AccountInfo<'a>>, - payer: Option<&'b solana_account_info::AccountInfo<'a>>, - system_program: Option<&'b solana_account_info::AccountInfo<'a>>, - rent: Option<&'b solana_account_info::AccountInfo<'a>>, - option_index: Option, - index: Option, - hold_up_time: Option, - instructions: Option>, + governance_account: &'b solana_account_info::AccountInfo<'a>, + proposal_account: &'b solana_account_info::AccountInfo<'a>, + token_owner_record: &'b solana_account_info::AccountInfo<'a>, + governance_authority: &'b solana_account_info::AccountInfo<'a>, + proposal_transaction_account: &'b solana_account_info::AccountInfo<'a>, + payer: &'b solana_account_info::AccountInfo<'a>, + system_program: &'b solana_account_info::AccountInfo<'a>, + rent: &'b solana_account_info::AccountInfo<'a>, + option_index: u8, + index: u16, + hold_up_time: u32, + instructions: Vec, /// Additional instruction accounts `(AccountInfo, is_writable, is_signer)`. __remaining_accounts: Vec<(&'b solana_account_info::AccountInfo<'a>, bool, bool)>, } diff --git a/e2e/governance/src/generated/instructions/legacy1.rs b/e2e/governance/src/generated/instructions/legacy1.rs index db81623..df1e65f 100644 --- a/e2e/governance/src/generated/instructions/legacy1.rs +++ b/e2e/governance/src/generated/instructions/legacy1.rs @@ -165,9 +165,9 @@ pub struct Legacy1CpiBuilder<'a, 'b> { } impl<'a, 'b> Legacy1CpiBuilder<'a, 'b> { - pub fn new(program: &'b solana_account_info::AccountInfo<'a>) -> Self { + pub fn new(__program: &'b solana_account_info::AccountInfo<'a>) -> Self { let instruction = Box::new(Legacy1CpiBuilderInstruction { - __program: program, + __program, __remaining_accounts: Vec::new(), }); Self { instruction } diff --git a/e2e/governance/src/generated/instructions/refund_proposal_deposit.rs b/e2e/governance/src/generated/instructions/refund_proposal_deposit.rs index 3300dfe..cfc7b47 100644 --- a/e2e/governance/src/generated/instructions/refund_proposal_deposit.rs +++ b/e2e/governance/src/generated/instructions/refund_proposal_deposit.rs @@ -84,40 +84,26 @@ impl Default for RefundProposalDepositInstructionData { /// 0. `[]` proposal_account /// 1. `[writable]` proposal_deposit_account /// 2. `[writable]` proposal_deposit_payer -#[derive(Clone, Debug, Default)] +#[derive(Clone, Debug)] pub struct RefundProposalDepositBuilder { - proposal_account: Option, - proposal_deposit_account: Option, - proposal_deposit_payer: Option, + proposal_account: solana_address::Address, + proposal_deposit_account: solana_address::Address, + proposal_deposit_payer: solana_address::Address, __remaining_accounts: Vec, } impl RefundProposalDepositBuilder { - pub fn new() -> Self { - Self::default() - } - #[inline(always)] - pub fn proposal_account(&mut self, proposal_account: solana_address::Address) -> &mut Self { - self.proposal_account = Some(proposal_account); - self - } - /// PDA Seeds: ['proposal-deposit', proposal, deposit payer] - #[inline(always)] - pub fn proposal_deposit_account( - &mut self, + pub fn new( + proposal_account: solana_address::Address, proposal_deposit_account: solana_address::Address, - ) -> &mut Self { - self.proposal_deposit_account = Some(proposal_deposit_account); - self - } - /// Proposal Deposit Payer (beneficiary) account - #[inline(always)] - pub fn proposal_deposit_payer( - &mut self, proposal_deposit_payer: solana_address::Address, - ) -> &mut Self { - self.proposal_deposit_payer = Some(proposal_deposit_payer); - self + ) -> Self { + Self { + proposal_account, + proposal_deposit_account, + proposal_deposit_payer, + __remaining_accounts: Vec::new(), + } } /// Add an additional account to the instruction. #[inline(always)] @@ -136,14 +122,13 @@ impl RefundProposalDepositBuilder { } #[allow(clippy::clone_on_copy)] pub fn instruction(&self) -> solana_instruction::Instruction { + let proposal_account = self.proposal_account; + let proposal_deposit_account = self.proposal_deposit_account; + let proposal_deposit_payer = self.proposal_deposit_payer; let accounts = RefundProposalDeposit { - proposal_account: self.proposal_account.expect("proposal_account is not set"), - proposal_deposit_account: self - .proposal_deposit_account - .expect("proposal_deposit_account is not set"), - proposal_deposit_payer: self - .proposal_deposit_payer - .expect("proposal_deposit_payer is not set"), + proposal_account, + proposal_deposit_account, + proposal_deposit_payer, }; accounts.instruction_with_remaining_accounts(&self.__remaining_accounts) @@ -265,42 +250,21 @@ pub struct RefundProposalDepositCpiBuilder<'a, 'b> { } impl<'a, 'b> RefundProposalDepositCpiBuilder<'a, 'b> { - pub fn new(program: &'b solana_account_info::AccountInfo<'a>) -> Self { + pub fn new( + __program: &'b solana_account_info::AccountInfo<'a>, + proposal_account: &'b solana_account_info::AccountInfo<'a>, + proposal_deposit_account: &'b solana_account_info::AccountInfo<'a>, + proposal_deposit_payer: &'b solana_account_info::AccountInfo<'a>, + ) -> Self { let instruction = Box::new(RefundProposalDepositCpiBuilderInstruction { - __program: program, - proposal_account: None, - proposal_deposit_account: None, - proposal_deposit_payer: None, + __program, + proposal_account, + proposal_deposit_account, + proposal_deposit_payer, __remaining_accounts: Vec::new(), }); Self { instruction } } - #[inline(always)] - pub fn proposal_account( - &mut self, - proposal_account: &'b solana_account_info::AccountInfo<'a>, - ) -> &mut Self { - self.instruction.proposal_account = Some(proposal_account); - self - } - /// PDA Seeds: ['proposal-deposit', proposal, deposit payer] - #[inline(always)] - pub fn proposal_deposit_account( - &mut self, - proposal_deposit_account: &'b solana_account_info::AccountInfo<'a>, - ) -> &mut Self { - self.instruction.proposal_deposit_account = Some(proposal_deposit_account); - self - } - /// Proposal Deposit Payer (beneficiary) account - #[inline(always)] - pub fn proposal_deposit_payer( - &mut self, - proposal_deposit_payer: &'b solana_account_info::AccountInfo<'a>, - ) -> &mut Self { - self.instruction.proposal_deposit_payer = Some(proposal_deposit_payer); - self - } /// Add an additional account to the instruction. #[inline(always)] pub fn add_remaining_account( @@ -337,21 +301,9 @@ impl<'a, 'b> RefundProposalDepositCpiBuilder<'a, 'b> { pub fn invoke_signed(&self, signers_seeds: &[&[&[u8]]]) -> solana_program_error::ProgramResult { let instruction = RefundProposalDepositCpi { __program: self.instruction.__program, - - proposal_account: self - .instruction - .proposal_account - .expect("proposal_account is not set"), - - proposal_deposit_account: self - .instruction - .proposal_deposit_account - .expect("proposal_deposit_account is not set"), - - proposal_deposit_payer: self - .instruction - .proposal_deposit_payer - .expect("proposal_deposit_payer is not set"), + proposal_account: self.instruction.proposal_account, + proposal_deposit_account: self.instruction.proposal_deposit_account, + proposal_deposit_payer: self.instruction.proposal_deposit_payer, }; instruction.invoke_signed_with_remaining_accounts( signers_seeds, @@ -363,9 +315,9 @@ impl<'a, 'b> RefundProposalDepositCpiBuilder<'a, 'b> { #[derive(Clone, Debug)] struct RefundProposalDepositCpiBuilderInstruction<'a, 'b> { __program: &'b solana_account_info::AccountInfo<'a>, - proposal_account: Option<&'b solana_account_info::AccountInfo<'a>>, - proposal_deposit_account: Option<&'b solana_account_info::AccountInfo<'a>>, - proposal_deposit_payer: Option<&'b solana_account_info::AccountInfo<'a>>, + proposal_account: &'b solana_account_info::AccountInfo<'a>, + proposal_deposit_account: &'b solana_account_info::AccountInfo<'a>, + proposal_deposit_payer: &'b solana_account_info::AccountInfo<'a>, /// Additional instruction accounts `(AccountInfo, is_writable, is_signer)`. __remaining_accounts: Vec<(&'b solana_account_info::AccountInfo<'a>, bool, bool)>, } diff --git a/e2e/governance/src/generated/instructions/relinquish_vote.rs b/e2e/governance/src/generated/instructions/relinquish_vote.rs index 4eaa0d1..d326070 100644 --- a/e2e/governance/src/generated/instructions/relinquish_vote.rs +++ b/e2e/governance/src/generated/instructions/relinquish_vote.rs @@ -132,61 +132,39 @@ impl Default for RelinquishVoteInstructionData { /// 5. `[]` governing_token_mint /// 6. `[signer, optional]` governance_authority /// 7. `[writable, optional]` beneficiary_account -#[derive(Clone, Debug, Default)] +#[derive(Clone, Debug)] pub struct RelinquishVoteBuilder { - realm_account: Option, - governance_account: Option, - proposal_account: Option, - token_owner_record: Option, - proposal_vote_record: Option, - governing_token_mint: Option, + realm_account: solana_address::Address, + governance_account: solana_address::Address, + proposal_account: solana_address::Address, + token_owner_record: solana_address::Address, + proposal_vote_record: solana_address::Address, + governing_token_mint: solana_address::Address, governance_authority: Option, beneficiary_account: Option, __remaining_accounts: Vec, } impl RelinquishVoteBuilder { - pub fn new() -> Self { - Self::default() - } - #[inline(always)] - pub fn realm_account(&mut self, realm_account: solana_address::Address) -> &mut Self { - self.realm_account = Some(realm_account); - self - } - #[inline(always)] - pub fn governance_account(&mut self, governance_account: solana_address::Address) -> &mut Self { - self.governance_account = Some(governance_account); - self - } - #[inline(always)] - pub fn proposal_account(&mut self, proposal_account: solana_address::Address) -> &mut Self { - self.proposal_account = Some(proposal_account); - self - } - /// TokenOwnerRecord account. PDA seeds: ['governance',realm, vote_governing_token_mint, governing_token_owner] - #[inline(always)] - pub fn token_owner_record(&mut self, token_owner_record: solana_address::Address) -> &mut Self { - self.token_owner_record = Some(token_owner_record); - self - } - /// Proposal VoteRecord account. PDA seeds: ['governance',proposal, token_owner_record] - #[inline(always)] - pub fn proposal_vote_record( - &mut self, + pub fn new( + realm_account: solana_address::Address, + governance_account: solana_address::Address, + proposal_account: solana_address::Address, + token_owner_record: solana_address::Address, proposal_vote_record: solana_address::Address, - ) -> &mut Self { - self.proposal_vote_record = Some(proposal_vote_record); - self - } - /// The Governing Token Mint which was used to cast the vote (vote_governing_token_mint) - #[inline(always)] - pub fn governing_token_mint( - &mut self, governing_token_mint: solana_address::Address, - ) -> &mut Self { - self.governing_token_mint = Some(governing_token_mint); - self + ) -> Self { + Self { + realm_account, + governance_account, + proposal_account, + token_owner_record, + proposal_vote_record, + governing_token_mint, + governance_authority: None, + beneficiary_account: None, + __remaining_accounts: Vec::new(), + } } /// `[optional account]` #[inline(always)] @@ -225,23 +203,23 @@ impl RelinquishVoteBuilder { } #[allow(clippy::clone_on_copy)] pub fn instruction(&self) -> solana_instruction::Instruction { + let realm_account = self.realm_account; + let governance_account = self.governance_account; + let proposal_account = self.proposal_account; + let token_owner_record = self.token_owner_record; + let proposal_vote_record = self.proposal_vote_record; + let governing_token_mint = self.governing_token_mint; + let governance_authority = self.governance_authority; + let beneficiary_account = self.beneficiary_account; let accounts = RelinquishVote { - realm_account: self.realm_account.expect("realm_account is not set"), - governance_account: self - .governance_account - .expect("governance_account is not set"), - proposal_account: self.proposal_account.expect("proposal_account is not set"), - token_owner_record: self - .token_owner_record - .expect("token_owner_record is not set"), - proposal_vote_record: self - .proposal_vote_record - .expect("proposal_vote_record is not set"), - governing_token_mint: self - .governing_token_mint - .expect("governing_token_mint is not set"), - governance_authority: self.governance_authority, - beneficiary_account: self.beneficiary_account, + realm_account, + governance_account, + proposal_account, + token_owner_record, + proposal_vote_record, + governing_token_mint, + governance_authority, + beneficiary_account, }; accounts.instruction_with_remaining_accounts(&self.__remaining_accounts) @@ -436,71 +414,28 @@ pub struct RelinquishVoteCpiBuilder<'a, 'b> { } impl<'a, 'b> RelinquishVoteCpiBuilder<'a, 'b> { - pub fn new(program: &'b solana_account_info::AccountInfo<'a>) -> Self { - let instruction = Box::new(RelinquishVoteCpiBuilderInstruction { - __program: program, - realm_account: None, - governance_account: None, - proposal_account: None, - token_owner_record: None, - proposal_vote_record: None, - governing_token_mint: None, - governance_authority: None, - beneficiary_account: None, - __remaining_accounts: Vec::new(), - }); - Self { instruction } - } - #[inline(always)] - pub fn realm_account( - &mut self, + pub fn new( + __program: &'b solana_account_info::AccountInfo<'a>, realm_account: &'b solana_account_info::AccountInfo<'a>, - ) -> &mut Self { - self.instruction.realm_account = Some(realm_account); - self - } - #[inline(always)] - pub fn governance_account( - &mut self, governance_account: &'b solana_account_info::AccountInfo<'a>, - ) -> &mut Self { - self.instruction.governance_account = Some(governance_account); - self - } - #[inline(always)] - pub fn proposal_account( - &mut self, proposal_account: &'b solana_account_info::AccountInfo<'a>, - ) -> &mut Self { - self.instruction.proposal_account = Some(proposal_account); - self - } - /// TokenOwnerRecord account. PDA seeds: ['governance',realm, vote_governing_token_mint, governing_token_owner] - #[inline(always)] - pub fn token_owner_record( - &mut self, token_owner_record: &'b solana_account_info::AccountInfo<'a>, - ) -> &mut Self { - self.instruction.token_owner_record = Some(token_owner_record); - self - } - /// Proposal VoteRecord account. PDA seeds: ['governance',proposal, token_owner_record] - #[inline(always)] - pub fn proposal_vote_record( - &mut self, proposal_vote_record: &'b solana_account_info::AccountInfo<'a>, - ) -> &mut Self { - self.instruction.proposal_vote_record = Some(proposal_vote_record); - self - } - /// The Governing Token Mint which was used to cast the vote (vote_governing_token_mint) - #[inline(always)] - pub fn governing_token_mint( - &mut self, governing_token_mint: &'b solana_account_info::AccountInfo<'a>, - ) -> &mut Self { - self.instruction.governing_token_mint = Some(governing_token_mint); - self + ) -> Self { + let instruction = Box::new(RelinquishVoteCpiBuilderInstruction { + __program, + realm_account, + governance_account, + proposal_account, + token_owner_record, + proposal_vote_record, + governing_token_mint, + governance_authority: None, + beneficiary_account: None, + __remaining_accounts: Vec::new(), + }); + Self { instruction } } /// `[optional account]` #[inline(always)] @@ -558,39 +493,13 @@ impl<'a, 'b> RelinquishVoteCpiBuilder<'a, 'b> { pub fn invoke_signed(&self, signers_seeds: &[&[&[u8]]]) -> solana_program_error::ProgramResult { let instruction = RelinquishVoteCpi { __program: self.instruction.__program, - - realm_account: self - .instruction - .realm_account - .expect("realm_account is not set"), - - governance_account: self - .instruction - .governance_account - .expect("governance_account is not set"), - - proposal_account: self - .instruction - .proposal_account - .expect("proposal_account is not set"), - - token_owner_record: self - .instruction - .token_owner_record - .expect("token_owner_record is not set"), - - proposal_vote_record: self - .instruction - .proposal_vote_record - .expect("proposal_vote_record is not set"), - - governing_token_mint: self - .instruction - .governing_token_mint - .expect("governing_token_mint is not set"), - + realm_account: self.instruction.realm_account, + governance_account: self.instruction.governance_account, + proposal_account: self.instruction.proposal_account, + token_owner_record: self.instruction.token_owner_record, + proposal_vote_record: self.instruction.proposal_vote_record, + governing_token_mint: self.instruction.governing_token_mint, governance_authority: self.instruction.governance_authority, - beneficiary_account: self.instruction.beneficiary_account, }; instruction.invoke_signed_with_remaining_accounts( @@ -603,12 +512,12 @@ impl<'a, 'b> RelinquishVoteCpiBuilder<'a, 'b> { #[derive(Clone, Debug)] struct RelinquishVoteCpiBuilderInstruction<'a, 'b> { __program: &'b solana_account_info::AccountInfo<'a>, - realm_account: Option<&'b solana_account_info::AccountInfo<'a>>, - governance_account: Option<&'b solana_account_info::AccountInfo<'a>>, - proposal_account: Option<&'b solana_account_info::AccountInfo<'a>>, - token_owner_record: Option<&'b solana_account_info::AccountInfo<'a>>, - proposal_vote_record: Option<&'b solana_account_info::AccountInfo<'a>>, - governing_token_mint: Option<&'b solana_account_info::AccountInfo<'a>>, + realm_account: &'b solana_account_info::AccountInfo<'a>, + governance_account: &'b solana_account_info::AccountInfo<'a>, + proposal_account: &'b solana_account_info::AccountInfo<'a>, + token_owner_record: &'b solana_account_info::AccountInfo<'a>, + proposal_vote_record: &'b solana_account_info::AccountInfo<'a>, + governing_token_mint: &'b solana_account_info::AccountInfo<'a>, governance_authority: Option<&'b solana_account_info::AccountInfo<'a>>, beneficiary_account: Option<&'b solana_account_info::AccountInfo<'a>>, /// Additional instruction accounts `(AccountInfo, is_writable, is_signer)`. diff --git a/e2e/governance/src/generated/instructions/remove_required_signatory.rs b/e2e/governance/src/generated/instructions/remove_required_signatory.rs index 180efe0..5a38470 100644 --- a/e2e/governance/src/generated/instructions/remove_required_signatory.rs +++ b/e2e/governance/src/generated/instructions/remove_required_signatory.rs @@ -84,39 +84,26 @@ impl Default for RemoveRequiredSignatoryInstructionData { /// 0. `[writable, signer]` governance_account /// 1. `[writable]` required_signatory_account /// 2. `[writable]` beneficiary_account -#[derive(Clone, Debug, Default)] +#[derive(Clone, Debug)] pub struct RemoveRequiredSignatoryBuilder { - governance_account: Option, - required_signatory_account: Option, - beneficiary_account: Option, + governance_account: solana_address::Address, + required_signatory_account: solana_address::Address, + beneficiary_account: solana_address::Address, __remaining_accounts: Vec, } impl RemoveRequiredSignatoryBuilder { - pub fn new() -> Self { - Self::default() - } - #[inline(always)] - pub fn governance_account(&mut self, governance_account: solana_address::Address) -> &mut Self { - self.governance_account = Some(governance_account); - self - } - #[inline(always)] - pub fn required_signatory_account( - &mut self, + pub fn new( + governance_account: solana_address::Address, required_signatory_account: solana_address::Address, - ) -> &mut Self { - self.required_signatory_account = Some(required_signatory_account); - self - } - /// Beneficiary Account which would receive lamports from the disposed RequiredSignatory Account - #[inline(always)] - pub fn beneficiary_account( - &mut self, beneficiary_account: solana_address::Address, - ) -> &mut Self { - self.beneficiary_account = Some(beneficiary_account); - self + ) -> Self { + Self { + governance_account, + required_signatory_account, + beneficiary_account, + __remaining_accounts: Vec::new(), + } } /// Add an additional account to the instruction. #[inline(always)] @@ -135,16 +122,13 @@ impl RemoveRequiredSignatoryBuilder { } #[allow(clippy::clone_on_copy)] pub fn instruction(&self) -> solana_instruction::Instruction { + let governance_account = self.governance_account; + let required_signatory_account = self.required_signatory_account; + let beneficiary_account = self.beneficiary_account; let accounts = RemoveRequiredSignatory { - governance_account: self - .governance_account - .expect("governance_account is not set"), - required_signatory_account: self - .required_signatory_account - .expect("required_signatory_account is not set"), - beneficiary_account: self - .beneficiary_account - .expect("beneficiary_account is not set"), + governance_account, + required_signatory_account, + beneficiary_account, }; accounts.instruction_with_remaining_accounts(&self.__remaining_accounts) @@ -266,41 +250,21 @@ pub struct RemoveRequiredSignatoryCpiBuilder<'a, 'b> { } impl<'a, 'b> RemoveRequiredSignatoryCpiBuilder<'a, 'b> { - pub fn new(program: &'b solana_account_info::AccountInfo<'a>) -> Self { + pub fn new( + __program: &'b solana_account_info::AccountInfo<'a>, + governance_account: &'b solana_account_info::AccountInfo<'a>, + required_signatory_account: &'b solana_account_info::AccountInfo<'a>, + beneficiary_account: &'b solana_account_info::AccountInfo<'a>, + ) -> Self { let instruction = Box::new(RemoveRequiredSignatoryCpiBuilderInstruction { - __program: program, - governance_account: None, - required_signatory_account: None, - beneficiary_account: None, + __program, + governance_account, + required_signatory_account, + beneficiary_account, __remaining_accounts: Vec::new(), }); Self { instruction } } - #[inline(always)] - pub fn governance_account( - &mut self, - governance_account: &'b solana_account_info::AccountInfo<'a>, - ) -> &mut Self { - self.instruction.governance_account = Some(governance_account); - self - } - #[inline(always)] - pub fn required_signatory_account( - &mut self, - required_signatory_account: &'b solana_account_info::AccountInfo<'a>, - ) -> &mut Self { - self.instruction.required_signatory_account = Some(required_signatory_account); - self - } - /// Beneficiary Account which would receive lamports from the disposed RequiredSignatory Account - #[inline(always)] - pub fn beneficiary_account( - &mut self, - beneficiary_account: &'b solana_account_info::AccountInfo<'a>, - ) -> &mut Self { - self.instruction.beneficiary_account = Some(beneficiary_account); - self - } /// Add an additional account to the instruction. #[inline(always)] pub fn add_remaining_account( @@ -337,21 +301,9 @@ impl<'a, 'b> RemoveRequiredSignatoryCpiBuilder<'a, 'b> { pub fn invoke_signed(&self, signers_seeds: &[&[&[u8]]]) -> solana_program_error::ProgramResult { let instruction = RemoveRequiredSignatoryCpi { __program: self.instruction.__program, - - governance_account: self - .instruction - .governance_account - .expect("governance_account is not set"), - - required_signatory_account: self - .instruction - .required_signatory_account - .expect("required_signatory_account is not set"), - - beneficiary_account: self - .instruction - .beneficiary_account - .expect("beneficiary_account is not set"), + governance_account: self.instruction.governance_account, + required_signatory_account: self.instruction.required_signatory_account, + beneficiary_account: self.instruction.beneficiary_account, }; instruction.invoke_signed_with_remaining_accounts( signers_seeds, @@ -363,9 +315,9 @@ impl<'a, 'b> RemoveRequiredSignatoryCpiBuilder<'a, 'b> { #[derive(Clone, Debug)] struct RemoveRequiredSignatoryCpiBuilderInstruction<'a, 'b> { __program: &'b solana_account_info::AccountInfo<'a>, - governance_account: Option<&'b solana_account_info::AccountInfo<'a>>, - required_signatory_account: Option<&'b solana_account_info::AccountInfo<'a>>, - beneficiary_account: Option<&'b solana_account_info::AccountInfo<'a>>, + governance_account: &'b solana_account_info::AccountInfo<'a>, + required_signatory_account: &'b solana_account_info::AccountInfo<'a>, + beneficiary_account: &'b solana_account_info::AccountInfo<'a>, /// Additional instruction accounts `(AccountInfo, is_writable, is_signer)`. __remaining_accounts: Vec<(&'b solana_account_info::AccountInfo<'a>, bool, bool)>, } diff --git a/e2e/governance/src/generated/instructions/remove_transaction.rs b/e2e/governance/src/generated/instructions/remove_transaction.rs index 9afdeb5..f504e13 100644 --- a/e2e/governance/src/generated/instructions/remove_transaction.rs +++ b/e2e/governance/src/generated/instructions/remove_transaction.rs @@ -98,56 +98,32 @@ impl Default for RemoveTransactionInstructionData { /// 2. `[signer]` governance_authority /// 3. `[writable]` proposal_transaction_account /// 4. `[writable]` beneficiary_account -#[derive(Clone, Debug, Default)] +#[derive(Clone, Debug)] pub struct RemoveTransactionBuilder { - proposal_account: Option, - token_owner_record: Option, - governance_authority: Option, - proposal_transaction_account: Option, - beneficiary_account: Option, + proposal_account: solana_address::Address, + token_owner_record: solana_address::Address, + governance_authority: solana_address::Address, + proposal_transaction_account: solana_address::Address, + beneficiary_account: solana_address::Address, __remaining_accounts: Vec, } impl RemoveTransactionBuilder { - pub fn new() -> Self { - Self::default() - } - #[inline(always)] - pub fn proposal_account(&mut self, proposal_account: solana_address::Address) -> &mut Self { - self.proposal_account = Some(proposal_account); - self - } - /// TokenOwnerRecord account of the Proposal owner - #[inline(always)] - pub fn token_owner_record(&mut self, token_owner_record: solana_address::Address) -> &mut Self { - self.token_owner_record = Some(token_owner_record); - self - } - /// Governance Authority (Token Owner or Governance Delegate) - #[inline(always)] - pub fn governance_authority( - &mut self, + pub fn new( + proposal_account: solana_address::Address, + token_owner_record: solana_address::Address, governance_authority: solana_address::Address, - ) -> &mut Self { - self.governance_authority = Some(governance_authority); - self - } - #[inline(always)] - pub fn proposal_transaction_account( - &mut self, proposal_transaction_account: solana_address::Address, - ) -> &mut Self { - self.proposal_transaction_account = Some(proposal_transaction_account); - self - } - /// Beneficiary Account which would receive lamports from the disposed ProposalTransaction account - #[inline(always)] - pub fn beneficiary_account( - &mut self, beneficiary_account: solana_address::Address, - ) -> &mut Self { - self.beneficiary_account = Some(beneficiary_account); - self + ) -> Self { + Self { + proposal_account, + token_owner_record, + governance_authority, + proposal_transaction_account, + beneficiary_account, + __remaining_accounts: Vec::new(), + } } /// Add an additional account to the instruction. #[inline(always)] @@ -166,20 +142,17 @@ impl RemoveTransactionBuilder { } #[allow(clippy::clone_on_copy)] pub fn instruction(&self) -> solana_instruction::Instruction { + let proposal_account = self.proposal_account; + let token_owner_record = self.token_owner_record; + let governance_authority = self.governance_authority; + let proposal_transaction_account = self.proposal_transaction_account; + let beneficiary_account = self.beneficiary_account; let accounts = RemoveTransaction { - proposal_account: self.proposal_account.expect("proposal_account is not set"), - token_owner_record: self - .token_owner_record - .expect("token_owner_record is not set"), - governance_authority: self - .governance_authority - .expect("governance_authority is not set"), - proposal_transaction_account: self - .proposal_transaction_account - .expect("proposal_transaction_account is not set"), - beneficiary_account: self - .beneficiary_account - .expect("beneficiary_account is not set"), + proposal_account, + token_owner_record, + governance_authority, + proposal_transaction_account, + beneficiary_account, }; accounts.instruction_with_remaining_accounts(&self.__remaining_accounts) @@ -323,60 +296,24 @@ pub struct RemoveTransactionCpiBuilder<'a, 'b> { } impl<'a, 'b> RemoveTransactionCpiBuilder<'a, 'b> { - pub fn new(program: &'b solana_account_info::AccountInfo<'a>) -> Self { - let instruction = Box::new(RemoveTransactionCpiBuilderInstruction { - __program: program, - proposal_account: None, - token_owner_record: None, - governance_authority: None, - proposal_transaction_account: None, - beneficiary_account: None, - __remaining_accounts: Vec::new(), - }); - Self { instruction } - } - #[inline(always)] - pub fn proposal_account( - &mut self, + pub fn new( + __program: &'b solana_account_info::AccountInfo<'a>, proposal_account: &'b solana_account_info::AccountInfo<'a>, - ) -> &mut Self { - self.instruction.proposal_account = Some(proposal_account); - self - } - /// TokenOwnerRecord account of the Proposal owner - #[inline(always)] - pub fn token_owner_record( - &mut self, token_owner_record: &'b solana_account_info::AccountInfo<'a>, - ) -> &mut Self { - self.instruction.token_owner_record = Some(token_owner_record); - self - } - /// Governance Authority (Token Owner or Governance Delegate) - #[inline(always)] - pub fn governance_authority( - &mut self, governance_authority: &'b solana_account_info::AccountInfo<'a>, - ) -> &mut Self { - self.instruction.governance_authority = Some(governance_authority); - self - } - #[inline(always)] - pub fn proposal_transaction_account( - &mut self, proposal_transaction_account: &'b solana_account_info::AccountInfo<'a>, - ) -> &mut Self { - self.instruction.proposal_transaction_account = Some(proposal_transaction_account); - self - } - /// Beneficiary Account which would receive lamports from the disposed ProposalTransaction account - #[inline(always)] - pub fn beneficiary_account( - &mut self, beneficiary_account: &'b solana_account_info::AccountInfo<'a>, - ) -> &mut Self { - self.instruction.beneficiary_account = Some(beneficiary_account); - self + ) -> Self { + let instruction = Box::new(RemoveTransactionCpiBuilderInstruction { + __program, + proposal_account, + token_owner_record, + governance_authority, + proposal_transaction_account, + beneficiary_account, + __remaining_accounts: Vec::new(), + }); + Self { instruction } } /// Add an additional account to the instruction. #[inline(always)] @@ -414,31 +351,11 @@ impl<'a, 'b> RemoveTransactionCpiBuilder<'a, 'b> { pub fn invoke_signed(&self, signers_seeds: &[&[&[u8]]]) -> solana_program_error::ProgramResult { let instruction = RemoveTransactionCpi { __program: self.instruction.__program, - - proposal_account: self - .instruction - .proposal_account - .expect("proposal_account is not set"), - - token_owner_record: self - .instruction - .token_owner_record - .expect("token_owner_record is not set"), - - governance_authority: self - .instruction - .governance_authority - .expect("governance_authority is not set"), - - proposal_transaction_account: self - .instruction - .proposal_transaction_account - .expect("proposal_transaction_account is not set"), - - beneficiary_account: self - .instruction - .beneficiary_account - .expect("beneficiary_account is not set"), + proposal_account: self.instruction.proposal_account, + token_owner_record: self.instruction.token_owner_record, + governance_authority: self.instruction.governance_authority, + proposal_transaction_account: self.instruction.proposal_transaction_account, + beneficiary_account: self.instruction.beneficiary_account, }; instruction.invoke_signed_with_remaining_accounts( signers_seeds, @@ -450,11 +367,11 @@ impl<'a, 'b> RemoveTransactionCpiBuilder<'a, 'b> { #[derive(Clone, Debug)] struct RemoveTransactionCpiBuilderInstruction<'a, 'b> { __program: &'b solana_account_info::AccountInfo<'a>, - proposal_account: Option<&'b solana_account_info::AccountInfo<'a>>, - token_owner_record: Option<&'b solana_account_info::AccountInfo<'a>>, - governance_authority: Option<&'b solana_account_info::AccountInfo<'a>>, - proposal_transaction_account: Option<&'b solana_account_info::AccountInfo<'a>>, - beneficiary_account: Option<&'b solana_account_info::AccountInfo<'a>>, + proposal_account: &'b solana_account_info::AccountInfo<'a>, + token_owner_record: &'b solana_account_info::AccountInfo<'a>, + governance_authority: &'b solana_account_info::AccountInfo<'a>, + proposal_transaction_account: &'b solana_account_info::AccountInfo<'a>, + beneficiary_account: &'b solana_account_info::AccountInfo<'a>, /// Additional instruction accounts `(AccountInfo, is_writable, is_signer)`. __remaining_accounts: Vec<(&'b solana_account_info::AccountInfo<'a>, bool, bool)>, } diff --git a/e2e/governance/src/generated/instructions/revoke_governing_tokens.rs b/e2e/governance/src/generated/instructions/revoke_governing_tokens.rs index aa382c4..c7efa2f 100644 --- a/e2e/governance/src/generated/instructions/revoke_governing_tokens.rs +++ b/e2e/governance/src/generated/instructions/revoke_governing_tokens.rs @@ -129,69 +129,40 @@ impl RevokeGoverningTokensInstructionArgs { /// 4. `[signer]` governing_token_mint_authority_or_token_owner /// 5. `[]` realm_config_account /// 6. `[optional]` token_program (default to `TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA`) -#[derive(Clone, Debug, Default)] +#[derive(Clone, Debug)] pub struct RevokeGoverningTokensBuilder { - realm_account: Option, - governing_token_holding_account: Option, - token_owner_record: Option, - governing_token_mint: Option, - governing_token_mint_authority_or_token_owner: Option, - realm_config_account: Option, + realm_account: solana_address::Address, + governing_token_holding_account: solana_address::Address, + token_owner_record: solana_address::Address, + governing_token_mint: solana_address::Address, + governing_token_mint_authority_or_token_owner: solana_address::Address, + realm_config_account: solana_address::Address, token_program: Option, - amount: Option, + amount: u64, __remaining_accounts: Vec, } impl RevokeGoverningTokensBuilder { - pub fn new() -> Self { - Self::default() - } - #[inline(always)] - pub fn realm_account(&mut self, realm_account: solana_address::Address) -> &mut Self { - self.realm_account = Some(realm_account); - self - } - /// seeds=['governance', realm, governing_token_mint] - #[inline(always)] - pub fn governing_token_holding_account( - &mut self, + pub fn new( + realm_account: solana_address::Address, governing_token_holding_account: solana_address::Address, - ) -> &mut Self { - self.governing_token_holding_account = Some(governing_token_holding_account); - self - } - /// seeds=['governance', realm, governing_token_mint, governing_token_owner] - #[inline(always)] - pub fn token_owner_record(&mut self, token_owner_record: solana_address::Address) -> &mut Self { - self.token_owner_record = Some(token_owner_record); - self - } - #[inline(always)] - pub fn governing_token_mint( - &mut self, + token_owner_record: solana_address::Address, governing_token_mint: solana_address::Address, - ) -> &mut Self { - self.governing_token_mint = Some(governing_token_mint); - self - } - /// GoverningTokenMint mint_authority - #[inline(always)] - pub fn governing_token_mint_authority_or_token_owner( - &mut self, governing_token_mint_authority_or_token_owner: solana_address::Address, - ) -> &mut Self { - self.governing_token_mint_authority_or_token_owner = - Some(governing_token_mint_authority_or_token_owner); - self - } - /// seeds=['realm-config', realm] - #[inline(always)] - pub fn realm_config_account( - &mut self, realm_config_account: solana_address::Address, - ) -> &mut Self { - self.realm_config_account = Some(realm_config_account); - self + amount: u64, + ) -> Self { + Self { + realm_account, + governing_token_holding_account, + token_owner_record, + governing_token_mint, + governing_token_mint_authority_or_token_owner, + realm_config_account, + token_program: None, + amount, + __remaining_accounts: Vec::new(), + } } /// `[optional account, default to 'TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA']` #[inline(always)] @@ -199,11 +170,6 @@ impl RevokeGoverningTokensBuilder { self.token_program = Some(token_program); self } - #[inline(always)] - pub fn amount(&mut self, amount: u64) -> &mut Self { - self.amount = Some(amount); - self - } /// Add an additional account to the instruction. #[inline(always)] pub fn add_remaining_account(&mut self, account: solana_instruction::AccountMeta) -> &mut Self { @@ -221,29 +187,27 @@ impl RevokeGoverningTokensBuilder { } #[allow(clippy::clone_on_copy)] pub fn instruction(&self) -> solana_instruction::Instruction { + let realm_account = self.realm_account; + let governing_token_holding_account = self.governing_token_holding_account; + let token_owner_record = self.token_owner_record; + let governing_token_mint = self.governing_token_mint; + let governing_token_mint_authority_or_token_owner = + self.governing_token_mint_authority_or_token_owner; + let realm_config_account = self.realm_config_account; + let token_program = self.token_program.unwrap_or(solana_address::address!( + "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA" + )); let accounts = RevokeGoverningTokens { - realm_account: self.realm_account.expect("realm_account is not set"), - governing_token_holding_account: self - .governing_token_holding_account - .expect("governing_token_holding_account is not set"), - token_owner_record: self - .token_owner_record - .expect("token_owner_record is not set"), - governing_token_mint: self - .governing_token_mint - .expect("governing_token_mint is not set"), - governing_token_mint_authority_or_token_owner: self - .governing_token_mint_authority_or_token_owner - .expect("governing_token_mint_authority_or_token_owner is not set"), - realm_config_account: self - .realm_config_account - .expect("realm_config_account is not set"), - token_program: self.token_program.unwrap_or(solana_address::address!( - "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA" - )), + realm_account, + governing_token_holding_account, + token_owner_record, + governing_token_mint, + governing_token_mint_authority_or_token_owner, + realm_config_account, + token_program, }; let args = RevokeGoverningTokensInstructionArgs { - amount: self.amount.clone().expect("amount is not set"), + amount: self.amount.clone(), }; accounts.instruction_with_remaining_accounts(args, &self.__remaining_accounts) @@ -416,87 +380,30 @@ pub struct RevokeGoverningTokensCpiBuilder<'a, 'b> { } impl<'a, 'b> RevokeGoverningTokensCpiBuilder<'a, 'b> { - pub fn new(program: &'b solana_account_info::AccountInfo<'a>) -> Self { - let instruction = Box::new(RevokeGoverningTokensCpiBuilderInstruction { - __program: program, - realm_account: None, - governing_token_holding_account: None, - token_owner_record: None, - governing_token_mint: None, - governing_token_mint_authority_or_token_owner: None, - realm_config_account: None, - token_program: None, - amount: None, - __remaining_accounts: Vec::new(), - }); - Self { instruction } - } - #[inline(always)] - pub fn realm_account( - &mut self, + pub fn new( + __program: &'b solana_account_info::AccountInfo<'a>, realm_account: &'b solana_account_info::AccountInfo<'a>, - ) -> &mut Self { - self.instruction.realm_account = Some(realm_account); - self - } - /// seeds=['governance', realm, governing_token_mint] - #[inline(always)] - pub fn governing_token_holding_account( - &mut self, governing_token_holding_account: &'b solana_account_info::AccountInfo<'a>, - ) -> &mut Self { - self.instruction.governing_token_holding_account = Some(governing_token_holding_account); - self - } - /// seeds=['governance', realm, governing_token_mint, governing_token_owner] - #[inline(always)] - pub fn token_owner_record( - &mut self, token_owner_record: &'b solana_account_info::AccountInfo<'a>, - ) -> &mut Self { - self.instruction.token_owner_record = Some(token_owner_record); - self - } - #[inline(always)] - pub fn governing_token_mint( - &mut self, governing_token_mint: &'b solana_account_info::AccountInfo<'a>, - ) -> &mut Self { - self.instruction.governing_token_mint = Some(governing_token_mint); - self - } - /// GoverningTokenMint mint_authority - #[inline(always)] - pub fn governing_token_mint_authority_or_token_owner( - &mut self, governing_token_mint_authority_or_token_owner: &'b solana_account_info::AccountInfo<'a>, - ) -> &mut Self { - self.instruction - .governing_token_mint_authority_or_token_owner = - Some(governing_token_mint_authority_or_token_owner); - self - } - /// seeds=['realm-config', realm] - #[inline(always)] - pub fn realm_config_account( - &mut self, realm_config_account: &'b solana_account_info::AccountInfo<'a>, - ) -> &mut Self { - self.instruction.realm_config_account = Some(realm_config_account); - self - } - #[inline(always)] - pub fn token_program( - &mut self, token_program: &'b solana_account_info::AccountInfo<'a>, - ) -> &mut Self { - self.instruction.token_program = Some(token_program); - self - } - #[inline(always)] - pub fn amount(&mut self, amount: u64) -> &mut Self { - self.instruction.amount = Some(amount); - self + amount: u64, + ) -> Self { + let instruction = Box::new(RevokeGoverningTokensCpiBuilderInstruction { + __program, + realm_account, + governing_token_holding_account, + token_owner_record, + governing_token_mint, + governing_token_mint_authority_or_token_owner, + realm_config_account, + token_program, + amount, + __remaining_accounts: Vec::new(), + }); + Self { instruction } } /// Add an additional account to the instruction. #[inline(always)] @@ -533,45 +440,19 @@ impl<'a, 'b> RevokeGoverningTokensCpiBuilder<'a, 'b> { #[allow(clippy::vec_init_then_push)] pub fn invoke_signed(&self, signers_seeds: &[&[&[u8]]]) -> solana_program_error::ProgramResult { let args = RevokeGoverningTokensInstructionArgs { - amount: self.instruction.amount.clone().expect("amount is not set"), + amount: self.instruction.amount.clone(), }; let instruction = RevokeGoverningTokensCpi { __program: self.instruction.__program, - - realm_account: self - .instruction - .realm_account - .expect("realm_account is not set"), - - governing_token_holding_account: self - .instruction - .governing_token_holding_account - .expect("governing_token_holding_account is not set"), - - token_owner_record: self - .instruction - .token_owner_record - .expect("token_owner_record is not set"), - - governing_token_mint: self - .instruction - .governing_token_mint - .expect("governing_token_mint is not set"), - + realm_account: self.instruction.realm_account, + governing_token_holding_account: self.instruction.governing_token_holding_account, + token_owner_record: self.instruction.token_owner_record, + governing_token_mint: self.instruction.governing_token_mint, governing_token_mint_authority_or_token_owner: self .instruction - .governing_token_mint_authority_or_token_owner - .expect("governing_token_mint_authority_or_token_owner is not set"), - - realm_config_account: self - .instruction - .realm_config_account - .expect("realm_config_account is not set"), - - token_program: self - .instruction - .token_program - .expect("token_program is not set"), + .governing_token_mint_authority_or_token_owner, + realm_config_account: self.instruction.realm_config_account, + token_program: self.instruction.token_program, __args: args, }; instruction.invoke_signed_with_remaining_accounts( @@ -584,14 +465,14 @@ impl<'a, 'b> RevokeGoverningTokensCpiBuilder<'a, 'b> { #[derive(Clone, Debug)] struct RevokeGoverningTokensCpiBuilderInstruction<'a, 'b> { __program: &'b solana_account_info::AccountInfo<'a>, - realm_account: Option<&'b solana_account_info::AccountInfo<'a>>, - governing_token_holding_account: Option<&'b solana_account_info::AccountInfo<'a>>, - token_owner_record: Option<&'b solana_account_info::AccountInfo<'a>>, - governing_token_mint: Option<&'b solana_account_info::AccountInfo<'a>>, - governing_token_mint_authority_or_token_owner: Option<&'b solana_account_info::AccountInfo<'a>>, - realm_config_account: Option<&'b solana_account_info::AccountInfo<'a>>, - token_program: Option<&'b solana_account_info::AccountInfo<'a>>, - amount: Option, + realm_account: &'b solana_account_info::AccountInfo<'a>, + governing_token_holding_account: &'b solana_account_info::AccountInfo<'a>, + token_owner_record: &'b solana_account_info::AccountInfo<'a>, + governing_token_mint: &'b solana_account_info::AccountInfo<'a>, + governing_token_mint_authority_or_token_owner: &'b solana_account_info::AccountInfo<'a>, + realm_config_account: &'b solana_account_info::AccountInfo<'a>, + token_program: &'b solana_account_info::AccountInfo<'a>, + amount: u64, /// Additional instruction accounts `(AccountInfo, is_writable, is_signer)`. __remaining_accounts: Vec<(&'b solana_account_info::AccountInfo<'a>, bool, bool)>, } diff --git a/e2e/governance/src/generated/instructions/set_governance_config.rs b/e2e/governance/src/generated/instructions/set_governance_config.rs index 3fe2df3..9238d3b 100644 --- a/e2e/governance/src/generated/instructions/set_governance_config.rs +++ b/e2e/governance/src/generated/instructions/set_governance_config.rs @@ -89,27 +89,20 @@ impl SetGovernanceConfigInstructionArgs { /// ### Accounts: /// /// 0. `[writable, signer]` governance_account -#[derive(Clone, Debug, Default)] +#[derive(Clone, Debug)] pub struct SetGovernanceConfigBuilder { - governance_account: Option, - config: Option, + governance_account: solana_address::Address, + config: GovernanceConfig, __remaining_accounts: Vec, } impl SetGovernanceConfigBuilder { - pub fn new() -> Self { - Self::default() - } - /// The governance account the config is for - #[inline(always)] - pub fn governance_account(&mut self, governance_account: solana_address::Address) -> &mut Self { - self.governance_account = Some(governance_account); - self - } - #[inline(always)] - pub fn config(&mut self, config: GovernanceConfig) -> &mut Self { - self.config = Some(config); - self + pub fn new(governance_account: solana_address::Address, config: GovernanceConfig) -> Self { + Self { + governance_account, + config, + __remaining_accounts: Vec::new(), + } } /// Add an additional account to the instruction. #[inline(always)] @@ -128,13 +121,10 @@ impl SetGovernanceConfigBuilder { } #[allow(clippy::clone_on_copy)] pub fn instruction(&self) -> solana_instruction::Instruction { - let accounts = SetGovernanceConfig { - governance_account: self - .governance_account - .expect("governance_account is not set"), - }; + let governance_account = self.governance_account; + let accounts = SetGovernanceConfig { governance_account }; let args = SetGovernanceConfigInstructionArgs { - config: self.config.clone().expect("config is not set"), + config: self.config.clone(), }; accounts.instruction_with_remaining_accounts(args, &self.__remaining_accounts) @@ -241,29 +231,19 @@ pub struct SetGovernanceConfigCpiBuilder<'a, 'b> { } impl<'a, 'b> SetGovernanceConfigCpiBuilder<'a, 'b> { - pub fn new(program: &'b solana_account_info::AccountInfo<'a>) -> Self { + pub fn new( + __program: &'b solana_account_info::AccountInfo<'a>, + governance_account: &'b solana_account_info::AccountInfo<'a>, + config: GovernanceConfig, + ) -> Self { let instruction = Box::new(SetGovernanceConfigCpiBuilderInstruction { - __program: program, - governance_account: None, - config: None, + __program, + governance_account, + config, __remaining_accounts: Vec::new(), }); Self { instruction } } - /// The governance account the config is for - #[inline(always)] - pub fn governance_account( - &mut self, - governance_account: &'b solana_account_info::AccountInfo<'a>, - ) -> &mut Self { - self.instruction.governance_account = Some(governance_account); - self - } - #[inline(always)] - pub fn config(&mut self, config: GovernanceConfig) -> &mut Self { - self.instruction.config = Some(config); - self - } /// Add an additional account to the instruction. #[inline(always)] pub fn add_remaining_account( @@ -299,15 +279,11 @@ impl<'a, 'b> SetGovernanceConfigCpiBuilder<'a, 'b> { #[allow(clippy::vec_init_then_push)] pub fn invoke_signed(&self, signers_seeds: &[&[&[u8]]]) -> solana_program_error::ProgramResult { let args = SetGovernanceConfigInstructionArgs { - config: self.instruction.config.clone().expect("config is not set"), + config: self.instruction.config.clone(), }; let instruction = SetGovernanceConfigCpi { __program: self.instruction.__program, - - governance_account: self - .instruction - .governance_account - .expect("governance_account is not set"), + governance_account: self.instruction.governance_account, __args: args, }; instruction.invoke_signed_with_remaining_accounts( @@ -320,8 +296,8 @@ impl<'a, 'b> SetGovernanceConfigCpiBuilder<'a, 'b> { #[derive(Clone, Debug)] struct SetGovernanceConfigCpiBuilderInstruction<'a, 'b> { __program: &'b solana_account_info::AccountInfo<'a>, - governance_account: Option<&'b solana_account_info::AccountInfo<'a>>, - config: Option, + governance_account: &'b solana_account_info::AccountInfo<'a>, + config: GovernanceConfig, /// Additional instruction accounts `(AccountInfo, is_writable, is_signer)`. __remaining_accounts: Vec<(&'b solana_account_info::AccountInfo<'a>, bool, bool)>, } diff --git a/e2e/governance/src/generated/instructions/set_governance_delegate.rs b/e2e/governance/src/generated/instructions/set_governance_delegate.rs index 1d6c050..4bf5d9d 100644 --- a/e2e/governance/src/generated/instructions/set_governance_delegate.rs +++ b/e2e/governance/src/generated/instructions/set_governance_delegate.rs @@ -96,31 +96,25 @@ impl SetGovernanceDelegateInstructionArgs { /// /// 0. `[signer]` current_delegate_or_owner /// 1. `[writable]` token_owner_record -#[derive(Clone, Debug, Default)] +#[derive(Clone, Debug)] pub struct SetGovernanceDelegateBuilder { - current_delegate_or_owner: Option, - token_owner_record: Option, + current_delegate_or_owner: solana_address::Address, + token_owner_record: solana_address::Address, new_governance_delegate: Option
, __remaining_accounts: Vec, } impl SetGovernanceDelegateBuilder { - pub fn new() -> Self { - Self::default() - } - /// Current governance delegate or governing token owner - #[inline(always)] - pub fn current_delegate_or_owner( - &mut self, + pub fn new( current_delegate_or_owner: solana_address::Address, - ) -> &mut Self { - self.current_delegate_or_owner = Some(current_delegate_or_owner); - self - } - #[inline(always)] - pub fn token_owner_record(&mut self, token_owner_record: solana_address::Address) -> &mut Self { - self.token_owner_record = Some(token_owner_record); - self + token_owner_record: solana_address::Address, + ) -> Self { + Self { + current_delegate_or_owner, + token_owner_record, + new_governance_delegate: None, + __remaining_accounts: Vec::new(), + } } /// `[optional argument]` #[inline(always)] @@ -145,13 +139,11 @@ impl SetGovernanceDelegateBuilder { } #[allow(clippy::clone_on_copy)] pub fn instruction(&self) -> solana_instruction::Instruction { + let current_delegate_or_owner = self.current_delegate_or_owner; + let token_owner_record = self.token_owner_record; let accounts = SetGovernanceDelegate { - current_delegate_or_owner: self - .current_delegate_or_owner - .expect("current_delegate_or_owner is not set"), - token_owner_record: self - .token_owner_record - .expect("token_owner_record is not set"), + current_delegate_or_owner, + token_owner_record, }; let args = SetGovernanceDelegateInstructionArgs { new_governance_delegate: self.new_governance_delegate.clone(), @@ -272,33 +264,20 @@ pub struct SetGovernanceDelegateCpiBuilder<'a, 'b> { } impl<'a, 'b> SetGovernanceDelegateCpiBuilder<'a, 'b> { - pub fn new(program: &'b solana_account_info::AccountInfo<'a>) -> Self { + pub fn new( + __program: &'b solana_account_info::AccountInfo<'a>, + current_delegate_or_owner: &'b solana_account_info::AccountInfo<'a>, + token_owner_record: &'b solana_account_info::AccountInfo<'a>, + ) -> Self { let instruction = Box::new(SetGovernanceDelegateCpiBuilderInstruction { - __program: program, - current_delegate_or_owner: None, - token_owner_record: None, + __program, + current_delegate_or_owner, + token_owner_record, new_governance_delegate: None, __remaining_accounts: Vec::new(), }); Self { instruction } } - /// Current governance delegate or governing token owner - #[inline(always)] - pub fn current_delegate_or_owner( - &mut self, - current_delegate_or_owner: &'b solana_account_info::AccountInfo<'a>, - ) -> &mut Self { - self.instruction.current_delegate_or_owner = Some(current_delegate_or_owner); - self - } - #[inline(always)] - pub fn token_owner_record( - &mut self, - token_owner_record: &'b solana_account_info::AccountInfo<'a>, - ) -> &mut Self { - self.instruction.token_owner_record = Some(token_owner_record); - self - } /// `[optional argument]` #[inline(always)] pub fn new_governance_delegate(&mut self, new_governance_delegate: Address) -> &mut Self { @@ -344,16 +323,8 @@ impl<'a, 'b> SetGovernanceDelegateCpiBuilder<'a, 'b> { }; let instruction = SetGovernanceDelegateCpi { __program: self.instruction.__program, - - current_delegate_or_owner: self - .instruction - .current_delegate_or_owner - .expect("current_delegate_or_owner is not set"), - - token_owner_record: self - .instruction - .token_owner_record - .expect("token_owner_record is not set"), + current_delegate_or_owner: self.instruction.current_delegate_or_owner, + token_owner_record: self.instruction.token_owner_record, __args: args, }; instruction.invoke_signed_with_remaining_accounts( @@ -366,8 +337,8 @@ impl<'a, 'b> SetGovernanceDelegateCpiBuilder<'a, 'b> { #[derive(Clone, Debug)] struct SetGovernanceDelegateCpiBuilderInstruction<'a, 'b> { __program: &'b solana_account_info::AccountInfo<'a>, - current_delegate_or_owner: Option<&'b solana_account_info::AccountInfo<'a>>, - token_owner_record: Option<&'b solana_account_info::AccountInfo<'a>>, + current_delegate_or_owner: &'b solana_account_info::AccountInfo<'a>, + token_owner_record: &'b solana_account_info::AccountInfo<'a>, new_governance_delegate: Option
, /// Additional instruction accounts `(AccountInfo, is_writable, is_signer)`. __remaining_accounts: Vec<(&'b solana_account_info::AccountInfo<'a>, bool, bool)>, diff --git a/e2e/governance/src/generated/instructions/set_realm_authority.rs b/e2e/governance/src/generated/instructions/set_realm_authority.rs index ef11a15..7c5bece 100644 --- a/e2e/governance/src/generated/instructions/set_realm_authority.rs +++ b/e2e/governance/src/generated/instructions/set_realm_authority.rs @@ -109,28 +109,28 @@ impl SetRealmAuthorityInstructionArgs { /// 0. `[writable]` realm_account /// 1. `[signer]` realm_authority /// 2. `[optional]` new_realm_authority -#[derive(Clone, Debug, Default)] +#[derive(Clone, Debug)] pub struct SetRealmAuthorityBuilder { - realm_account: Option, - realm_authority: Option, + realm_account: solana_address::Address, + realm_authority: solana_address::Address, new_realm_authority: Option, - action: Option, + action: SetRealmAuthorityAction, __remaining_accounts: Vec, } impl SetRealmAuthorityBuilder { - pub fn new() -> Self { - Self::default() - } - #[inline(always)] - pub fn realm_account(&mut self, realm_account: solana_address::Address) -> &mut Self { - self.realm_account = Some(realm_account); - self - } - #[inline(always)] - pub fn realm_authority(&mut self, realm_authority: solana_address::Address) -> &mut Self { - self.realm_authority = Some(realm_authority); - self + pub fn new( + realm_account: solana_address::Address, + realm_authority: solana_address::Address, + action: SetRealmAuthorityAction, + ) -> Self { + Self { + realm_account, + realm_authority, + new_realm_authority: None, + action, + __remaining_accounts: Vec::new(), + } } /// `[optional account]` /// Must be one of the realm governances when set @@ -142,11 +142,6 @@ impl SetRealmAuthorityBuilder { self.new_realm_authority = new_realm_authority; self } - #[inline(always)] - pub fn action(&mut self, action: SetRealmAuthorityAction) -> &mut Self { - self.action = Some(action); - self - } /// Add an additional account to the instruction. #[inline(always)] pub fn add_remaining_account(&mut self, account: solana_instruction::AccountMeta) -> &mut Self { @@ -164,13 +159,16 @@ impl SetRealmAuthorityBuilder { } #[allow(clippy::clone_on_copy)] pub fn instruction(&self) -> solana_instruction::Instruction { + let realm_account = self.realm_account; + let realm_authority = self.realm_authority; + let new_realm_authority = self.new_realm_authority; let accounts = SetRealmAuthority { - realm_account: self.realm_account.expect("realm_account is not set"), - realm_authority: self.realm_authority.expect("realm_authority is not set"), - new_realm_authority: self.new_realm_authority, + realm_account, + realm_authority, + new_realm_authority, }; let args = SetRealmAuthorityInstructionArgs { - action: self.action.clone().expect("action is not set"), + action: self.action.clone(), }; accounts.instruction_with_remaining_accounts(args, &self.__remaining_accounts) @@ -307,33 +305,22 @@ pub struct SetRealmAuthorityCpiBuilder<'a, 'b> { } impl<'a, 'b> SetRealmAuthorityCpiBuilder<'a, 'b> { - pub fn new(program: &'b solana_account_info::AccountInfo<'a>) -> Self { + pub fn new( + __program: &'b solana_account_info::AccountInfo<'a>, + realm_account: &'b solana_account_info::AccountInfo<'a>, + realm_authority: &'b solana_account_info::AccountInfo<'a>, + action: SetRealmAuthorityAction, + ) -> Self { let instruction = Box::new(SetRealmAuthorityCpiBuilderInstruction { - __program: program, - realm_account: None, - realm_authority: None, + __program, + realm_account, + realm_authority, new_realm_authority: None, - action: None, + action, __remaining_accounts: Vec::new(), }); Self { instruction } } - #[inline(always)] - pub fn realm_account( - &mut self, - realm_account: &'b solana_account_info::AccountInfo<'a>, - ) -> &mut Self { - self.instruction.realm_account = Some(realm_account); - self - } - #[inline(always)] - pub fn realm_authority( - &mut self, - realm_authority: &'b solana_account_info::AccountInfo<'a>, - ) -> &mut Self { - self.instruction.realm_authority = Some(realm_authority); - self - } /// `[optional account]` /// Must be one of the realm governances when set #[inline(always)] @@ -344,11 +331,6 @@ impl<'a, 'b> SetRealmAuthorityCpiBuilder<'a, 'b> { self.instruction.new_realm_authority = new_realm_authority; self } - #[inline(always)] - pub fn action(&mut self, action: SetRealmAuthorityAction) -> &mut Self { - self.instruction.action = Some(action); - self - } /// Add an additional account to the instruction. #[inline(always)] pub fn add_remaining_account( @@ -384,21 +366,12 @@ impl<'a, 'b> SetRealmAuthorityCpiBuilder<'a, 'b> { #[allow(clippy::vec_init_then_push)] pub fn invoke_signed(&self, signers_seeds: &[&[&[u8]]]) -> solana_program_error::ProgramResult { let args = SetRealmAuthorityInstructionArgs { - action: self.instruction.action.clone().expect("action is not set"), + action: self.instruction.action.clone(), }; let instruction = SetRealmAuthorityCpi { __program: self.instruction.__program, - - realm_account: self - .instruction - .realm_account - .expect("realm_account is not set"), - - realm_authority: self - .instruction - .realm_authority - .expect("realm_authority is not set"), - + realm_account: self.instruction.realm_account, + realm_authority: self.instruction.realm_authority, new_realm_authority: self.instruction.new_realm_authority, __args: args, }; @@ -412,10 +385,10 @@ impl<'a, 'b> SetRealmAuthorityCpiBuilder<'a, 'b> { #[derive(Clone, Debug)] struct SetRealmAuthorityCpiBuilderInstruction<'a, 'b> { __program: &'b solana_account_info::AccountInfo<'a>, - realm_account: Option<&'b solana_account_info::AccountInfo<'a>>, - realm_authority: Option<&'b solana_account_info::AccountInfo<'a>>, + realm_account: &'b solana_account_info::AccountInfo<'a>, + realm_authority: &'b solana_account_info::AccountInfo<'a>, new_realm_authority: Option<&'b solana_account_info::AccountInfo<'a>>, - action: Option, + action: SetRealmAuthorityAction, /// Additional instruction accounts `(AccountInfo, is_writable, is_signer)`. __remaining_accounts: Vec<(&'b solana_account_info::AccountInfo<'a>, bool, bool)>, } diff --git a/e2e/governance/src/generated/instructions/set_realm_config.rs b/e2e/governance/src/generated/instructions/set_realm_config.rs index 82554fd..7b559a3 100644 --- a/e2e/governance/src/generated/instructions/set_realm_config.rs +++ b/e2e/governance/src/generated/instructions/set_realm_config.rs @@ -213,36 +213,45 @@ impl SetRealmConfigInstructionArgs { /// 8. `[optional]` council_voter_weight_addin_program_id /// 9. `[optional]` max_council_voter_weight_addin_program_id /// 10. `[signer, optional]` payer -#[derive(Clone, Debug, Default)] +#[derive(Clone, Debug)] pub struct SetRealmConfigBuilder { - realm_account: Option, - realm_authority: Option, + realm_account: solana_address::Address, + realm_authority: solana_address::Address, council_token_mint: Option, council_token_holding_account: Option, system_program: Option, - realm_config: Option, + realm_config: solana_address::Address, community_voter_weight_addin_program_id: Option, max_community_voter_weight_addin_program_id: Option, council_voter_weight_addin_program_id: Option, max_council_voter_weight_addin_program_id: Option, payer: Option, - config_args: Option, + config_args: RealmConfigParams, __remaining_accounts: Vec, } impl SetRealmConfigBuilder { - pub fn new() -> Self { - Self::default() - } - #[inline(always)] - pub fn realm_account(&mut self, realm_account: solana_address::Address) -> &mut Self { - self.realm_account = Some(realm_account); - self - } - #[inline(always)] - pub fn realm_authority(&mut self, realm_authority: solana_address::Address) -> &mut Self { - self.realm_authority = Some(realm_authority); - self + pub fn new( + realm_account: solana_address::Address, + realm_authority: solana_address::Address, + realm_config: solana_address::Address, + config_args: RealmConfigParams, + ) -> Self { + Self { + realm_account, + realm_authority, + council_token_mint: None, + council_token_holding_account: None, + system_program: None, + realm_config, + community_voter_weight_addin_program_id: None, + max_community_voter_weight_addin_program_id: None, + council_voter_weight_addin_program_id: None, + max_council_voter_weight_addin_program_id: None, + payer: None, + config_args, + __remaining_accounts: Vec::new(), + } } /// `[optional account]` /// Council Token Mint - optional. @@ -273,12 +282,6 @@ impl SetRealmConfigBuilder { self.system_program = Some(system_program); self } - /// RealmConfig account. seeds=['realm-config', realm] - #[inline(always)] - pub fn realm_config(&mut self, realm_config: solana_address::Address) -> &mut Self { - self.realm_config = Some(realm_config); - self - } /// `[optional account]` /// Optional Community Voter Weight Addin Program Id #[inline(always)] @@ -327,11 +330,6 @@ impl SetRealmConfigBuilder { self.payer = payer; self } - #[inline(always)] - pub fn config_args(&mut self, config_args: RealmConfigParams) -> &mut Self { - self.config_args = Some(config_args); - self - } /// Add an additional account to the instruction. #[inline(always)] pub fn add_remaining_account(&mut self, account: solana_instruction::AccountMeta) -> &mut Self { @@ -349,25 +347,36 @@ impl SetRealmConfigBuilder { } #[allow(clippy::clone_on_copy)] pub fn instruction(&self) -> solana_instruction::Instruction { + let realm_account = self.realm_account; + let realm_authority = self.realm_authority; + let council_token_mint = self.council_token_mint; + let council_token_holding_account = self.council_token_holding_account; + let system_program = self + .system_program + .unwrap_or(solana_address::address!("11111111111111111111111111111111")); + let realm_config = self.realm_config; + let community_voter_weight_addin_program_id = self.community_voter_weight_addin_program_id; + let max_community_voter_weight_addin_program_id = + self.max_community_voter_weight_addin_program_id; + let council_voter_weight_addin_program_id = self.council_voter_weight_addin_program_id; + let max_council_voter_weight_addin_program_id = + self.max_council_voter_weight_addin_program_id; + let payer = self.payer; let accounts = SetRealmConfig { - realm_account: self.realm_account.expect("realm_account is not set"), - realm_authority: self.realm_authority.expect("realm_authority is not set"), - council_token_mint: self.council_token_mint, - council_token_holding_account: self.council_token_holding_account, - system_program: self - .system_program - .unwrap_or(solana_address::address!("11111111111111111111111111111111")), - realm_config: self.realm_config.expect("realm_config is not set"), - community_voter_weight_addin_program_id: self.community_voter_weight_addin_program_id, - max_community_voter_weight_addin_program_id: self - .max_community_voter_weight_addin_program_id, - council_voter_weight_addin_program_id: self.council_voter_weight_addin_program_id, - max_council_voter_weight_addin_program_id: self - .max_council_voter_weight_addin_program_id, - payer: self.payer, + realm_account, + realm_authority, + council_token_mint, + council_token_holding_account, + system_program, + realm_config, + community_voter_weight_addin_program_id, + max_community_voter_weight_addin_program_id, + council_voter_weight_addin_program_id, + max_council_voter_weight_addin_program_id, + payer, }; let args = SetRealmConfigInstructionArgs { - config_args: self.config_args.clone().expect("config_args is not set"), + config_args: self.config_args.clone(), }; accounts.instruction_with_remaining_accounts(args, &self.__remaining_accounts) @@ -670,41 +679,32 @@ pub struct SetRealmConfigCpiBuilder<'a, 'b> { } impl<'a, 'b> SetRealmConfigCpiBuilder<'a, 'b> { - pub fn new(program: &'b solana_account_info::AccountInfo<'a>) -> Self { + pub fn new( + __program: &'b solana_account_info::AccountInfo<'a>, + realm_account: &'b solana_account_info::AccountInfo<'a>, + realm_authority: &'b solana_account_info::AccountInfo<'a>, + system_program: &'b solana_account_info::AccountInfo<'a>, + realm_config: &'b solana_account_info::AccountInfo<'a>, + config_args: RealmConfigParams, + ) -> Self { let instruction = Box::new(SetRealmConfigCpiBuilderInstruction { - __program: program, - realm_account: None, - realm_authority: None, + __program, + realm_account, + realm_authority, council_token_mint: None, council_token_holding_account: None, - system_program: None, - realm_config: None, + system_program, + realm_config, community_voter_weight_addin_program_id: None, max_community_voter_weight_addin_program_id: None, council_voter_weight_addin_program_id: None, max_council_voter_weight_addin_program_id: None, payer: None, - config_args: None, + config_args, __remaining_accounts: Vec::new(), }); Self { instruction } } - #[inline(always)] - pub fn realm_account( - &mut self, - realm_account: &'b solana_account_info::AccountInfo<'a>, - ) -> &mut Self { - self.instruction.realm_account = Some(realm_account); - self - } - #[inline(always)] - pub fn realm_authority( - &mut self, - realm_authority: &'b solana_account_info::AccountInfo<'a>, - ) -> &mut Self { - self.instruction.realm_authority = Some(realm_authority); - self - } /// `[optional account]` /// Council Token Mint - optional. /// Note: In the current version it's only possible to remove council mint (set it to None) @@ -728,23 +728,6 @@ impl<'a, 'b> SetRealmConfigCpiBuilder<'a, 'b> { self.instruction.council_token_holding_account = council_token_holding_account; self } - #[inline(always)] - pub fn system_program( - &mut self, - system_program: &'b solana_account_info::AccountInfo<'a>, - ) -> &mut Self { - self.instruction.system_program = Some(system_program); - self - } - /// RealmConfig account. seeds=['realm-config', realm] - #[inline(always)] - pub fn realm_config( - &mut self, - realm_config: &'b solana_account_info::AccountInfo<'a>, - ) -> &mut Self { - self.instruction.realm_config = Some(realm_config); - self - } /// `[optional account]` /// Optional Community Voter Weight Addin Program Id #[inline(always)] @@ -798,11 +781,6 @@ impl<'a, 'b> SetRealmConfigCpiBuilder<'a, 'b> { self.instruction.payer = payer; self } - #[inline(always)] - pub fn config_args(&mut self, config_args: RealmConfigParams) -> &mut Self { - self.instruction.config_args = Some(config_args); - self - } /// Add an additional account to the instruction. #[inline(always)] pub fn add_remaining_account( @@ -838,55 +816,28 @@ impl<'a, 'b> SetRealmConfigCpiBuilder<'a, 'b> { #[allow(clippy::vec_init_then_push)] pub fn invoke_signed(&self, signers_seeds: &[&[&[u8]]]) -> solana_program_error::ProgramResult { let args = SetRealmConfigInstructionArgs { - config_args: self - .instruction - .config_args - .clone() - .expect("config_args is not set"), + config_args: self.instruction.config_args.clone(), }; let instruction = SetRealmConfigCpi { __program: self.instruction.__program, - - realm_account: self - .instruction - .realm_account - .expect("realm_account is not set"), - - realm_authority: self - .instruction - .realm_authority - .expect("realm_authority is not set"), - + realm_account: self.instruction.realm_account, + realm_authority: self.instruction.realm_authority, council_token_mint: self.instruction.council_token_mint, - council_token_holding_account: self.instruction.council_token_holding_account, - - system_program: self - .instruction - .system_program - .expect("system_program is not set"), - - realm_config: self - .instruction - .realm_config - .expect("realm_config is not set"), - + system_program: self.instruction.system_program, + realm_config: self.instruction.realm_config, community_voter_weight_addin_program_id: self .instruction .community_voter_weight_addin_program_id, - max_community_voter_weight_addin_program_id: self .instruction .max_community_voter_weight_addin_program_id, - council_voter_weight_addin_program_id: self .instruction .council_voter_weight_addin_program_id, - max_council_voter_weight_addin_program_id: self .instruction .max_council_voter_weight_addin_program_id, - payer: self.instruction.payer, __args: args, }; @@ -900,18 +851,18 @@ impl<'a, 'b> SetRealmConfigCpiBuilder<'a, 'b> { #[derive(Clone, Debug)] struct SetRealmConfigCpiBuilderInstruction<'a, 'b> { __program: &'b solana_account_info::AccountInfo<'a>, - realm_account: Option<&'b solana_account_info::AccountInfo<'a>>, - realm_authority: Option<&'b solana_account_info::AccountInfo<'a>>, + realm_account: &'b solana_account_info::AccountInfo<'a>, + realm_authority: &'b solana_account_info::AccountInfo<'a>, council_token_mint: Option<&'b solana_account_info::AccountInfo<'a>>, council_token_holding_account: Option<&'b solana_account_info::AccountInfo<'a>>, - system_program: Option<&'b solana_account_info::AccountInfo<'a>>, - realm_config: Option<&'b solana_account_info::AccountInfo<'a>>, + system_program: &'b solana_account_info::AccountInfo<'a>, + realm_config: &'b solana_account_info::AccountInfo<'a>, community_voter_weight_addin_program_id: Option<&'b solana_account_info::AccountInfo<'a>>, max_community_voter_weight_addin_program_id: Option<&'b solana_account_info::AccountInfo<'a>>, council_voter_weight_addin_program_id: Option<&'b solana_account_info::AccountInfo<'a>>, max_council_voter_weight_addin_program_id: Option<&'b solana_account_info::AccountInfo<'a>>, payer: Option<&'b solana_account_info::AccountInfo<'a>>, - config_args: Option, + config_args: RealmConfigParams, /// Additional instruction accounts `(AccountInfo, is_writable, is_signer)`. __remaining_accounts: Vec<(&'b solana_account_info::AccountInfo<'a>, bool, bool)>, } diff --git a/e2e/governance/src/generated/instructions/sign_off_proposal.rs b/e2e/governance/src/generated/instructions/sign_off_proposal.rs index 39e9483..b2eec5d 100644 --- a/e2e/governance/src/generated/instructions/sign_off_proposal.rs +++ b/e2e/governance/src/generated/instructions/sign_off_proposal.rs @@ -98,48 +98,32 @@ impl Default for SignOffProposalInstructionData { /// 2. `[writable]` proposal_account /// 3. `[signer]` signatory_account /// 4. `[writable]` token_owner_record -#[derive(Clone, Debug, Default)] +#[derive(Clone, Debug)] pub struct SignOffProposalBuilder { - realm_account: Option, - governance_account: Option, - proposal_account: Option, - signatory_account: Option, - token_owner_record: Option, + realm_account: solana_address::Address, + governance_account: solana_address::Address, + proposal_account: solana_address::Address, + signatory_account: solana_address::Address, + token_owner_record: solana_address::Address, __remaining_accounts: Vec, } impl SignOffProposalBuilder { - pub fn new() -> Self { - Self::default() - } - #[inline(always)] - pub fn realm_account(&mut self, realm_account: solana_address::Address) -> &mut Self { - self.realm_account = Some(realm_account); - self - } - #[inline(always)] - pub fn governance_account(&mut self, governance_account: solana_address::Address) -> &mut Self { - self.governance_account = Some(governance_account); - self - } - #[inline(always)] - pub fn proposal_account(&mut self, proposal_account: solana_address::Address) -> &mut Self { - self.proposal_account = Some(proposal_account); - self - } - /// Signatory account signing off the Proposal. - /// Or Proposal owner if the owner hasn't appointed any signatories - #[inline(always)] - pub fn signatory_account(&mut self, signatory_account: solana_address::Address) -> &mut Self { - self.signatory_account = Some(signatory_account); - self - } - /// TokenOwnerRecord for the Proposal owner, required when the owner signs off the Proposal. - /// Or `[writable]` SignatoryRecord account, required when non owner signs off the Proposal - #[inline(always)] - pub fn token_owner_record(&mut self, token_owner_record: solana_address::Address) -> &mut Self { - self.token_owner_record = Some(token_owner_record); - self + pub fn new( + realm_account: solana_address::Address, + governance_account: solana_address::Address, + proposal_account: solana_address::Address, + signatory_account: solana_address::Address, + token_owner_record: solana_address::Address, + ) -> Self { + Self { + realm_account, + governance_account, + proposal_account, + signatory_account, + token_owner_record, + __remaining_accounts: Vec::new(), + } } /// Add an additional account to the instruction. #[inline(always)] @@ -158,18 +142,17 @@ impl SignOffProposalBuilder { } #[allow(clippy::clone_on_copy)] pub fn instruction(&self) -> solana_instruction::Instruction { + let realm_account = self.realm_account; + let governance_account = self.governance_account; + let proposal_account = self.proposal_account; + let signatory_account = self.signatory_account; + let token_owner_record = self.token_owner_record; let accounts = SignOffProposal { - realm_account: self.realm_account.expect("realm_account is not set"), - governance_account: self - .governance_account - .expect("governance_account is not set"), - proposal_account: self.proposal_account.expect("proposal_account is not set"), - signatory_account: self - .signatory_account - .expect("signatory_account is not set"), - token_owner_record: self - .token_owner_record - .expect("token_owner_record is not set"), + realm_account, + governance_account, + proposal_account, + signatory_account, + token_owner_record, }; accounts.instruction_with_remaining_accounts(&self.__remaining_accounts) @@ -315,61 +298,24 @@ pub struct SignOffProposalCpiBuilder<'a, 'b> { } impl<'a, 'b> SignOffProposalCpiBuilder<'a, 'b> { - pub fn new(program: &'b solana_account_info::AccountInfo<'a>) -> Self { - let instruction = Box::new(SignOffProposalCpiBuilderInstruction { - __program: program, - realm_account: None, - governance_account: None, - proposal_account: None, - signatory_account: None, - token_owner_record: None, - __remaining_accounts: Vec::new(), - }); - Self { instruction } - } - #[inline(always)] - pub fn realm_account( - &mut self, + pub fn new( + __program: &'b solana_account_info::AccountInfo<'a>, realm_account: &'b solana_account_info::AccountInfo<'a>, - ) -> &mut Self { - self.instruction.realm_account = Some(realm_account); - self - } - #[inline(always)] - pub fn governance_account( - &mut self, governance_account: &'b solana_account_info::AccountInfo<'a>, - ) -> &mut Self { - self.instruction.governance_account = Some(governance_account); - self - } - #[inline(always)] - pub fn proposal_account( - &mut self, proposal_account: &'b solana_account_info::AccountInfo<'a>, - ) -> &mut Self { - self.instruction.proposal_account = Some(proposal_account); - self - } - /// Signatory account signing off the Proposal. - /// Or Proposal owner if the owner hasn't appointed any signatories - #[inline(always)] - pub fn signatory_account( - &mut self, signatory_account: &'b solana_account_info::AccountInfo<'a>, - ) -> &mut Self { - self.instruction.signatory_account = Some(signatory_account); - self - } - /// TokenOwnerRecord for the Proposal owner, required when the owner signs off the Proposal. - /// Or `[writable]` SignatoryRecord account, required when non owner signs off the Proposal - #[inline(always)] - pub fn token_owner_record( - &mut self, token_owner_record: &'b solana_account_info::AccountInfo<'a>, - ) -> &mut Self { - self.instruction.token_owner_record = Some(token_owner_record); - self + ) -> Self { + let instruction = Box::new(SignOffProposalCpiBuilderInstruction { + __program, + realm_account, + governance_account, + proposal_account, + signatory_account, + token_owner_record, + __remaining_accounts: Vec::new(), + }); + Self { instruction } } /// Add an additional account to the instruction. #[inline(always)] @@ -407,31 +353,11 @@ impl<'a, 'b> SignOffProposalCpiBuilder<'a, 'b> { pub fn invoke_signed(&self, signers_seeds: &[&[&[u8]]]) -> solana_program_error::ProgramResult { let instruction = SignOffProposalCpi { __program: self.instruction.__program, - - realm_account: self - .instruction - .realm_account - .expect("realm_account is not set"), - - governance_account: self - .instruction - .governance_account - .expect("governance_account is not set"), - - proposal_account: self - .instruction - .proposal_account - .expect("proposal_account is not set"), - - signatory_account: self - .instruction - .signatory_account - .expect("signatory_account is not set"), - - token_owner_record: self - .instruction - .token_owner_record - .expect("token_owner_record is not set"), + realm_account: self.instruction.realm_account, + governance_account: self.instruction.governance_account, + proposal_account: self.instruction.proposal_account, + signatory_account: self.instruction.signatory_account, + token_owner_record: self.instruction.token_owner_record, }; instruction.invoke_signed_with_remaining_accounts( signers_seeds, @@ -443,11 +369,11 @@ impl<'a, 'b> SignOffProposalCpiBuilder<'a, 'b> { #[derive(Clone, Debug)] struct SignOffProposalCpiBuilderInstruction<'a, 'b> { __program: &'b solana_account_info::AccountInfo<'a>, - realm_account: Option<&'b solana_account_info::AccountInfo<'a>>, - governance_account: Option<&'b solana_account_info::AccountInfo<'a>>, - proposal_account: Option<&'b solana_account_info::AccountInfo<'a>>, - signatory_account: Option<&'b solana_account_info::AccountInfo<'a>>, - token_owner_record: Option<&'b solana_account_info::AccountInfo<'a>>, + realm_account: &'b solana_account_info::AccountInfo<'a>, + governance_account: &'b solana_account_info::AccountInfo<'a>, + proposal_account: &'b solana_account_info::AccountInfo<'a>, + signatory_account: &'b solana_account_info::AccountInfo<'a>, + token_owner_record: &'b solana_account_info::AccountInfo<'a>, /// Additional instruction accounts `(AccountInfo, is_writable, is_signer)`. __remaining_accounts: Vec<(&'b solana_account_info::AccountInfo<'a>, bool, bool)>, } diff --git a/e2e/governance/src/generated/instructions/update_program_metadata.rs b/e2e/governance/src/generated/instructions/update_program_metadata.rs index 54a07c4..9b342d9 100644 --- a/e2e/governance/src/generated/instructions/update_program_metadata.rs +++ b/e2e/governance/src/generated/instructions/update_program_metadata.rs @@ -84,31 +84,25 @@ impl Default for UpdateProgramMetadataInstructionData { /// 0. `[writable]` program_metadata_account /// 1. `[signer]` payer /// 2. `[optional]` system_program (default to `11111111111111111111111111111111`) -#[derive(Clone, Debug, Default)] +#[derive(Clone, Debug)] pub struct UpdateProgramMetadataBuilder { - program_metadata_account: Option, - payer: Option, + program_metadata_account: solana_address::Address, + payer: solana_address::Address, system_program: Option, __remaining_accounts: Vec, } impl UpdateProgramMetadataBuilder { - pub fn new() -> Self { - Self::default() - } - /// seeds=['metadata'] - #[inline(always)] - pub fn program_metadata_account( - &mut self, + pub fn new( program_metadata_account: solana_address::Address, - ) -> &mut Self { - self.program_metadata_account = Some(program_metadata_account); - self - } - #[inline(always)] - pub fn payer(&mut self, payer: solana_address::Address) -> &mut Self { - self.payer = Some(payer); - self + payer: solana_address::Address, + ) -> Self { + Self { + program_metadata_account, + payer, + system_program: None, + __remaining_accounts: Vec::new(), + } } /// `[optional account, default to '11111111111111111111111111111111']` #[inline(always)] @@ -133,14 +127,15 @@ impl UpdateProgramMetadataBuilder { } #[allow(clippy::clone_on_copy)] pub fn instruction(&self) -> solana_instruction::Instruction { + let program_metadata_account = self.program_metadata_account; + let payer = self.payer; + let system_program = self + .system_program + .unwrap_or(solana_address::address!("11111111111111111111111111111111")); let accounts = UpdateProgramMetadata { - program_metadata_account: self - .program_metadata_account - .expect("program_metadata_account is not set"), - payer: self.payer.expect("payer is not set"), - system_program: self - .system_program - .unwrap_or(solana_address::address!("11111111111111111111111111111111")), + program_metadata_account, + payer, + system_program, }; accounts.instruction_with_remaining_accounts(&self.__remaining_accounts) @@ -263,38 +258,21 @@ pub struct UpdateProgramMetadataCpiBuilder<'a, 'b> { } impl<'a, 'b> UpdateProgramMetadataCpiBuilder<'a, 'b> { - pub fn new(program: &'b solana_account_info::AccountInfo<'a>) -> Self { + pub fn new( + __program: &'b solana_account_info::AccountInfo<'a>, + program_metadata_account: &'b solana_account_info::AccountInfo<'a>, + payer: &'b solana_account_info::AccountInfo<'a>, + system_program: &'b solana_account_info::AccountInfo<'a>, + ) -> Self { let instruction = Box::new(UpdateProgramMetadataCpiBuilderInstruction { - __program: program, - program_metadata_account: None, - payer: None, - system_program: None, + __program, + program_metadata_account, + payer, + system_program, __remaining_accounts: Vec::new(), }); Self { instruction } } - /// seeds=['metadata'] - #[inline(always)] - pub fn program_metadata_account( - &mut self, - program_metadata_account: &'b solana_account_info::AccountInfo<'a>, - ) -> &mut Self { - self.instruction.program_metadata_account = Some(program_metadata_account); - self - } - #[inline(always)] - pub fn payer(&mut self, payer: &'b solana_account_info::AccountInfo<'a>) -> &mut Self { - self.instruction.payer = Some(payer); - self - } - #[inline(always)] - pub fn system_program( - &mut self, - system_program: &'b solana_account_info::AccountInfo<'a>, - ) -> &mut Self { - self.instruction.system_program = Some(system_program); - self - } /// Add an additional account to the instruction. #[inline(always)] pub fn add_remaining_account( @@ -331,18 +309,9 @@ impl<'a, 'b> UpdateProgramMetadataCpiBuilder<'a, 'b> { pub fn invoke_signed(&self, signers_seeds: &[&[&[u8]]]) -> solana_program_error::ProgramResult { let instruction = UpdateProgramMetadataCpi { __program: self.instruction.__program, - - program_metadata_account: self - .instruction - .program_metadata_account - .expect("program_metadata_account is not set"), - - payer: self.instruction.payer.expect("payer is not set"), - - system_program: self - .instruction - .system_program - .expect("system_program is not set"), + program_metadata_account: self.instruction.program_metadata_account, + payer: self.instruction.payer, + system_program: self.instruction.system_program, }; instruction.invoke_signed_with_remaining_accounts( signers_seeds, @@ -354,9 +323,9 @@ impl<'a, 'b> UpdateProgramMetadataCpiBuilder<'a, 'b> { #[derive(Clone, Debug)] struct UpdateProgramMetadataCpiBuilderInstruction<'a, 'b> { __program: &'b solana_account_info::AccountInfo<'a>, - program_metadata_account: Option<&'b solana_account_info::AccountInfo<'a>>, - payer: Option<&'b solana_account_info::AccountInfo<'a>>, - system_program: Option<&'b solana_account_info::AccountInfo<'a>>, + program_metadata_account: &'b solana_account_info::AccountInfo<'a>, + payer: &'b solana_account_info::AccountInfo<'a>, + system_program: &'b solana_account_info::AccountInfo<'a>, /// Additional instruction accounts `(AccountInfo, is_writable, is_signer)`. __remaining_accounts: Vec<(&'b solana_account_info::AccountInfo<'a>, bool, bool)>, } diff --git a/e2e/governance/src/generated/instructions/withdraw_governing_tokens.rs b/e2e/governance/src/generated/instructions/withdraw_governing_tokens.rs index 8a2cbe0..38e7ea3 100644 --- a/e2e/governance/src/generated/instructions/withdraw_governing_tokens.rs +++ b/e2e/governance/src/generated/instructions/withdraw_governing_tokens.rs @@ -112,58 +112,37 @@ impl Default for WithdrawGoverningTokensInstructionData { /// 4. `[writable]` token_owner_record /// 5. `[optional]` token_program (default to `TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA`) /// 6. `[]` realm_config_account -#[derive(Clone, Debug, Default)] +#[derive(Clone, Debug)] pub struct WithdrawGoverningTokensBuilder { - realm_account: Option, - governing_token_holding_account: Option, - governing_token_destination_account: Option, - governing_token_owner_account: Option, - token_owner_record: Option, + realm_account: solana_address::Address, + governing_token_holding_account: solana_address::Address, + governing_token_destination_account: solana_address::Address, + governing_token_owner_account: solana_address::Address, + token_owner_record: solana_address::Address, token_program: Option, - realm_config_account: Option, + realm_config_account: solana_address::Address, __remaining_accounts: Vec, } impl WithdrawGoverningTokensBuilder { - pub fn new() -> Self { - Self::default() - } - #[inline(always)] - pub fn realm_account(&mut self, realm_account: solana_address::Address) -> &mut Self { - self.realm_account = Some(realm_account); - self - } - /// seeds=['governance', realm, governing_token_mint] - #[inline(always)] - pub fn governing_token_holding_account( - &mut self, + pub fn new( + realm_account: solana_address::Address, governing_token_holding_account: solana_address::Address, - ) -> &mut Self { - self.governing_token_holding_account = Some(governing_token_holding_account); - self - } - /// All tokens will be transferred to this account - #[inline(always)] - pub fn governing_token_destination_account( - &mut self, governing_token_destination_account: solana_address::Address, - ) -> &mut Self { - self.governing_token_destination_account = Some(governing_token_destination_account); - self - } - #[inline(always)] - pub fn governing_token_owner_account( - &mut self, governing_token_owner_account: solana_address::Address, - ) -> &mut Self { - self.governing_token_owner_account = Some(governing_token_owner_account); - self - } - /// seeds=['governance',realm, governing_token_mint, governing_token_owner] - #[inline(always)] - pub fn token_owner_record(&mut self, token_owner_record: solana_address::Address) -> &mut Self { - self.token_owner_record = Some(token_owner_record); - self + token_owner_record: solana_address::Address, + realm_config_account: solana_address::Address, + ) -> Self { + Self { + realm_account, + governing_token_holding_account, + governing_token_destination_account, + governing_token_owner_account, + token_owner_record, + token_program: None, + realm_config_account, + __remaining_accounts: Vec::new(), + } } /// `[optional account, default to 'TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA']` #[inline(always)] @@ -171,15 +150,6 @@ impl WithdrawGoverningTokensBuilder { self.token_program = Some(token_program); self } - /// seeds=['realm-config', realm] - #[inline(always)] - pub fn realm_config_account( - &mut self, - realm_config_account: solana_address::Address, - ) -> &mut Self { - self.realm_config_account = Some(realm_config_account); - self - } /// Add an additional account to the instruction. #[inline(always)] pub fn add_remaining_account(&mut self, account: solana_instruction::AccountMeta) -> &mut Self { @@ -197,26 +167,23 @@ impl WithdrawGoverningTokensBuilder { } #[allow(clippy::clone_on_copy)] pub fn instruction(&self) -> solana_instruction::Instruction { + let realm_account = self.realm_account; + let governing_token_holding_account = self.governing_token_holding_account; + let governing_token_destination_account = self.governing_token_destination_account; + let governing_token_owner_account = self.governing_token_owner_account; + let token_owner_record = self.token_owner_record; + let token_program = self.token_program.unwrap_or(solana_address::address!( + "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA" + )); + let realm_config_account = self.realm_config_account; let accounts = WithdrawGoverningTokens { - realm_account: self.realm_account.expect("realm_account is not set"), - governing_token_holding_account: self - .governing_token_holding_account - .expect("governing_token_holding_account is not set"), - governing_token_destination_account: self - .governing_token_destination_account - .expect("governing_token_destination_account is not set"), - governing_token_owner_account: self - .governing_token_owner_account - .expect("governing_token_owner_account is not set"), - token_owner_record: self - .token_owner_record - .expect("token_owner_record is not set"), - token_program: self.token_program.unwrap_or(solana_address::address!( - "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA" - )), - realm_config_account: self - .realm_config_account - .expect("realm_config_account is not set"), + realm_account, + governing_token_holding_account, + governing_token_destination_account, + governing_token_owner_account, + token_owner_record, + token_program, + realm_config_account, }; accounts.instruction_with_remaining_accounts(&self.__remaining_accounts) @@ -382,80 +349,28 @@ pub struct WithdrawGoverningTokensCpiBuilder<'a, 'b> { } impl<'a, 'b> WithdrawGoverningTokensCpiBuilder<'a, 'b> { - pub fn new(program: &'b solana_account_info::AccountInfo<'a>) -> Self { - let instruction = Box::new(WithdrawGoverningTokensCpiBuilderInstruction { - __program: program, - realm_account: None, - governing_token_holding_account: None, - governing_token_destination_account: None, - governing_token_owner_account: None, - token_owner_record: None, - token_program: None, - realm_config_account: None, - __remaining_accounts: Vec::new(), - }); - Self { instruction } - } - #[inline(always)] - pub fn realm_account( - &mut self, + pub fn new( + __program: &'b solana_account_info::AccountInfo<'a>, realm_account: &'b solana_account_info::AccountInfo<'a>, - ) -> &mut Self { - self.instruction.realm_account = Some(realm_account); - self - } - /// seeds=['governance', realm, governing_token_mint] - #[inline(always)] - pub fn governing_token_holding_account( - &mut self, governing_token_holding_account: &'b solana_account_info::AccountInfo<'a>, - ) -> &mut Self { - self.instruction.governing_token_holding_account = Some(governing_token_holding_account); - self - } - /// All tokens will be transferred to this account - #[inline(always)] - pub fn governing_token_destination_account( - &mut self, governing_token_destination_account: &'b solana_account_info::AccountInfo<'a>, - ) -> &mut Self { - self.instruction.governing_token_destination_account = - Some(governing_token_destination_account); - self - } - #[inline(always)] - pub fn governing_token_owner_account( - &mut self, governing_token_owner_account: &'b solana_account_info::AccountInfo<'a>, - ) -> &mut Self { - self.instruction.governing_token_owner_account = Some(governing_token_owner_account); - self - } - /// seeds=['governance',realm, governing_token_mint, governing_token_owner] - #[inline(always)] - pub fn token_owner_record( - &mut self, token_owner_record: &'b solana_account_info::AccountInfo<'a>, - ) -> &mut Self { - self.instruction.token_owner_record = Some(token_owner_record); - self - } - #[inline(always)] - pub fn token_program( - &mut self, token_program: &'b solana_account_info::AccountInfo<'a>, - ) -> &mut Self { - self.instruction.token_program = Some(token_program); - self - } - /// seeds=['realm-config', realm] - #[inline(always)] - pub fn realm_config_account( - &mut self, realm_config_account: &'b solana_account_info::AccountInfo<'a>, - ) -> &mut Self { - self.instruction.realm_config_account = Some(realm_config_account); - self + ) -> Self { + let instruction = Box::new(WithdrawGoverningTokensCpiBuilderInstruction { + __program, + realm_account, + governing_token_holding_account, + governing_token_destination_account, + governing_token_owner_account, + token_owner_record, + token_program, + realm_config_account, + __remaining_accounts: Vec::new(), + }); + Self { instruction } } /// Add an additional account to the instruction. #[inline(always)] @@ -493,41 +408,15 @@ impl<'a, 'b> WithdrawGoverningTokensCpiBuilder<'a, 'b> { pub fn invoke_signed(&self, signers_seeds: &[&[&[u8]]]) -> solana_program_error::ProgramResult { let instruction = WithdrawGoverningTokensCpi { __program: self.instruction.__program, - - realm_account: self - .instruction - .realm_account - .expect("realm_account is not set"), - - governing_token_holding_account: self - .instruction - .governing_token_holding_account - .expect("governing_token_holding_account is not set"), - + realm_account: self.instruction.realm_account, + governing_token_holding_account: self.instruction.governing_token_holding_account, governing_token_destination_account: self .instruction - .governing_token_destination_account - .expect("governing_token_destination_account is not set"), - - governing_token_owner_account: self - .instruction - .governing_token_owner_account - .expect("governing_token_owner_account is not set"), - - token_owner_record: self - .instruction - .token_owner_record - .expect("token_owner_record is not set"), - - token_program: self - .instruction - .token_program - .expect("token_program is not set"), - - realm_config_account: self - .instruction - .realm_config_account - .expect("realm_config_account is not set"), + .governing_token_destination_account, + governing_token_owner_account: self.instruction.governing_token_owner_account, + token_owner_record: self.instruction.token_owner_record, + token_program: self.instruction.token_program, + realm_config_account: self.instruction.realm_config_account, }; instruction.invoke_signed_with_remaining_accounts( signers_seeds, @@ -539,13 +428,13 @@ impl<'a, 'b> WithdrawGoverningTokensCpiBuilder<'a, 'b> { #[derive(Clone, Debug)] struct WithdrawGoverningTokensCpiBuilderInstruction<'a, 'b> { __program: &'b solana_account_info::AccountInfo<'a>, - realm_account: Option<&'b solana_account_info::AccountInfo<'a>>, - governing_token_holding_account: Option<&'b solana_account_info::AccountInfo<'a>>, - governing_token_destination_account: Option<&'b solana_account_info::AccountInfo<'a>>, - governing_token_owner_account: Option<&'b solana_account_info::AccountInfo<'a>>, - token_owner_record: Option<&'b solana_account_info::AccountInfo<'a>>, - token_program: Option<&'b solana_account_info::AccountInfo<'a>>, - realm_config_account: Option<&'b solana_account_info::AccountInfo<'a>>, + realm_account: &'b solana_account_info::AccountInfo<'a>, + governing_token_holding_account: &'b solana_account_info::AccountInfo<'a>, + governing_token_destination_account: &'b solana_account_info::AccountInfo<'a>, + governing_token_owner_account: &'b solana_account_info::AccountInfo<'a>, + token_owner_record: &'b solana_account_info::AccountInfo<'a>, + token_program: &'b solana_account_info::AccountInfo<'a>, + realm_config_account: &'b solana_account_info::AccountInfo<'a>, /// Additional instruction accounts `(AccountInfo, is_writable, is_signer)`. __remaining_accounts: Vec<(&'b solana_account_info::AccountInfo<'a>, bool, bool)>, } diff --git a/e2e/memo/src/generated/instructions/add_memo.rs b/e2e/memo/src/generated/instructions/add_memo.rs index ab0460e..e9a31c5 100644 --- a/e2e/memo/src/generated/instructions/add_memo.rs +++ b/e2e/memo/src/generated/instructions/add_memo.rs @@ -72,20 +72,18 @@ impl AddMemoInstructionArgs { /// /// ### Accounts: /// -#[derive(Clone, Debug, Default)] +#[derive(Clone, Debug)] pub struct AddMemoBuilder { - memo: Option, + memo: TrailingStr, __remaining_accounts: Vec, } impl AddMemoBuilder { - pub fn new() -> Self { - Self::default() - } - #[inline(always)] - pub fn memo(&mut self, memo: TrailingStr) -> &mut Self { - self.memo = Some(memo); - self + pub fn new(memo: TrailingStr) -> Self { + Self { + memo, + __remaining_accounts: Vec::new(), + } } /// Add an additional account to the instruction. #[inline(always)] @@ -106,7 +104,7 @@ impl AddMemoBuilder { pub fn instruction(&self) -> solana_instruction::Instruction { let accounts = AddMemo {}; let args = AddMemoInstructionArgs { - memo: self.memo.clone().expect("memo is not set"), + memo: self.memo.clone(), }; accounts.instruction_with_remaining_accounts(args, &self.__remaining_accounts) @@ -195,19 +193,14 @@ pub struct AddMemoCpiBuilder<'a, 'b> { } impl<'a, 'b> AddMemoCpiBuilder<'a, 'b> { - pub fn new(program: &'b solana_account_info::AccountInfo<'a>) -> Self { + pub fn new(__program: &'b solana_account_info::AccountInfo<'a>, memo: TrailingStr) -> Self { let instruction = Box::new(AddMemoCpiBuilderInstruction { - __program: program, - memo: None, + __program, + memo, __remaining_accounts: Vec::new(), }); Self { instruction } } - #[inline(always)] - pub fn memo(&mut self, memo: TrailingStr) -> &mut Self { - self.instruction.memo = Some(memo); - self - } /// Add an additional account to the instruction. #[inline(always)] pub fn add_remaining_account( @@ -243,7 +236,7 @@ impl<'a, 'b> AddMemoCpiBuilder<'a, 'b> { #[allow(clippy::vec_init_then_push)] pub fn invoke_signed(&self, signers_seeds: &[&[&[u8]]]) -> solana_program_error::ProgramResult { let args = AddMemoInstructionArgs { - memo: self.instruction.memo.clone().expect("memo is not set"), + memo: self.instruction.memo.clone(), }; let instruction = AddMemoCpi { __program: self.instruction.__program, @@ -259,7 +252,7 @@ impl<'a, 'b> AddMemoCpiBuilder<'a, 'b> { #[derive(Clone, Debug)] struct AddMemoCpiBuilderInstruction<'a, 'b> { __program: &'b solana_account_info::AccountInfo<'a>, - memo: Option, + memo: TrailingStr, /// Additional instruction accounts `(AccountInfo, is_writable, is_signer)`. __remaining_accounts: Vec<(&'b solana_account_info::AccountInfo<'a>, bool, bool)>, } diff --git a/e2e/system/src/generated/instructions/advance_nonce_account.rs b/e2e/system/src/generated/instructions/advance_nonce_account.rs index 4858fa9..d2e6417 100644 --- a/e2e/system/src/generated/instructions/advance_nonce_account.rs +++ b/e2e/system/src/generated/instructions/advance_nonce_account.rs @@ -84,22 +84,25 @@ impl Default for AdvanceNonceAccountInstructionData { /// 0. `[writable]` nonce_account /// 1. `[optional]` recent_blockhashes_sysvar (default to `SysvarRecentB1ockHashes11111111111111111111`) /// 2. `[signer]` nonce_authority -#[derive(Clone, Debug, Default)] +#[derive(Clone, Debug)] pub struct AdvanceNonceAccountBuilder { - nonce_account: Option, + nonce_account: solana_address::Address, recent_blockhashes_sysvar: Option, - nonce_authority: Option, + nonce_authority: solana_address::Address, __remaining_accounts: Vec, } impl AdvanceNonceAccountBuilder { - pub fn new() -> Self { - Self::default() - } - #[inline(always)] - pub fn nonce_account(&mut self, nonce_account: solana_address::Address) -> &mut Self { - self.nonce_account = Some(nonce_account); - self + pub fn new( + nonce_account: solana_address::Address, + nonce_authority: solana_address::Address, + ) -> Self { + Self { + nonce_account, + recent_blockhashes_sysvar: None, + nonce_authority, + __remaining_accounts: Vec::new(), + } } /// `[optional account, default to 'SysvarRecentB1ockHashes11111111111111111111']` #[inline(always)] @@ -110,11 +113,6 @@ impl AdvanceNonceAccountBuilder { self.recent_blockhashes_sysvar = Some(recent_blockhashes_sysvar); self } - #[inline(always)] - pub fn nonce_authority(&mut self, nonce_authority: solana_address::Address) -> &mut Self { - self.nonce_authority = Some(nonce_authority); - self - } /// Add an additional account to the instruction. #[inline(always)] pub fn add_remaining_account(&mut self, account: solana_instruction::AccountMeta) -> &mut Self { @@ -132,12 +130,17 @@ impl AdvanceNonceAccountBuilder { } #[allow(clippy::clone_on_copy)] pub fn instruction(&self) -> solana_instruction::Instruction { + let nonce_account = self.nonce_account; + let recent_blockhashes_sysvar = + self.recent_blockhashes_sysvar + .unwrap_or(solana_address::address!( + "SysvarRecentB1ockHashes11111111111111111111" + )); + let nonce_authority = self.nonce_authority; let accounts = AdvanceNonceAccount { - nonce_account: self.nonce_account.expect("nonce_account is not set"), - recent_blockhashes_sysvar: self.recent_blockhashes_sysvar.unwrap_or( - solana_address::address!("SysvarRecentB1ockHashes11111111111111111111"), - ), - nonce_authority: self.nonce_authority.expect("nonce_authority is not set"), + nonce_account, + recent_blockhashes_sysvar, + nonce_authority, }; accounts.instruction_with_remaining_accounts(&self.__remaining_accounts) @@ -259,40 +262,21 @@ pub struct AdvanceNonceAccountCpiBuilder<'a, 'b> { } impl<'a, 'b> AdvanceNonceAccountCpiBuilder<'a, 'b> { - pub fn new(program: &'b solana_account_info::AccountInfo<'a>) -> Self { + pub fn new( + __program: &'b solana_account_info::AccountInfo<'a>, + nonce_account: &'b solana_account_info::AccountInfo<'a>, + recent_blockhashes_sysvar: &'b solana_account_info::AccountInfo<'a>, + nonce_authority: &'b solana_account_info::AccountInfo<'a>, + ) -> Self { let instruction = Box::new(AdvanceNonceAccountCpiBuilderInstruction { - __program: program, - nonce_account: None, - recent_blockhashes_sysvar: None, - nonce_authority: None, + __program, + nonce_account, + recent_blockhashes_sysvar, + nonce_authority, __remaining_accounts: Vec::new(), }); Self { instruction } } - #[inline(always)] - pub fn nonce_account( - &mut self, - nonce_account: &'b solana_account_info::AccountInfo<'a>, - ) -> &mut Self { - self.instruction.nonce_account = Some(nonce_account); - self - } - #[inline(always)] - pub fn recent_blockhashes_sysvar( - &mut self, - recent_blockhashes_sysvar: &'b solana_account_info::AccountInfo<'a>, - ) -> &mut Self { - self.instruction.recent_blockhashes_sysvar = Some(recent_blockhashes_sysvar); - self - } - #[inline(always)] - pub fn nonce_authority( - &mut self, - nonce_authority: &'b solana_account_info::AccountInfo<'a>, - ) -> &mut Self { - self.instruction.nonce_authority = Some(nonce_authority); - self - } /// Add an additional account to the instruction. #[inline(always)] pub fn add_remaining_account( @@ -329,21 +313,9 @@ impl<'a, 'b> AdvanceNonceAccountCpiBuilder<'a, 'b> { pub fn invoke_signed(&self, signers_seeds: &[&[&[u8]]]) -> solana_program_error::ProgramResult { let instruction = AdvanceNonceAccountCpi { __program: self.instruction.__program, - - nonce_account: self - .instruction - .nonce_account - .expect("nonce_account is not set"), - - recent_blockhashes_sysvar: self - .instruction - .recent_blockhashes_sysvar - .expect("recent_blockhashes_sysvar is not set"), - - nonce_authority: self - .instruction - .nonce_authority - .expect("nonce_authority is not set"), + nonce_account: self.instruction.nonce_account, + recent_blockhashes_sysvar: self.instruction.recent_blockhashes_sysvar, + nonce_authority: self.instruction.nonce_authority, }; instruction.invoke_signed_with_remaining_accounts( signers_seeds, @@ -355,9 +327,9 @@ impl<'a, 'b> AdvanceNonceAccountCpiBuilder<'a, 'b> { #[derive(Clone, Debug)] struct AdvanceNonceAccountCpiBuilderInstruction<'a, 'b> { __program: &'b solana_account_info::AccountInfo<'a>, - nonce_account: Option<&'b solana_account_info::AccountInfo<'a>>, - recent_blockhashes_sysvar: Option<&'b solana_account_info::AccountInfo<'a>>, - nonce_authority: Option<&'b solana_account_info::AccountInfo<'a>>, + nonce_account: &'b solana_account_info::AccountInfo<'a>, + recent_blockhashes_sysvar: &'b solana_account_info::AccountInfo<'a>, + nonce_authority: &'b solana_account_info::AccountInfo<'a>, /// Additional instruction accounts `(AccountInfo, is_writable, is_signer)`. __remaining_accounts: Vec<(&'b solana_account_info::AccountInfo<'a>, bool, bool)>, } diff --git a/e2e/system/src/generated/instructions/allocate.rs b/e2e/system/src/generated/instructions/allocate.rs index ef7989f..9f95141 100644 --- a/e2e/system/src/generated/instructions/allocate.rs +++ b/e2e/system/src/generated/instructions/allocate.rs @@ -79,26 +79,20 @@ impl AllocateInstructionArgs { /// ### Accounts: /// /// 0. `[writable, signer]` new_account -#[derive(Clone, Debug, Default)] +#[derive(Clone, Debug)] pub struct AllocateBuilder { - new_account: Option, - space: Option, + new_account: solana_address::Address, + space: u64, __remaining_accounts: Vec, } impl AllocateBuilder { - pub fn new() -> Self { - Self::default() - } - #[inline(always)] - pub fn new_account(&mut self, new_account: solana_address::Address) -> &mut Self { - self.new_account = Some(new_account); - self - } - #[inline(always)] - pub fn space(&mut self, space: u64) -> &mut Self { - self.space = Some(space); - self + pub fn new(new_account: solana_address::Address, space: u64) -> Self { + Self { + new_account, + space, + __remaining_accounts: Vec::new(), + } } /// Add an additional account to the instruction. #[inline(always)] @@ -117,11 +111,10 @@ impl AllocateBuilder { } #[allow(clippy::clone_on_copy)] pub fn instruction(&self) -> solana_instruction::Instruction { - let accounts = Allocate { - new_account: self.new_account.expect("new_account is not set"), - }; + let new_account = self.new_account; + let accounts = Allocate { new_account }; let args = AllocateInstructionArgs { - space: self.space.clone().expect("space is not set"), + space: self.space.clone(), }; accounts.instruction_with_remaining_accounts(args, &self.__remaining_accounts) @@ -225,28 +218,19 @@ pub struct AllocateCpiBuilder<'a, 'b> { } impl<'a, 'b> AllocateCpiBuilder<'a, 'b> { - pub fn new(program: &'b solana_account_info::AccountInfo<'a>) -> Self { + pub fn new( + __program: &'b solana_account_info::AccountInfo<'a>, + new_account: &'b solana_account_info::AccountInfo<'a>, + space: u64, + ) -> Self { let instruction = Box::new(AllocateCpiBuilderInstruction { - __program: program, - new_account: None, - space: None, + __program, + new_account, + space, __remaining_accounts: Vec::new(), }); Self { instruction } } - #[inline(always)] - pub fn new_account( - &mut self, - new_account: &'b solana_account_info::AccountInfo<'a>, - ) -> &mut Self { - self.instruction.new_account = Some(new_account); - self - } - #[inline(always)] - pub fn space(&mut self, space: u64) -> &mut Self { - self.instruction.space = Some(space); - self - } /// Add an additional account to the instruction. #[inline(always)] pub fn add_remaining_account( @@ -282,15 +266,11 @@ impl<'a, 'b> AllocateCpiBuilder<'a, 'b> { #[allow(clippy::vec_init_then_push)] pub fn invoke_signed(&self, signers_seeds: &[&[&[u8]]]) -> solana_program_error::ProgramResult { let args = AllocateInstructionArgs { - space: self.instruction.space.clone().expect("space is not set"), + space: self.instruction.space.clone(), }; let instruction = AllocateCpi { __program: self.instruction.__program, - - new_account: self - .instruction - .new_account - .expect("new_account is not set"), + new_account: self.instruction.new_account, __args: args, }; instruction.invoke_signed_with_remaining_accounts( @@ -303,8 +283,8 @@ impl<'a, 'b> AllocateCpiBuilder<'a, 'b> { #[derive(Clone, Debug)] struct AllocateCpiBuilderInstruction<'a, 'b> { __program: &'b solana_account_info::AccountInfo<'a>, - new_account: Option<&'b solana_account_info::AccountInfo<'a>>, - space: Option, + new_account: &'b solana_account_info::AccountInfo<'a>, + space: u64, /// Additional instruction accounts `(AccountInfo, is_writable, is_signer)`. __remaining_accounts: Vec<(&'b solana_account_info::AccountInfo<'a>, bool, bool)>, } diff --git a/e2e/system/src/generated/instructions/allocate_with_seed.rs b/e2e/system/src/generated/instructions/allocate_with_seed.rs index 0064540..48a3208 100644 --- a/e2e/system/src/generated/instructions/allocate_with_seed.rs +++ b/e2e/system/src/generated/instructions/allocate_with_seed.rs @@ -96,50 +96,35 @@ impl AllocateWithSeedInstructionArgs { /// /// 0. `[writable]` new_account /// 1. `[signer]` base_account -#[derive(Clone, Debug, Default)] +#[derive(Clone, Debug)] pub struct AllocateWithSeedBuilder { - new_account: Option, - base_account: Option, - base: Option
, - seed: Option, - space: Option, - program_address: Option
, + new_account: solana_address::Address, + base_account: solana_address::Address, + base: Address, + seed: String, + space: u64, + program_address: Address, __remaining_accounts: Vec, } impl AllocateWithSeedBuilder { - pub fn new() -> Self { - Self::default() - } - #[inline(always)] - pub fn new_account(&mut self, new_account: solana_address::Address) -> &mut Self { - self.new_account = Some(new_account); - self - } - #[inline(always)] - pub fn base_account(&mut self, base_account: solana_address::Address) -> &mut Self { - self.base_account = Some(base_account); - self - } - #[inline(always)] - pub fn base(&mut self, base: Address) -> &mut Self { - self.base = Some(base); - self - } - #[inline(always)] - pub fn seed(&mut self, seed: String) -> &mut Self { - self.seed = Some(seed); - self - } - #[inline(always)] - pub fn space(&mut self, space: u64) -> &mut Self { - self.space = Some(space); - self - } - #[inline(always)] - pub fn program_address(&mut self, program_address: Address) -> &mut Self { - self.program_address = Some(program_address); - self + pub fn new( + new_account: solana_address::Address, + base_account: solana_address::Address, + base: Address, + seed: String, + space: u64, + program_address: Address, + ) -> Self { + Self { + new_account, + base_account, + base, + seed, + space, + program_address, + __remaining_accounts: Vec::new(), + } } /// Add an additional account to the instruction. #[inline(always)] @@ -158,18 +143,17 @@ impl AllocateWithSeedBuilder { } #[allow(clippy::clone_on_copy)] pub fn instruction(&self) -> solana_instruction::Instruction { + let new_account = self.new_account; + let base_account = self.base_account; let accounts = AllocateWithSeed { - new_account: self.new_account.expect("new_account is not set"), - base_account: self.base_account.expect("base_account is not set"), + new_account, + base_account, }; let args = AllocateWithSeedInstructionArgs { - base: self.base.clone().expect("base is not set"), - seed: self.seed.clone().expect("seed is not set"), - space: self.space.clone().expect("space is not set"), - program_address: self - .program_address - .clone() - .expect("program_address is not set"), + base: self.base.clone(), + seed: self.seed.clone(), + space: self.space.clone(), + program_address: self.program_address.clone(), }; accounts.instruction_with_remaining_accounts(args, &self.__remaining_accounts) @@ -284,55 +268,27 @@ pub struct AllocateWithSeedCpiBuilder<'a, 'b> { } impl<'a, 'b> AllocateWithSeedCpiBuilder<'a, 'b> { - pub fn new(program: &'b solana_account_info::AccountInfo<'a>) -> Self { + pub fn new( + __program: &'b solana_account_info::AccountInfo<'a>, + new_account: &'b solana_account_info::AccountInfo<'a>, + base_account: &'b solana_account_info::AccountInfo<'a>, + base: Address, + seed: String, + space: u64, + program_address: Address, + ) -> Self { let instruction = Box::new(AllocateWithSeedCpiBuilderInstruction { - __program: program, - new_account: None, - base_account: None, - base: None, - seed: None, - space: None, - program_address: None, + __program, + new_account, + base_account, + base, + seed, + space, + program_address, __remaining_accounts: Vec::new(), }); Self { instruction } } - #[inline(always)] - pub fn new_account( - &mut self, - new_account: &'b solana_account_info::AccountInfo<'a>, - ) -> &mut Self { - self.instruction.new_account = Some(new_account); - self - } - #[inline(always)] - pub fn base_account( - &mut self, - base_account: &'b solana_account_info::AccountInfo<'a>, - ) -> &mut Self { - self.instruction.base_account = Some(base_account); - self - } - #[inline(always)] - pub fn base(&mut self, base: Address) -> &mut Self { - self.instruction.base = Some(base); - self - } - #[inline(always)] - pub fn seed(&mut self, seed: String) -> &mut Self { - self.instruction.seed = Some(seed); - self - } - #[inline(always)] - pub fn space(&mut self, space: u64) -> &mut Self { - self.instruction.space = Some(space); - self - } - #[inline(always)] - pub fn program_address(&mut self, program_address: Address) -> &mut Self { - self.instruction.program_address = Some(program_address); - self - } /// Add an additional account to the instruction. #[inline(always)] pub fn add_remaining_account( @@ -368,27 +324,15 @@ impl<'a, 'b> AllocateWithSeedCpiBuilder<'a, 'b> { #[allow(clippy::vec_init_then_push)] pub fn invoke_signed(&self, signers_seeds: &[&[&[u8]]]) -> solana_program_error::ProgramResult { let args = AllocateWithSeedInstructionArgs { - base: self.instruction.base.clone().expect("base is not set"), - seed: self.instruction.seed.clone().expect("seed is not set"), - space: self.instruction.space.clone().expect("space is not set"), - program_address: self - .instruction - .program_address - .clone() - .expect("program_address is not set"), + base: self.instruction.base.clone(), + seed: self.instruction.seed.clone(), + space: self.instruction.space.clone(), + program_address: self.instruction.program_address.clone(), }; let instruction = AllocateWithSeedCpi { __program: self.instruction.__program, - - new_account: self - .instruction - .new_account - .expect("new_account is not set"), - - base_account: self - .instruction - .base_account - .expect("base_account is not set"), + new_account: self.instruction.new_account, + base_account: self.instruction.base_account, __args: args, }; instruction.invoke_signed_with_remaining_accounts( @@ -401,12 +345,12 @@ impl<'a, 'b> AllocateWithSeedCpiBuilder<'a, 'b> { #[derive(Clone, Debug)] struct AllocateWithSeedCpiBuilderInstruction<'a, 'b> { __program: &'b solana_account_info::AccountInfo<'a>, - new_account: Option<&'b solana_account_info::AccountInfo<'a>>, - base_account: Option<&'b solana_account_info::AccountInfo<'a>>, - base: Option
, - seed: Option, - space: Option, - program_address: Option
, + new_account: &'b solana_account_info::AccountInfo<'a>, + base_account: &'b solana_account_info::AccountInfo<'a>, + base: Address, + seed: String, + space: u64, + program_address: Address, /// Additional instruction accounts `(AccountInfo, is_writable, is_signer)`. __remaining_accounts: Vec<(&'b solana_account_info::AccountInfo<'a>, bool, bool)>, } diff --git a/e2e/system/src/generated/instructions/assign.rs b/e2e/system/src/generated/instructions/assign.rs index 4ccc263..14ada32 100644 --- a/e2e/system/src/generated/instructions/assign.rs +++ b/e2e/system/src/generated/instructions/assign.rs @@ -80,26 +80,20 @@ impl AssignInstructionArgs { /// ### Accounts: /// /// 0. `[writable, signer]` account -#[derive(Clone, Debug, Default)] +#[derive(Clone, Debug)] pub struct AssignBuilder { - account: Option, - program_address: Option
, + account: solana_address::Address, + program_address: Address, __remaining_accounts: Vec, } impl AssignBuilder { - pub fn new() -> Self { - Self::default() - } - #[inline(always)] - pub fn account(&mut self, account: solana_address::Address) -> &mut Self { - self.account = Some(account); - self - } - #[inline(always)] - pub fn program_address(&mut self, program_address: Address) -> &mut Self { - self.program_address = Some(program_address); - self + pub fn new(account: solana_address::Address, program_address: Address) -> Self { + Self { + account, + program_address, + __remaining_accounts: Vec::new(), + } } /// Add an additional account to the instruction. #[inline(always)] @@ -118,14 +112,10 @@ impl AssignBuilder { } #[allow(clippy::clone_on_copy)] pub fn instruction(&self) -> solana_instruction::Instruction { - let accounts = Assign { - account: self.account.expect("account is not set"), - }; + let account = self.account; + let accounts = Assign { account }; let args = AssignInstructionArgs { - program_address: self - .program_address - .clone() - .expect("program_address is not set"), + program_address: self.program_address.clone(), }; accounts.instruction_with_remaining_accounts(args, &self.__remaining_accounts) @@ -229,25 +219,19 @@ pub struct AssignCpiBuilder<'a, 'b> { } impl<'a, 'b> AssignCpiBuilder<'a, 'b> { - pub fn new(program: &'b solana_account_info::AccountInfo<'a>) -> Self { + pub fn new( + __program: &'b solana_account_info::AccountInfo<'a>, + account: &'b solana_account_info::AccountInfo<'a>, + program_address: Address, + ) -> Self { let instruction = Box::new(AssignCpiBuilderInstruction { - __program: program, - account: None, - program_address: None, + __program, + account, + program_address, __remaining_accounts: Vec::new(), }); Self { instruction } } - #[inline(always)] - pub fn account(&mut self, account: &'b solana_account_info::AccountInfo<'a>) -> &mut Self { - self.instruction.account = Some(account); - self - } - #[inline(always)] - pub fn program_address(&mut self, program_address: Address) -> &mut Self { - self.instruction.program_address = Some(program_address); - self - } /// Add an additional account to the instruction. #[inline(always)] pub fn add_remaining_account( @@ -283,16 +267,11 @@ impl<'a, 'b> AssignCpiBuilder<'a, 'b> { #[allow(clippy::vec_init_then_push)] pub fn invoke_signed(&self, signers_seeds: &[&[&[u8]]]) -> solana_program_error::ProgramResult { let args = AssignInstructionArgs { - program_address: self - .instruction - .program_address - .clone() - .expect("program_address is not set"), + program_address: self.instruction.program_address.clone(), }; let instruction = AssignCpi { __program: self.instruction.__program, - - account: self.instruction.account.expect("account is not set"), + account: self.instruction.account, __args: args, }; instruction.invoke_signed_with_remaining_accounts( @@ -305,8 +284,8 @@ impl<'a, 'b> AssignCpiBuilder<'a, 'b> { #[derive(Clone, Debug)] struct AssignCpiBuilderInstruction<'a, 'b> { __program: &'b solana_account_info::AccountInfo<'a>, - account: Option<&'b solana_account_info::AccountInfo<'a>>, - program_address: Option
, + account: &'b solana_account_info::AccountInfo<'a>, + program_address: Address, /// Additional instruction accounts `(AccountInfo, is_writable, is_signer)`. __remaining_accounts: Vec<(&'b solana_account_info::AccountInfo<'a>, bool, bool)>, } diff --git a/e2e/system/src/generated/instructions/assign_with_seed.rs b/e2e/system/src/generated/instructions/assign_with_seed.rs index bd88c2f..e0f55f2 100644 --- a/e2e/system/src/generated/instructions/assign_with_seed.rs +++ b/e2e/system/src/generated/instructions/assign_with_seed.rs @@ -92,44 +92,32 @@ impl AssignWithSeedInstructionArgs { /// /// 0. `[writable]` account /// 1. `[signer]` base_account -#[derive(Clone, Debug, Default)] +#[derive(Clone, Debug)] pub struct AssignWithSeedBuilder { - account: Option, - base_account: Option, - base: Option
, - seed: Option, - program_address: Option
, + account: solana_address::Address, + base_account: solana_address::Address, + base: Address, + seed: String, + program_address: Address, __remaining_accounts: Vec, } impl AssignWithSeedBuilder { - pub fn new() -> Self { - Self::default() - } - #[inline(always)] - pub fn account(&mut self, account: solana_address::Address) -> &mut Self { - self.account = Some(account); - self - } - #[inline(always)] - pub fn base_account(&mut self, base_account: solana_address::Address) -> &mut Self { - self.base_account = Some(base_account); - self - } - #[inline(always)] - pub fn base(&mut self, base: Address) -> &mut Self { - self.base = Some(base); - self - } - #[inline(always)] - pub fn seed(&mut self, seed: String) -> &mut Self { - self.seed = Some(seed); - self - } - #[inline(always)] - pub fn program_address(&mut self, program_address: Address) -> &mut Self { - self.program_address = Some(program_address); - self + pub fn new( + account: solana_address::Address, + base_account: solana_address::Address, + base: Address, + seed: String, + program_address: Address, + ) -> Self { + Self { + account, + base_account, + base, + seed, + program_address, + __remaining_accounts: Vec::new(), + } } /// Add an additional account to the instruction. #[inline(always)] @@ -148,17 +136,16 @@ impl AssignWithSeedBuilder { } #[allow(clippy::clone_on_copy)] pub fn instruction(&self) -> solana_instruction::Instruction { + let account = self.account; + let base_account = self.base_account; let accounts = AssignWithSeed { - account: self.account.expect("account is not set"), - base_account: self.base_account.expect("base_account is not set"), + account, + base_account, }; let args = AssignWithSeedInstructionArgs { - base: self.base.clone().expect("base is not set"), - seed: self.seed.clone().expect("seed is not set"), - program_address: self - .program_address - .clone() - .expect("program_address is not set"), + base: self.base.clone(), + seed: self.seed.clone(), + program_address: self.program_address.clone(), }; accounts.instruction_with_remaining_accounts(args, &self.__remaining_accounts) @@ -273,46 +260,25 @@ pub struct AssignWithSeedCpiBuilder<'a, 'b> { } impl<'a, 'b> AssignWithSeedCpiBuilder<'a, 'b> { - pub fn new(program: &'b solana_account_info::AccountInfo<'a>) -> Self { + pub fn new( + __program: &'b solana_account_info::AccountInfo<'a>, + account: &'b solana_account_info::AccountInfo<'a>, + base_account: &'b solana_account_info::AccountInfo<'a>, + base: Address, + seed: String, + program_address: Address, + ) -> Self { let instruction = Box::new(AssignWithSeedCpiBuilderInstruction { - __program: program, - account: None, - base_account: None, - base: None, - seed: None, - program_address: None, + __program, + account, + base_account, + base, + seed, + program_address, __remaining_accounts: Vec::new(), }); Self { instruction } } - #[inline(always)] - pub fn account(&mut self, account: &'b solana_account_info::AccountInfo<'a>) -> &mut Self { - self.instruction.account = Some(account); - self - } - #[inline(always)] - pub fn base_account( - &mut self, - base_account: &'b solana_account_info::AccountInfo<'a>, - ) -> &mut Self { - self.instruction.base_account = Some(base_account); - self - } - #[inline(always)] - pub fn base(&mut self, base: Address) -> &mut Self { - self.instruction.base = Some(base); - self - } - #[inline(always)] - pub fn seed(&mut self, seed: String) -> &mut Self { - self.instruction.seed = Some(seed); - self - } - #[inline(always)] - pub fn program_address(&mut self, program_address: Address) -> &mut Self { - self.instruction.program_address = Some(program_address); - self - } /// Add an additional account to the instruction. #[inline(always)] pub fn add_remaining_account( @@ -348,23 +314,14 @@ impl<'a, 'b> AssignWithSeedCpiBuilder<'a, 'b> { #[allow(clippy::vec_init_then_push)] pub fn invoke_signed(&self, signers_seeds: &[&[&[u8]]]) -> solana_program_error::ProgramResult { let args = AssignWithSeedInstructionArgs { - base: self.instruction.base.clone().expect("base is not set"), - seed: self.instruction.seed.clone().expect("seed is not set"), - program_address: self - .instruction - .program_address - .clone() - .expect("program_address is not set"), + base: self.instruction.base.clone(), + seed: self.instruction.seed.clone(), + program_address: self.instruction.program_address.clone(), }; let instruction = AssignWithSeedCpi { __program: self.instruction.__program, - - account: self.instruction.account.expect("account is not set"), - - base_account: self - .instruction - .base_account - .expect("base_account is not set"), + account: self.instruction.account, + base_account: self.instruction.base_account, __args: args, }; instruction.invoke_signed_with_remaining_accounts( @@ -377,11 +334,11 @@ impl<'a, 'b> AssignWithSeedCpiBuilder<'a, 'b> { #[derive(Clone, Debug)] struct AssignWithSeedCpiBuilderInstruction<'a, 'b> { __program: &'b solana_account_info::AccountInfo<'a>, - account: Option<&'b solana_account_info::AccountInfo<'a>>, - base_account: Option<&'b solana_account_info::AccountInfo<'a>>, - base: Option
, - seed: Option, - program_address: Option
, + account: &'b solana_account_info::AccountInfo<'a>, + base_account: &'b solana_account_info::AccountInfo<'a>, + base: Address, + seed: String, + program_address: Address, /// Additional instruction accounts `(AccountInfo, is_writable, is_signer)`. __remaining_accounts: Vec<(&'b solana_account_info::AccountInfo<'a>, bool, bool)>, } diff --git a/e2e/system/src/generated/instructions/authorize_nonce_account.rs b/e2e/system/src/generated/instructions/authorize_nonce_account.rs index e881144..4c77ac3 100644 --- a/e2e/system/src/generated/instructions/authorize_nonce_account.rs +++ b/e2e/system/src/generated/instructions/authorize_nonce_account.rs @@ -95,32 +95,26 @@ impl AuthorizeNonceAccountInstructionArgs { /// /// 0. `[writable]` nonce_account /// 1. `[signer]` nonce_authority -#[derive(Clone, Debug, Default)] +#[derive(Clone, Debug)] pub struct AuthorizeNonceAccountBuilder { - nonce_account: Option, - nonce_authority: Option, - new_nonce_authority: Option
, + nonce_account: solana_address::Address, + nonce_authority: solana_address::Address, + new_nonce_authority: Address, __remaining_accounts: Vec, } impl AuthorizeNonceAccountBuilder { - pub fn new() -> Self { - Self::default() - } - #[inline(always)] - pub fn nonce_account(&mut self, nonce_account: solana_address::Address) -> &mut Self { - self.nonce_account = Some(nonce_account); - self - } - #[inline(always)] - pub fn nonce_authority(&mut self, nonce_authority: solana_address::Address) -> &mut Self { - self.nonce_authority = Some(nonce_authority); - self - } - #[inline(always)] - pub fn new_nonce_authority(&mut self, new_nonce_authority: Address) -> &mut Self { - self.new_nonce_authority = Some(new_nonce_authority); - self + pub fn new( + nonce_account: solana_address::Address, + nonce_authority: solana_address::Address, + new_nonce_authority: Address, + ) -> Self { + Self { + nonce_account, + nonce_authority, + new_nonce_authority, + __remaining_accounts: Vec::new(), + } } /// Add an additional account to the instruction. #[inline(always)] @@ -139,15 +133,14 @@ impl AuthorizeNonceAccountBuilder { } #[allow(clippy::clone_on_copy)] pub fn instruction(&self) -> solana_instruction::Instruction { + let nonce_account = self.nonce_account; + let nonce_authority = self.nonce_authority; let accounts = AuthorizeNonceAccount { - nonce_account: self.nonce_account.expect("nonce_account is not set"), - nonce_authority: self.nonce_authority.expect("nonce_authority is not set"), + nonce_account, + nonce_authority, }; let args = AuthorizeNonceAccountInstructionArgs { - new_nonce_authority: self - .new_nonce_authority - .clone() - .expect("new_nonce_authority is not set"), + new_nonce_authority: self.new_nonce_authority.clone(), }; accounts.instruction_with_remaining_accounts(args, &self.__remaining_accounts) @@ -264,37 +257,21 @@ pub struct AuthorizeNonceAccountCpiBuilder<'a, 'b> { } impl<'a, 'b> AuthorizeNonceAccountCpiBuilder<'a, 'b> { - pub fn new(program: &'b solana_account_info::AccountInfo<'a>) -> Self { + pub fn new( + __program: &'b solana_account_info::AccountInfo<'a>, + nonce_account: &'b solana_account_info::AccountInfo<'a>, + nonce_authority: &'b solana_account_info::AccountInfo<'a>, + new_nonce_authority: Address, + ) -> Self { let instruction = Box::new(AuthorizeNonceAccountCpiBuilderInstruction { - __program: program, - nonce_account: None, - nonce_authority: None, - new_nonce_authority: None, + __program, + nonce_account, + nonce_authority, + new_nonce_authority, __remaining_accounts: Vec::new(), }); Self { instruction } } - #[inline(always)] - pub fn nonce_account( - &mut self, - nonce_account: &'b solana_account_info::AccountInfo<'a>, - ) -> &mut Self { - self.instruction.nonce_account = Some(nonce_account); - self - } - #[inline(always)] - pub fn nonce_authority( - &mut self, - nonce_authority: &'b solana_account_info::AccountInfo<'a>, - ) -> &mut Self { - self.instruction.nonce_authority = Some(nonce_authority); - self - } - #[inline(always)] - pub fn new_nonce_authority(&mut self, new_nonce_authority: Address) -> &mut Self { - self.instruction.new_nonce_authority = Some(new_nonce_authority); - self - } /// Add an additional account to the instruction. #[inline(always)] pub fn add_remaining_account( @@ -330,24 +307,12 @@ impl<'a, 'b> AuthorizeNonceAccountCpiBuilder<'a, 'b> { #[allow(clippy::vec_init_then_push)] pub fn invoke_signed(&self, signers_seeds: &[&[&[u8]]]) -> solana_program_error::ProgramResult { let args = AuthorizeNonceAccountInstructionArgs { - new_nonce_authority: self - .instruction - .new_nonce_authority - .clone() - .expect("new_nonce_authority is not set"), + new_nonce_authority: self.instruction.new_nonce_authority.clone(), }; let instruction = AuthorizeNonceAccountCpi { __program: self.instruction.__program, - - nonce_account: self - .instruction - .nonce_account - .expect("nonce_account is not set"), - - nonce_authority: self - .instruction - .nonce_authority - .expect("nonce_authority is not set"), + nonce_account: self.instruction.nonce_account, + nonce_authority: self.instruction.nonce_authority, __args: args, }; instruction.invoke_signed_with_remaining_accounts( @@ -360,9 +325,9 @@ impl<'a, 'b> AuthorizeNonceAccountCpiBuilder<'a, 'b> { #[derive(Clone, Debug)] struct AuthorizeNonceAccountCpiBuilderInstruction<'a, 'b> { __program: &'b solana_account_info::AccountInfo<'a>, - nonce_account: Option<&'b solana_account_info::AccountInfo<'a>>, - nonce_authority: Option<&'b solana_account_info::AccountInfo<'a>>, - new_nonce_authority: Option
, + nonce_account: &'b solana_account_info::AccountInfo<'a>, + nonce_authority: &'b solana_account_info::AccountInfo<'a>, + new_nonce_authority: Address, /// Additional instruction accounts `(AccountInfo, is_writable, is_signer)`. __remaining_accounts: Vec<(&'b solana_account_info::AccountInfo<'a>, bool, bool)>, } diff --git a/e2e/system/src/generated/instructions/create_account.rs b/e2e/system/src/generated/instructions/create_account.rs index b455e4c..8422404 100644 --- a/e2e/system/src/generated/instructions/create_account.rs +++ b/e2e/system/src/generated/instructions/create_account.rs @@ -89,44 +89,32 @@ impl CreateAccountInstructionArgs { /// /// 0. `[writable, signer]` payer /// 1. `[writable, signer]` new_account -#[derive(Clone, Debug, Default)] +#[derive(Clone, Debug)] pub struct CreateAccountBuilder { - payer: Option, - new_account: Option, - lamports: Option, - space: Option, - program_address: Option
, + payer: solana_address::Address, + new_account: solana_address::Address, + lamports: u64, + space: u64, + program_address: Address, __remaining_accounts: Vec, } impl CreateAccountBuilder { - pub fn new() -> Self { - Self::default() - } - #[inline(always)] - pub fn payer(&mut self, payer: solana_address::Address) -> &mut Self { - self.payer = Some(payer); - self - } - #[inline(always)] - pub fn new_account(&mut self, new_account: solana_address::Address) -> &mut Self { - self.new_account = Some(new_account); - self - } - #[inline(always)] - pub fn lamports(&mut self, lamports: u64) -> &mut Self { - self.lamports = Some(lamports); - self - } - #[inline(always)] - pub fn space(&mut self, space: u64) -> &mut Self { - self.space = Some(space); - self - } - #[inline(always)] - pub fn program_address(&mut self, program_address: Address) -> &mut Self { - self.program_address = Some(program_address); - self + pub fn new( + payer: solana_address::Address, + new_account: solana_address::Address, + lamports: u64, + space: u64, + program_address: Address, + ) -> Self { + Self { + payer, + new_account, + lamports, + space, + program_address, + __remaining_accounts: Vec::new(), + } } /// Add an additional account to the instruction. #[inline(always)] @@ -145,17 +133,13 @@ impl CreateAccountBuilder { } #[allow(clippy::clone_on_copy)] pub fn instruction(&self) -> solana_instruction::Instruction { - let accounts = CreateAccount { - payer: self.payer.expect("payer is not set"), - new_account: self.new_account.expect("new_account is not set"), - }; + let payer = self.payer; + let new_account = self.new_account; + let accounts = CreateAccount { payer, new_account }; let args = CreateAccountInstructionArgs { - lamports: self.lamports.clone().expect("lamports is not set"), - space: self.space.clone().expect("space is not set"), - program_address: self - .program_address - .clone() - .expect("program_address is not set"), + lamports: self.lamports.clone(), + space: self.space.clone(), + program_address: self.program_address.clone(), }; accounts.instruction_with_remaining_accounts(args, &self.__remaining_accounts) @@ -267,46 +251,25 @@ pub struct CreateAccountCpiBuilder<'a, 'b> { } impl<'a, 'b> CreateAccountCpiBuilder<'a, 'b> { - pub fn new(program: &'b solana_account_info::AccountInfo<'a>) -> Self { + pub fn new( + __program: &'b solana_account_info::AccountInfo<'a>, + payer: &'b solana_account_info::AccountInfo<'a>, + new_account: &'b solana_account_info::AccountInfo<'a>, + lamports: u64, + space: u64, + program_address: Address, + ) -> Self { let instruction = Box::new(CreateAccountCpiBuilderInstruction { - __program: program, - payer: None, - new_account: None, - lamports: None, - space: None, - program_address: None, + __program, + payer, + new_account, + lamports, + space, + program_address, __remaining_accounts: Vec::new(), }); Self { instruction } } - #[inline(always)] - pub fn payer(&mut self, payer: &'b solana_account_info::AccountInfo<'a>) -> &mut Self { - self.instruction.payer = Some(payer); - self - } - #[inline(always)] - pub fn new_account( - &mut self, - new_account: &'b solana_account_info::AccountInfo<'a>, - ) -> &mut Self { - self.instruction.new_account = Some(new_account); - self - } - #[inline(always)] - pub fn lamports(&mut self, lamports: u64) -> &mut Self { - self.instruction.lamports = Some(lamports); - self - } - #[inline(always)] - pub fn space(&mut self, space: u64) -> &mut Self { - self.instruction.space = Some(space); - self - } - #[inline(always)] - pub fn program_address(&mut self, program_address: Address) -> &mut Self { - self.instruction.program_address = Some(program_address); - self - } /// Add an additional account to the instruction. #[inline(always)] pub fn add_remaining_account( @@ -342,27 +305,14 @@ impl<'a, 'b> CreateAccountCpiBuilder<'a, 'b> { #[allow(clippy::vec_init_then_push)] pub fn invoke_signed(&self, signers_seeds: &[&[&[u8]]]) -> solana_program_error::ProgramResult { let args = CreateAccountInstructionArgs { - lamports: self - .instruction - .lamports - .clone() - .expect("lamports is not set"), - space: self.instruction.space.clone().expect("space is not set"), - program_address: self - .instruction - .program_address - .clone() - .expect("program_address is not set"), + lamports: self.instruction.lamports.clone(), + space: self.instruction.space.clone(), + program_address: self.instruction.program_address.clone(), }; let instruction = CreateAccountCpi { __program: self.instruction.__program, - - payer: self.instruction.payer.expect("payer is not set"), - - new_account: self - .instruction - .new_account - .expect("new_account is not set"), + payer: self.instruction.payer, + new_account: self.instruction.new_account, __args: args, }; instruction.invoke_signed_with_remaining_accounts( @@ -375,11 +325,11 @@ impl<'a, 'b> CreateAccountCpiBuilder<'a, 'b> { #[derive(Clone, Debug)] struct CreateAccountCpiBuilderInstruction<'a, 'b> { __program: &'b solana_account_info::AccountInfo<'a>, - payer: Option<&'b solana_account_info::AccountInfo<'a>>, - new_account: Option<&'b solana_account_info::AccountInfo<'a>>, - lamports: Option, - space: Option, - program_address: Option
, + payer: &'b solana_account_info::AccountInfo<'a>, + new_account: &'b solana_account_info::AccountInfo<'a>, + lamports: u64, + space: u64, + program_address: Address, /// Additional instruction accounts `(AccountInfo, is_writable, is_signer)`. __remaining_accounts: Vec<(&'b solana_account_info::AccountInfo<'a>, bool, bool)>, } diff --git a/e2e/system/src/generated/instructions/create_account_with_seed.rs b/e2e/system/src/generated/instructions/create_account_with_seed.rs index 97676e7..6483130 100644 --- a/e2e/system/src/generated/instructions/create_account_with_seed.rs +++ b/e2e/system/src/generated/instructions/create_account_with_seed.rs @@ -103,62 +103,41 @@ impl CreateAccountWithSeedInstructionArgs { /// 0. `[writable, signer]` payer /// 1. `[writable]` new_account /// 2. `[signer]` base_account -#[derive(Clone, Debug, Default)] +#[derive(Clone, Debug)] pub struct CreateAccountWithSeedBuilder { - payer: Option, - new_account: Option, - base_account: Option, - base: Option
, - seed: Option, - amount: Option, - space: Option, - program_address: Option
, + payer: solana_address::Address, + new_account: solana_address::Address, + base_account: solana_address::Address, + base: Address, + seed: String, + amount: u64, + space: u64, + program_address: Address, __remaining_accounts: Vec, } impl CreateAccountWithSeedBuilder { - pub fn new() -> Self { - Self::default() - } - #[inline(always)] - pub fn payer(&mut self, payer: solana_address::Address) -> &mut Self { - self.payer = Some(payer); - self - } - #[inline(always)] - pub fn new_account(&mut self, new_account: solana_address::Address) -> &mut Self { - self.new_account = Some(new_account); - self - } - #[inline(always)] - pub fn base_account(&mut self, base_account: solana_address::Address) -> &mut Self { - self.base_account = Some(base_account); - self - } - #[inline(always)] - pub fn base(&mut self, base: Address) -> &mut Self { - self.base = Some(base); - self - } - #[inline(always)] - pub fn seed(&mut self, seed: String) -> &mut Self { - self.seed = Some(seed); - self - } - #[inline(always)] - pub fn amount(&mut self, amount: u64) -> &mut Self { - self.amount = Some(amount); - self - } - #[inline(always)] - pub fn space(&mut self, space: u64) -> &mut Self { - self.space = Some(space); - self - } - #[inline(always)] - pub fn program_address(&mut self, program_address: Address) -> &mut Self { - self.program_address = Some(program_address); - self + pub fn new( + payer: solana_address::Address, + new_account: solana_address::Address, + base_account: solana_address::Address, + base: Address, + seed: String, + amount: u64, + space: u64, + program_address: Address, + ) -> Self { + Self { + payer, + new_account, + base_account, + base, + seed, + amount, + space, + program_address, + __remaining_accounts: Vec::new(), + } } /// Add an additional account to the instruction. #[inline(always)] @@ -177,20 +156,20 @@ impl CreateAccountWithSeedBuilder { } #[allow(clippy::clone_on_copy)] pub fn instruction(&self) -> solana_instruction::Instruction { + let payer = self.payer; + let new_account = self.new_account; + let base_account = self.base_account; let accounts = CreateAccountWithSeed { - payer: self.payer.expect("payer is not set"), - new_account: self.new_account.expect("new_account is not set"), - base_account: self.base_account.expect("base_account is not set"), + payer, + new_account, + base_account, }; let args = CreateAccountWithSeedInstructionArgs { - base: self.base.clone().expect("base is not set"), - seed: self.seed.clone().expect("seed is not set"), - amount: self.amount.clone().expect("amount is not set"), - space: self.space.clone().expect("space is not set"), - program_address: self - .program_address - .clone() - .expect("program_address is not set"), + base: self.base.clone(), + seed: self.seed.clone(), + amount: self.amount.clone(), + space: self.space.clone(), + program_address: self.program_address.clone(), }; accounts.instruction_with_remaining_accounts(args, &self.__remaining_accounts) @@ -315,67 +294,31 @@ pub struct CreateAccountWithSeedCpiBuilder<'a, 'b> { } impl<'a, 'b> CreateAccountWithSeedCpiBuilder<'a, 'b> { - pub fn new(program: &'b solana_account_info::AccountInfo<'a>) -> Self { + pub fn new( + __program: &'b solana_account_info::AccountInfo<'a>, + payer: &'b solana_account_info::AccountInfo<'a>, + new_account: &'b solana_account_info::AccountInfo<'a>, + base_account: &'b solana_account_info::AccountInfo<'a>, + base: Address, + seed: String, + amount: u64, + space: u64, + program_address: Address, + ) -> Self { let instruction = Box::new(CreateAccountWithSeedCpiBuilderInstruction { - __program: program, - payer: None, - new_account: None, - base_account: None, - base: None, - seed: None, - amount: None, - space: None, - program_address: None, + __program, + payer, + new_account, + base_account, + base, + seed, + amount, + space, + program_address, __remaining_accounts: Vec::new(), }); Self { instruction } } - #[inline(always)] - pub fn payer(&mut self, payer: &'b solana_account_info::AccountInfo<'a>) -> &mut Self { - self.instruction.payer = Some(payer); - self - } - #[inline(always)] - pub fn new_account( - &mut self, - new_account: &'b solana_account_info::AccountInfo<'a>, - ) -> &mut Self { - self.instruction.new_account = Some(new_account); - self - } - #[inline(always)] - pub fn base_account( - &mut self, - base_account: &'b solana_account_info::AccountInfo<'a>, - ) -> &mut Self { - self.instruction.base_account = Some(base_account); - self - } - #[inline(always)] - pub fn base(&mut self, base: Address) -> &mut Self { - self.instruction.base = Some(base); - self - } - #[inline(always)] - pub fn seed(&mut self, seed: String) -> &mut Self { - self.instruction.seed = Some(seed); - self - } - #[inline(always)] - pub fn amount(&mut self, amount: u64) -> &mut Self { - self.instruction.amount = Some(amount); - self - } - #[inline(always)] - pub fn space(&mut self, space: u64) -> &mut Self { - self.instruction.space = Some(space); - self - } - #[inline(always)] - pub fn program_address(&mut self, program_address: Address) -> &mut Self { - self.instruction.program_address = Some(program_address); - self - } /// Add an additional account to the instruction. #[inline(always)] pub fn add_remaining_account( @@ -411,30 +354,17 @@ impl<'a, 'b> CreateAccountWithSeedCpiBuilder<'a, 'b> { #[allow(clippy::vec_init_then_push)] pub fn invoke_signed(&self, signers_seeds: &[&[&[u8]]]) -> solana_program_error::ProgramResult { let args = CreateAccountWithSeedInstructionArgs { - base: self.instruction.base.clone().expect("base is not set"), - seed: self.instruction.seed.clone().expect("seed is not set"), - amount: self.instruction.amount.clone().expect("amount is not set"), - space: self.instruction.space.clone().expect("space is not set"), - program_address: self - .instruction - .program_address - .clone() - .expect("program_address is not set"), + base: self.instruction.base.clone(), + seed: self.instruction.seed.clone(), + amount: self.instruction.amount.clone(), + space: self.instruction.space.clone(), + program_address: self.instruction.program_address.clone(), }; let instruction = CreateAccountWithSeedCpi { __program: self.instruction.__program, - - payer: self.instruction.payer.expect("payer is not set"), - - new_account: self - .instruction - .new_account - .expect("new_account is not set"), - - base_account: self - .instruction - .base_account - .expect("base_account is not set"), + payer: self.instruction.payer, + new_account: self.instruction.new_account, + base_account: self.instruction.base_account, __args: args, }; instruction.invoke_signed_with_remaining_accounts( @@ -447,14 +377,14 @@ impl<'a, 'b> CreateAccountWithSeedCpiBuilder<'a, 'b> { #[derive(Clone, Debug)] struct CreateAccountWithSeedCpiBuilderInstruction<'a, 'b> { __program: &'b solana_account_info::AccountInfo<'a>, - payer: Option<&'b solana_account_info::AccountInfo<'a>>, - new_account: Option<&'b solana_account_info::AccountInfo<'a>>, - base_account: Option<&'b solana_account_info::AccountInfo<'a>>, - base: Option
, - seed: Option, - amount: Option, - space: Option, - program_address: Option
, + payer: &'b solana_account_info::AccountInfo<'a>, + new_account: &'b solana_account_info::AccountInfo<'a>, + base_account: &'b solana_account_info::AccountInfo<'a>, + base: Address, + seed: String, + amount: u64, + space: u64, + program_address: Address, /// Additional instruction accounts `(AccountInfo, is_writable, is_signer)`. __remaining_accounts: Vec<(&'b solana_account_info::AccountInfo<'a>, bool, bool)>, } diff --git a/e2e/system/src/generated/instructions/initialize_nonce_account.rs b/e2e/system/src/generated/instructions/initialize_nonce_account.rs index f453f48..ad9ba5b 100644 --- a/e2e/system/src/generated/instructions/initialize_nonce_account.rs +++ b/e2e/system/src/generated/instructions/initialize_nonce_account.rs @@ -102,23 +102,24 @@ impl InitializeNonceAccountInstructionArgs { /// 0. `[writable]` nonce_account /// 1. `[optional]` recent_blockhashes_sysvar (default to `SysvarRecentB1ockHashes11111111111111111111`) /// 2. `[optional]` rent_sysvar (default to `SysvarRent111111111111111111111111111111111`) -#[derive(Clone, Debug, Default)] +#[derive(Clone, Debug)] pub struct InitializeNonceAccountBuilder { - nonce_account: Option, + nonce_account: solana_address::Address, recent_blockhashes_sysvar: Option, rent_sysvar: Option, - nonce_authority: Option
, + nonce_authority: Address, __remaining_accounts: Vec, } impl InitializeNonceAccountBuilder { - pub fn new() -> Self { - Self::default() - } - #[inline(always)] - pub fn nonce_account(&mut self, nonce_account: solana_address::Address) -> &mut Self { - self.nonce_account = Some(nonce_account); - self + pub fn new(nonce_account: solana_address::Address, nonce_authority: Address) -> Self { + Self { + nonce_account, + recent_blockhashes_sysvar: None, + rent_sysvar: None, + nonce_authority, + __remaining_accounts: Vec::new(), + } } /// `[optional account, default to 'SysvarRecentB1ockHashes11111111111111111111']` #[inline(always)] @@ -135,11 +136,6 @@ impl InitializeNonceAccountBuilder { self.rent_sysvar = Some(rent_sysvar); self } - #[inline(always)] - pub fn nonce_authority(&mut self, nonce_authority: Address) -> &mut Self { - self.nonce_authority = Some(nonce_authority); - self - } /// Add an additional account to the instruction. #[inline(always)] pub fn add_remaining_account(&mut self, account: solana_instruction::AccountMeta) -> &mut Self { @@ -157,20 +153,22 @@ impl InitializeNonceAccountBuilder { } #[allow(clippy::clone_on_copy)] pub fn instruction(&self) -> solana_instruction::Instruction { + let nonce_account = self.nonce_account; + let recent_blockhashes_sysvar = + self.recent_blockhashes_sysvar + .unwrap_or(solana_address::address!( + "SysvarRecentB1ockHashes11111111111111111111" + )); + let rent_sysvar = self.rent_sysvar.unwrap_or(solana_address::address!( + "SysvarRent111111111111111111111111111111111" + )); let accounts = InitializeNonceAccount { - nonce_account: self.nonce_account.expect("nonce_account is not set"), - recent_blockhashes_sysvar: self.recent_blockhashes_sysvar.unwrap_or( - solana_address::address!("SysvarRecentB1ockHashes11111111111111111111"), - ), - rent_sysvar: self.rent_sysvar.unwrap_or(solana_address::address!( - "SysvarRent111111111111111111111111111111111" - )), + nonce_account, + recent_blockhashes_sysvar, + rent_sysvar, }; let args = InitializeNonceAccountInstructionArgs { - nonce_authority: self - .nonce_authority - .clone() - .expect("nonce_authority is not set"), + nonce_authority: self.nonce_authority.clone(), }; accounts.instruction_with_remaining_accounts(args, &self.__remaining_accounts) @@ -298,46 +296,23 @@ pub struct InitializeNonceAccountCpiBuilder<'a, 'b> { } impl<'a, 'b> InitializeNonceAccountCpiBuilder<'a, 'b> { - pub fn new(program: &'b solana_account_info::AccountInfo<'a>) -> Self { + pub fn new( + __program: &'b solana_account_info::AccountInfo<'a>, + nonce_account: &'b solana_account_info::AccountInfo<'a>, + recent_blockhashes_sysvar: &'b solana_account_info::AccountInfo<'a>, + rent_sysvar: &'b solana_account_info::AccountInfo<'a>, + nonce_authority: Address, + ) -> Self { let instruction = Box::new(InitializeNonceAccountCpiBuilderInstruction { - __program: program, - nonce_account: None, - recent_blockhashes_sysvar: None, - rent_sysvar: None, - nonce_authority: None, + __program, + nonce_account, + recent_blockhashes_sysvar, + rent_sysvar, + nonce_authority, __remaining_accounts: Vec::new(), }); Self { instruction } } - #[inline(always)] - pub fn nonce_account( - &mut self, - nonce_account: &'b solana_account_info::AccountInfo<'a>, - ) -> &mut Self { - self.instruction.nonce_account = Some(nonce_account); - self - } - #[inline(always)] - pub fn recent_blockhashes_sysvar( - &mut self, - recent_blockhashes_sysvar: &'b solana_account_info::AccountInfo<'a>, - ) -> &mut Self { - self.instruction.recent_blockhashes_sysvar = Some(recent_blockhashes_sysvar); - self - } - #[inline(always)] - pub fn rent_sysvar( - &mut self, - rent_sysvar: &'b solana_account_info::AccountInfo<'a>, - ) -> &mut Self { - self.instruction.rent_sysvar = Some(rent_sysvar); - self - } - #[inline(always)] - pub fn nonce_authority(&mut self, nonce_authority: Address) -> &mut Self { - self.instruction.nonce_authority = Some(nonce_authority); - self - } /// Add an additional account to the instruction. #[inline(always)] pub fn add_remaining_account( @@ -373,29 +348,13 @@ impl<'a, 'b> InitializeNonceAccountCpiBuilder<'a, 'b> { #[allow(clippy::vec_init_then_push)] pub fn invoke_signed(&self, signers_seeds: &[&[&[u8]]]) -> solana_program_error::ProgramResult { let args = InitializeNonceAccountInstructionArgs { - nonce_authority: self - .instruction - .nonce_authority - .clone() - .expect("nonce_authority is not set"), + nonce_authority: self.instruction.nonce_authority.clone(), }; let instruction = InitializeNonceAccountCpi { __program: self.instruction.__program, - - nonce_account: self - .instruction - .nonce_account - .expect("nonce_account is not set"), - - recent_blockhashes_sysvar: self - .instruction - .recent_blockhashes_sysvar - .expect("recent_blockhashes_sysvar is not set"), - - rent_sysvar: self - .instruction - .rent_sysvar - .expect("rent_sysvar is not set"), + nonce_account: self.instruction.nonce_account, + recent_blockhashes_sysvar: self.instruction.recent_blockhashes_sysvar, + rent_sysvar: self.instruction.rent_sysvar, __args: args, }; instruction.invoke_signed_with_remaining_accounts( @@ -408,10 +367,10 @@ impl<'a, 'b> InitializeNonceAccountCpiBuilder<'a, 'b> { #[derive(Clone, Debug)] struct InitializeNonceAccountCpiBuilderInstruction<'a, 'b> { __program: &'b solana_account_info::AccountInfo<'a>, - nonce_account: Option<&'b solana_account_info::AccountInfo<'a>>, - recent_blockhashes_sysvar: Option<&'b solana_account_info::AccountInfo<'a>>, - rent_sysvar: Option<&'b solana_account_info::AccountInfo<'a>>, - nonce_authority: Option
, + nonce_account: &'b solana_account_info::AccountInfo<'a>, + recent_blockhashes_sysvar: &'b solana_account_info::AccountInfo<'a>, + rent_sysvar: &'b solana_account_info::AccountInfo<'a>, + nonce_authority: Address, /// Additional instruction accounts `(AccountInfo, is_writable, is_signer)`. __remaining_accounts: Vec<(&'b solana_account_info::AccountInfo<'a>, bool, bool)>, } diff --git a/e2e/system/src/generated/instructions/transfer_sol.rs b/e2e/system/src/generated/instructions/transfer_sol.rs index 6403821..dfa13c9 100644 --- a/e2e/system/src/generated/instructions/transfer_sol.rs +++ b/e2e/system/src/generated/instructions/transfer_sol.rs @@ -86,32 +86,26 @@ impl TransferSolInstructionArgs { /// /// 0. `[writable, signer]` source /// 1. `[writable]` destination -#[derive(Clone, Debug, Default)] +#[derive(Clone, Debug)] pub struct TransferSolBuilder { - source: Option, - destination: Option, - amount: Option, + source: solana_address::Address, + destination: solana_address::Address, + amount: u64, __remaining_accounts: Vec, } impl TransferSolBuilder { - pub fn new() -> Self { - Self::default() - } - #[inline(always)] - pub fn source(&mut self, source: solana_address::Address) -> &mut Self { - self.source = Some(source); - self - } - #[inline(always)] - pub fn destination(&mut self, destination: solana_address::Address) -> &mut Self { - self.destination = Some(destination); - self - } - #[inline(always)] - pub fn amount(&mut self, amount: u64) -> &mut Self { - self.amount = Some(amount); - self + pub fn new( + source: solana_address::Address, + destination: solana_address::Address, + amount: u64, + ) -> Self { + Self { + source, + destination, + amount, + __remaining_accounts: Vec::new(), + } } /// Add an additional account to the instruction. #[inline(always)] @@ -130,12 +124,14 @@ impl TransferSolBuilder { } #[allow(clippy::clone_on_copy)] pub fn instruction(&self) -> solana_instruction::Instruction { + let source = self.source; + let destination = self.destination; let accounts = TransferSol { - source: self.source.expect("source is not set"), - destination: self.destination.expect("destination is not set"), + source, + destination, }; let args = TransferSolInstructionArgs { - amount: self.amount.clone().expect("amount is not set"), + amount: self.amount.clone(), }; accounts.instruction_with_remaining_accounts(args, &self.__remaining_accounts) @@ -247,34 +243,21 @@ pub struct TransferSolCpiBuilder<'a, 'b> { } impl<'a, 'b> TransferSolCpiBuilder<'a, 'b> { - pub fn new(program: &'b solana_account_info::AccountInfo<'a>) -> Self { + pub fn new( + __program: &'b solana_account_info::AccountInfo<'a>, + source: &'b solana_account_info::AccountInfo<'a>, + destination: &'b solana_account_info::AccountInfo<'a>, + amount: u64, + ) -> Self { let instruction = Box::new(TransferSolCpiBuilderInstruction { - __program: program, - source: None, - destination: None, - amount: None, + __program, + source, + destination, + amount, __remaining_accounts: Vec::new(), }); Self { instruction } } - #[inline(always)] - pub fn source(&mut self, source: &'b solana_account_info::AccountInfo<'a>) -> &mut Self { - self.instruction.source = Some(source); - self - } - #[inline(always)] - pub fn destination( - &mut self, - destination: &'b solana_account_info::AccountInfo<'a>, - ) -> &mut Self { - self.instruction.destination = Some(destination); - self - } - #[inline(always)] - pub fn amount(&mut self, amount: u64) -> &mut Self { - self.instruction.amount = Some(amount); - self - } /// Add an additional account to the instruction. #[inline(always)] pub fn add_remaining_account( @@ -310,17 +293,12 @@ impl<'a, 'b> TransferSolCpiBuilder<'a, 'b> { #[allow(clippy::vec_init_then_push)] pub fn invoke_signed(&self, signers_seeds: &[&[&[u8]]]) -> solana_program_error::ProgramResult { let args = TransferSolInstructionArgs { - amount: self.instruction.amount.clone().expect("amount is not set"), + amount: self.instruction.amount.clone(), }; let instruction = TransferSolCpi { __program: self.instruction.__program, - - source: self.instruction.source.expect("source is not set"), - - destination: self - .instruction - .destination - .expect("destination is not set"), + source: self.instruction.source, + destination: self.instruction.destination, __args: args, }; instruction.invoke_signed_with_remaining_accounts( @@ -333,9 +311,9 @@ impl<'a, 'b> TransferSolCpiBuilder<'a, 'b> { #[derive(Clone, Debug)] struct TransferSolCpiBuilderInstruction<'a, 'b> { __program: &'b solana_account_info::AccountInfo<'a>, - source: Option<&'b solana_account_info::AccountInfo<'a>>, - destination: Option<&'b solana_account_info::AccountInfo<'a>>, - amount: Option, + source: &'b solana_account_info::AccountInfo<'a>, + destination: &'b solana_account_info::AccountInfo<'a>, + amount: u64, /// Additional instruction accounts `(AccountInfo, is_writable, is_signer)`. __remaining_accounts: Vec<(&'b solana_account_info::AccountInfo<'a>, bool, bool)>, } diff --git a/e2e/system/src/generated/instructions/transfer_sol_with_seed.rs b/e2e/system/src/generated/instructions/transfer_sol_with_seed.rs index 3fd3668..37c4681 100644 --- a/e2e/system/src/generated/instructions/transfer_sol_with_seed.rs +++ b/e2e/system/src/generated/instructions/transfer_sol_with_seed.rs @@ -101,50 +101,35 @@ impl TransferSolWithSeedInstructionArgs { /// 0. `[writable]` source /// 1. `[signer]` base_account /// 2. `[writable]` destination -#[derive(Clone, Debug, Default)] +#[derive(Clone, Debug)] pub struct TransferSolWithSeedBuilder { - source: Option, - base_account: Option, - destination: Option, - amount: Option, - from_seed: Option, - from_owner: Option
, + source: solana_address::Address, + base_account: solana_address::Address, + destination: solana_address::Address, + amount: u64, + from_seed: String, + from_owner: Address, __remaining_accounts: Vec, } impl TransferSolWithSeedBuilder { - pub fn new() -> Self { - Self::default() - } - #[inline(always)] - pub fn source(&mut self, source: solana_address::Address) -> &mut Self { - self.source = Some(source); - self - } - #[inline(always)] - pub fn base_account(&mut self, base_account: solana_address::Address) -> &mut Self { - self.base_account = Some(base_account); - self - } - #[inline(always)] - pub fn destination(&mut self, destination: solana_address::Address) -> &mut Self { - self.destination = Some(destination); - self - } - #[inline(always)] - pub fn amount(&mut self, amount: u64) -> &mut Self { - self.amount = Some(amount); - self - } - #[inline(always)] - pub fn from_seed(&mut self, from_seed: String) -> &mut Self { - self.from_seed = Some(from_seed); - self - } - #[inline(always)] - pub fn from_owner(&mut self, from_owner: Address) -> &mut Self { - self.from_owner = Some(from_owner); - self + pub fn new( + source: solana_address::Address, + base_account: solana_address::Address, + destination: solana_address::Address, + amount: u64, + from_seed: String, + from_owner: Address, + ) -> Self { + Self { + source, + base_account, + destination, + amount, + from_seed, + from_owner, + __remaining_accounts: Vec::new(), + } } /// Add an additional account to the instruction. #[inline(always)] @@ -163,15 +148,18 @@ impl TransferSolWithSeedBuilder { } #[allow(clippy::clone_on_copy)] pub fn instruction(&self) -> solana_instruction::Instruction { + let source = self.source; + let base_account = self.base_account; + let destination = self.destination; let accounts = TransferSolWithSeed { - source: self.source.expect("source is not set"), - base_account: self.base_account.expect("base_account is not set"), - destination: self.destination.expect("destination is not set"), + source, + base_account, + destination, }; let args = TransferSolWithSeedInstructionArgs { - amount: self.amount.clone().expect("amount is not set"), - from_seed: self.from_seed.clone().expect("from_seed is not set"), - from_owner: self.from_owner.clone().expect("from_owner is not set"), + amount: self.amount.clone(), + from_seed: self.from_seed.clone(), + from_owner: self.from_owner.clone(), }; accounts.instruction_with_remaining_accounts(args, &self.__remaining_accounts) @@ -299,55 +287,27 @@ pub struct TransferSolWithSeedCpiBuilder<'a, 'b> { } impl<'a, 'b> TransferSolWithSeedCpiBuilder<'a, 'b> { - pub fn new(program: &'b solana_account_info::AccountInfo<'a>) -> Self { + pub fn new( + __program: &'b solana_account_info::AccountInfo<'a>, + source: &'b solana_account_info::AccountInfo<'a>, + base_account: &'b solana_account_info::AccountInfo<'a>, + destination: &'b solana_account_info::AccountInfo<'a>, + amount: u64, + from_seed: String, + from_owner: Address, + ) -> Self { let instruction = Box::new(TransferSolWithSeedCpiBuilderInstruction { - __program: program, - source: None, - base_account: None, - destination: None, - amount: None, - from_seed: None, - from_owner: None, + __program, + source, + base_account, + destination, + amount, + from_seed, + from_owner, __remaining_accounts: Vec::new(), }); Self { instruction } } - #[inline(always)] - pub fn source(&mut self, source: &'b solana_account_info::AccountInfo<'a>) -> &mut Self { - self.instruction.source = Some(source); - self - } - #[inline(always)] - pub fn base_account( - &mut self, - base_account: &'b solana_account_info::AccountInfo<'a>, - ) -> &mut Self { - self.instruction.base_account = Some(base_account); - self - } - #[inline(always)] - pub fn destination( - &mut self, - destination: &'b solana_account_info::AccountInfo<'a>, - ) -> &mut Self { - self.instruction.destination = Some(destination); - self - } - #[inline(always)] - pub fn amount(&mut self, amount: u64) -> &mut Self { - self.instruction.amount = Some(amount); - self - } - #[inline(always)] - pub fn from_seed(&mut self, from_seed: String) -> &mut Self { - self.instruction.from_seed = Some(from_seed); - self - } - #[inline(always)] - pub fn from_owner(&mut self, from_owner: Address) -> &mut Self { - self.instruction.from_owner = Some(from_owner); - self - } /// Add an additional account to the instruction. #[inline(always)] pub fn add_remaining_account( @@ -383,32 +343,15 @@ impl<'a, 'b> TransferSolWithSeedCpiBuilder<'a, 'b> { #[allow(clippy::vec_init_then_push)] pub fn invoke_signed(&self, signers_seeds: &[&[&[u8]]]) -> solana_program_error::ProgramResult { let args = TransferSolWithSeedInstructionArgs { - amount: self.instruction.amount.clone().expect("amount is not set"), - from_seed: self - .instruction - .from_seed - .clone() - .expect("from_seed is not set"), - from_owner: self - .instruction - .from_owner - .clone() - .expect("from_owner is not set"), + amount: self.instruction.amount.clone(), + from_seed: self.instruction.from_seed.clone(), + from_owner: self.instruction.from_owner.clone(), }; let instruction = TransferSolWithSeedCpi { __program: self.instruction.__program, - - source: self.instruction.source.expect("source is not set"), - - base_account: self - .instruction - .base_account - .expect("base_account is not set"), - - destination: self - .instruction - .destination - .expect("destination is not set"), + source: self.instruction.source, + base_account: self.instruction.base_account, + destination: self.instruction.destination, __args: args, }; instruction.invoke_signed_with_remaining_accounts( @@ -421,12 +364,12 @@ impl<'a, 'b> TransferSolWithSeedCpiBuilder<'a, 'b> { #[derive(Clone, Debug)] struct TransferSolWithSeedCpiBuilderInstruction<'a, 'b> { __program: &'b solana_account_info::AccountInfo<'a>, - source: Option<&'b solana_account_info::AccountInfo<'a>>, - base_account: Option<&'b solana_account_info::AccountInfo<'a>>, - destination: Option<&'b solana_account_info::AccountInfo<'a>>, - amount: Option, - from_seed: Option, - from_owner: Option
, + source: &'b solana_account_info::AccountInfo<'a>, + base_account: &'b solana_account_info::AccountInfo<'a>, + destination: &'b solana_account_info::AccountInfo<'a>, + amount: u64, + from_seed: String, + from_owner: Address, /// Additional instruction accounts `(AccountInfo, is_writable, is_signer)`. __remaining_accounts: Vec<(&'b solana_account_info::AccountInfo<'a>, bool, bool)>, } diff --git a/e2e/system/src/generated/instructions/upgrade_nonce_account.rs b/e2e/system/src/generated/instructions/upgrade_nonce_account.rs index 7de98bc..653123b 100644 --- a/e2e/system/src/generated/instructions/upgrade_nonce_account.rs +++ b/e2e/system/src/generated/instructions/upgrade_nonce_account.rs @@ -70,20 +70,18 @@ impl Default for UpgradeNonceAccountInstructionData { /// ### Accounts: /// /// 0. `[writable]` nonce_account -#[derive(Clone, Debug, Default)] +#[derive(Clone, Debug)] pub struct UpgradeNonceAccountBuilder { - nonce_account: Option, + nonce_account: solana_address::Address, __remaining_accounts: Vec, } impl UpgradeNonceAccountBuilder { - pub fn new() -> Self { - Self::default() - } - #[inline(always)] - pub fn nonce_account(&mut self, nonce_account: solana_address::Address) -> &mut Self { - self.nonce_account = Some(nonce_account); - self + pub fn new(nonce_account: solana_address::Address) -> Self { + Self { + nonce_account, + __remaining_accounts: Vec::new(), + } } /// Add an additional account to the instruction. #[inline(always)] @@ -102,9 +100,8 @@ impl UpgradeNonceAccountBuilder { } #[allow(clippy::clone_on_copy)] pub fn instruction(&self) -> solana_instruction::Instruction { - let accounts = UpgradeNonceAccount { - nonce_account: self.nonce_account.expect("nonce_account is not set"), - }; + let nonce_account = self.nonce_account; + let accounts = UpgradeNonceAccount { nonce_account }; accounts.instruction_with_remaining_accounts(&self.__remaining_accounts) } @@ -203,22 +200,17 @@ pub struct UpgradeNonceAccountCpiBuilder<'a, 'b> { } impl<'a, 'b> UpgradeNonceAccountCpiBuilder<'a, 'b> { - pub fn new(program: &'b solana_account_info::AccountInfo<'a>) -> Self { + pub fn new( + __program: &'b solana_account_info::AccountInfo<'a>, + nonce_account: &'b solana_account_info::AccountInfo<'a>, + ) -> Self { let instruction = Box::new(UpgradeNonceAccountCpiBuilderInstruction { - __program: program, - nonce_account: None, + __program, + nonce_account, __remaining_accounts: Vec::new(), }); Self { instruction } } - #[inline(always)] - pub fn nonce_account( - &mut self, - nonce_account: &'b solana_account_info::AccountInfo<'a>, - ) -> &mut Self { - self.instruction.nonce_account = Some(nonce_account); - self - } /// Add an additional account to the instruction. #[inline(always)] pub fn add_remaining_account( @@ -255,11 +247,7 @@ impl<'a, 'b> UpgradeNonceAccountCpiBuilder<'a, 'b> { pub fn invoke_signed(&self, signers_seeds: &[&[&[u8]]]) -> solana_program_error::ProgramResult { let instruction = UpgradeNonceAccountCpi { __program: self.instruction.__program, - - nonce_account: self - .instruction - .nonce_account - .expect("nonce_account is not set"), + nonce_account: self.instruction.nonce_account, }; instruction.invoke_signed_with_remaining_accounts( signers_seeds, @@ -271,7 +259,7 @@ impl<'a, 'b> UpgradeNonceAccountCpiBuilder<'a, 'b> { #[derive(Clone, Debug)] struct UpgradeNonceAccountCpiBuilderInstruction<'a, 'b> { __program: &'b solana_account_info::AccountInfo<'a>, - nonce_account: Option<&'b solana_account_info::AccountInfo<'a>>, + nonce_account: &'b solana_account_info::AccountInfo<'a>, /// Additional instruction accounts `(AccountInfo, is_writable, is_signer)`. __remaining_accounts: Vec<(&'b solana_account_info::AccountInfo<'a>, bool, bool)>, } diff --git a/e2e/system/src/generated/instructions/withdraw_nonce_account.rs b/e2e/system/src/generated/instructions/withdraw_nonce_account.rs index da43d7d..8f33967 100644 --- a/e2e/system/src/generated/instructions/withdraw_nonce_account.rs +++ b/e2e/system/src/generated/instructions/withdraw_nonce_account.rs @@ -115,30 +115,33 @@ impl WithdrawNonceAccountInstructionArgs { /// 2. `[optional]` recent_blockhashes_sysvar (default to `SysvarRecentB1ockHashes11111111111111111111`) /// 3. `[optional]` rent_sysvar (default to `SysvarRent111111111111111111111111111111111`) /// 4. `[signer]` nonce_authority -#[derive(Clone, Debug, Default)] +#[derive(Clone, Debug)] pub struct WithdrawNonceAccountBuilder { - nonce_account: Option, - recipient_account: Option, + nonce_account: solana_address::Address, + recipient_account: solana_address::Address, recent_blockhashes_sysvar: Option, rent_sysvar: Option, - nonce_authority: Option, - withdraw_amount: Option, + nonce_authority: solana_address::Address, + withdraw_amount: u64, __remaining_accounts: Vec, } impl WithdrawNonceAccountBuilder { - pub fn new() -> Self { - Self::default() - } - #[inline(always)] - pub fn nonce_account(&mut self, nonce_account: solana_address::Address) -> &mut Self { - self.nonce_account = Some(nonce_account); - self - } - #[inline(always)] - pub fn recipient_account(&mut self, recipient_account: solana_address::Address) -> &mut Self { - self.recipient_account = Some(recipient_account); - self + pub fn new( + nonce_account: solana_address::Address, + recipient_account: solana_address::Address, + nonce_authority: solana_address::Address, + withdraw_amount: u64, + ) -> Self { + Self { + nonce_account, + recipient_account, + recent_blockhashes_sysvar: None, + rent_sysvar: None, + nonce_authority, + withdraw_amount, + __remaining_accounts: Vec::new(), + } } /// `[optional account, default to 'SysvarRecentB1ockHashes11111111111111111111']` #[inline(always)] @@ -155,16 +158,6 @@ impl WithdrawNonceAccountBuilder { self.rent_sysvar = Some(rent_sysvar); self } - #[inline(always)] - pub fn nonce_authority(&mut self, nonce_authority: solana_address::Address) -> &mut Self { - self.nonce_authority = Some(nonce_authority); - self - } - #[inline(always)] - pub fn withdraw_amount(&mut self, withdraw_amount: u64) -> &mut Self { - self.withdraw_amount = Some(withdraw_amount); - self - } /// Add an additional account to the instruction. #[inline(always)] pub fn add_remaining_account(&mut self, account: solana_instruction::AccountMeta) -> &mut Self { @@ -182,24 +175,26 @@ impl WithdrawNonceAccountBuilder { } #[allow(clippy::clone_on_copy)] pub fn instruction(&self) -> solana_instruction::Instruction { + let nonce_account = self.nonce_account; + let recipient_account = self.recipient_account; + let recent_blockhashes_sysvar = + self.recent_blockhashes_sysvar + .unwrap_or(solana_address::address!( + "SysvarRecentB1ockHashes11111111111111111111" + )); + let rent_sysvar = self.rent_sysvar.unwrap_or(solana_address::address!( + "SysvarRent111111111111111111111111111111111" + )); + let nonce_authority = self.nonce_authority; let accounts = WithdrawNonceAccount { - nonce_account: self.nonce_account.expect("nonce_account is not set"), - recipient_account: self - .recipient_account - .expect("recipient_account is not set"), - recent_blockhashes_sysvar: self.recent_blockhashes_sysvar.unwrap_or( - solana_address::address!("SysvarRecentB1ockHashes11111111111111111111"), - ), - rent_sysvar: self.rent_sysvar.unwrap_or(solana_address::address!( - "SysvarRent111111111111111111111111111111111" - )), - nonce_authority: self.nonce_authority.expect("nonce_authority is not set"), + nonce_account, + recipient_account, + recent_blockhashes_sysvar, + rent_sysvar, + nonce_authority, }; let args = WithdrawNonceAccountInstructionArgs { - withdraw_amount: self - .withdraw_amount - .clone() - .expect("withdraw_amount is not set"), + withdraw_amount: self.withdraw_amount.clone(), }; accounts.instruction_with_remaining_accounts(args, &self.__remaining_accounts) @@ -349,63 +344,26 @@ pub struct WithdrawNonceAccountCpiBuilder<'a, 'b> { } impl<'a, 'b> WithdrawNonceAccountCpiBuilder<'a, 'b> { - pub fn new(program: &'b solana_account_info::AccountInfo<'a>) -> Self { - let instruction = Box::new(WithdrawNonceAccountCpiBuilderInstruction { - __program: program, - nonce_account: None, - recipient_account: None, - recent_blockhashes_sysvar: None, - rent_sysvar: None, - nonce_authority: None, - withdraw_amount: None, - __remaining_accounts: Vec::new(), - }); - Self { instruction } - } - #[inline(always)] - pub fn nonce_account( - &mut self, + pub fn new( + __program: &'b solana_account_info::AccountInfo<'a>, nonce_account: &'b solana_account_info::AccountInfo<'a>, - ) -> &mut Self { - self.instruction.nonce_account = Some(nonce_account); - self - } - #[inline(always)] - pub fn recipient_account( - &mut self, recipient_account: &'b solana_account_info::AccountInfo<'a>, - ) -> &mut Self { - self.instruction.recipient_account = Some(recipient_account); - self - } - #[inline(always)] - pub fn recent_blockhashes_sysvar( - &mut self, recent_blockhashes_sysvar: &'b solana_account_info::AccountInfo<'a>, - ) -> &mut Self { - self.instruction.recent_blockhashes_sysvar = Some(recent_blockhashes_sysvar); - self - } - #[inline(always)] - pub fn rent_sysvar( - &mut self, rent_sysvar: &'b solana_account_info::AccountInfo<'a>, - ) -> &mut Self { - self.instruction.rent_sysvar = Some(rent_sysvar); - self - } - #[inline(always)] - pub fn nonce_authority( - &mut self, nonce_authority: &'b solana_account_info::AccountInfo<'a>, - ) -> &mut Self { - self.instruction.nonce_authority = Some(nonce_authority); - self - } - #[inline(always)] - pub fn withdraw_amount(&mut self, withdraw_amount: u64) -> &mut Self { - self.instruction.withdraw_amount = Some(withdraw_amount); - self + withdraw_amount: u64, + ) -> Self { + let instruction = Box::new(WithdrawNonceAccountCpiBuilderInstruction { + __program, + nonce_account, + recipient_account, + recent_blockhashes_sysvar, + rent_sysvar, + nonce_authority, + withdraw_amount, + __remaining_accounts: Vec::new(), + }); + Self { instruction } } /// Add an additional account to the instruction. #[inline(always)] @@ -442,39 +400,15 @@ impl<'a, 'b> WithdrawNonceAccountCpiBuilder<'a, 'b> { #[allow(clippy::vec_init_then_push)] pub fn invoke_signed(&self, signers_seeds: &[&[&[u8]]]) -> solana_program_error::ProgramResult { let args = WithdrawNonceAccountInstructionArgs { - withdraw_amount: self - .instruction - .withdraw_amount - .clone() - .expect("withdraw_amount is not set"), + withdraw_amount: self.instruction.withdraw_amount.clone(), }; let instruction = WithdrawNonceAccountCpi { __program: self.instruction.__program, - - nonce_account: self - .instruction - .nonce_account - .expect("nonce_account is not set"), - - recipient_account: self - .instruction - .recipient_account - .expect("recipient_account is not set"), - - recent_blockhashes_sysvar: self - .instruction - .recent_blockhashes_sysvar - .expect("recent_blockhashes_sysvar is not set"), - - rent_sysvar: self - .instruction - .rent_sysvar - .expect("rent_sysvar is not set"), - - nonce_authority: self - .instruction - .nonce_authority - .expect("nonce_authority is not set"), + nonce_account: self.instruction.nonce_account, + recipient_account: self.instruction.recipient_account, + recent_blockhashes_sysvar: self.instruction.recent_blockhashes_sysvar, + rent_sysvar: self.instruction.rent_sysvar, + nonce_authority: self.instruction.nonce_authority, __args: args, }; instruction.invoke_signed_with_remaining_accounts( @@ -487,12 +421,12 @@ impl<'a, 'b> WithdrawNonceAccountCpiBuilder<'a, 'b> { #[derive(Clone, Debug)] struct WithdrawNonceAccountCpiBuilderInstruction<'a, 'b> { __program: &'b solana_account_info::AccountInfo<'a>, - nonce_account: Option<&'b solana_account_info::AccountInfo<'a>>, - recipient_account: Option<&'b solana_account_info::AccountInfo<'a>>, - recent_blockhashes_sysvar: Option<&'b solana_account_info::AccountInfo<'a>>, - rent_sysvar: Option<&'b solana_account_info::AccountInfo<'a>>, - nonce_authority: Option<&'b solana_account_info::AccountInfo<'a>>, - withdraw_amount: Option, + nonce_account: &'b solana_account_info::AccountInfo<'a>, + recipient_account: &'b solana_account_info::AccountInfo<'a>, + recent_blockhashes_sysvar: &'b solana_account_info::AccountInfo<'a>, + rent_sysvar: &'b solana_account_info::AccountInfo<'a>, + nonce_authority: &'b solana_account_info::AccountInfo<'a>, + withdraw_amount: u64, /// Additional instruction accounts `(AccountInfo, is_writable, is_signer)`. __remaining_accounts: Vec<(&'b solana_account_info::AccountInfo<'a>, bool, bool)>, } diff --git a/public/templates/instructionsCpiPageBuilder.njk b/public/templates/instructionsCpiPageBuilder.njk index cb1b0e6..d6b893a 100644 --- a/public/templates/instructionsCpiPageBuilder.njk +++ b/public/templates/instructionsCpiPageBuilder.njk @@ -10,10 +10,13 @@ {% if account.isSigner %} {% set modifiers = modifiers + ', signer' if modifiers.length > 0 else 'signer' %} {% endif %} - {% if account.isOptional %} + {% set isBuilderOptional = account.name in cpiBuilderOptionalAccounts %} + {% if isBuilderOptional %} {% set modifiers = modifiers + ', optional' if modifiers.length > 0 else 'optional' %} {% endif %} {{ '/// ' + loop.index0 + '. `[' + modifiers + ']` ' + account.name | snakeCase }} + {{- " (default to `" + account.defaultValue.publicKey + "`)" if isBuilderOptional and account.defaultValue.kind === 'publicKeyValueNode' }} + {{- " (default to PDA derived from '" + account.defaultValue.pda.name + "')" if isBuilderOptional and account.defaultValue.kind === 'pdaValueNode' and (account.defaultValue.pda.kind === 'pdaLinkNode' or account.defaultValue.pda.kind === 'pdaNode') }} {% endfor %} #[derive(Clone, Debug)] pub struct {{ instruction.name | pascalCase }}CpiBuilder<'a, 'b> { @@ -21,15 +24,37 @@ pub struct {{ instruction.name | pascalCase }}CpiBuilder<'a, 'b> { } impl<'a, 'b> {{ instruction.name | pascalCase }}CpiBuilder<'a, 'b> { - pub fn new(program: &'b solana_account_info::AccountInfo<'a>) -> Self { + pub fn new( + __program: &'b solana_account_info::AccountInfo<'a>, + {% for account in instruction.accounts %} + {% set isBuilderOptional = account.name in cpiBuilderOptionalAccounts %} + {% if not isBuilderOptional %} + {{ account.name | snakeCase }}: {{ "(&'b solana_account_info::AccountInfo<'a>, bool)" if account.isSigner === 'either' else "&'b solana_account_info::AccountInfo<'a>" }}, + {% endif %} + {% endfor %} + {% for arg in instructionArgs %} + {% if not arg.default and not arg.optional and not arg.innerOptionType %} + {{ arg.name | snakeCase }}: {{ arg.type }}, + {% endif %} + {% endfor %} + ) -> Self { let instruction = Box::new({{ instruction.name | pascalCase }}CpiBuilderInstruction { - __program: program, + __program, {% for account in instruction.accounts %} - {{ account.name | snakeCase }}: None, + {% set isBuilderOptional = account.name in cpiBuilderOptionalAccounts %} + {% if isBuilderOptional %} + {{ account.name | snakeCase }}: None, + {% else %} + {{ account.name | snakeCase }}, + {% endif %} {% endfor %} {% for arg in instructionArgs %} {% if not arg.default %} - {{ arg.name | snakeCase }}: None, + {% if not arg.optional and not arg.innerOptionType %} + {{ arg.name | snakeCase }}, + {% else %} + {{ arg.name | snakeCase }}: None, + {% endif %} {% endif %} {% endfor %} __remaining_accounts: Vec::new(), @@ -37,32 +62,35 @@ impl<'a, 'b> {{ instruction.name | pascalCase }}CpiBuilder<'a, 'b> { Self { instruction } } {% for account in instruction.accounts %} - {{'/// `[optional account]`\n' if account.isOptional }} - {{- macros.docblock(account.docs) -}} - #[inline(always)] - pub fn {{ account.name | snakeCase }}(&mut self, {{ account.name | snakeCase }}: {{ "Option<&'b solana_account_info::AccountInfo<'a>>" if account.isOptional else "&'b solana_account_info::AccountInfo<'a>" }}{{ ', as_signer: bool' if account.isSigner === 'either' }}) -> &mut Self { - {% if account.isOptional %} - {% if account.isSigner === 'either' %} - if let Some({{ account.name | snakeCase }}) = {{ account.name | snakeCase }} { - self.instruction.{{ account.name | snakeCase }} = Some(({{ account.name | snakeCase }}, as_signer)); - } else { - self.instruction.{{ account.name | snakeCase }} = None; - } - {% else %} - self.instruction.{{ account.name | snakeCase }} = {{ account.name | snakeCase }}; - {% endif %} - {% else %} - {% if account.isSigner === 'either' %} - self.instruction.{{ account.name | snakeCase }} = Some(({{ account.name | snakeCase }}, as_signer)); + {% set isBuilderOptional = account.name in cpiBuilderOptionalAccounts %} + {% if isBuilderOptional %} + {{'/// `[optional account]`\n' if account.isOptional }} + {{- macros.docblock(account.docs) -}} + #[inline(always)] + pub fn {{ account.name | snakeCase }}(&mut self, {{ account.name | snakeCase }}: {{ "Option<&'b solana_account_info::AccountInfo<'a>>" if account.isOptional else "&'b solana_account_info::AccountInfo<'a>" }}{{ ', as_signer: bool' if account.isSigner === 'either' }}) -> &mut Self { + {% if account.isOptional %} + {% if account.isSigner === 'either' %} + if let Some({{ account.name | snakeCase }}) = {{ account.name | snakeCase }} { + self.instruction.{{ account.name | snakeCase }} = Some(({{ account.name | snakeCase }}, as_signer)); + } else { + self.instruction.{{ account.name | snakeCase }} = None; + } + {% else %} + self.instruction.{{ account.name | snakeCase }} = {{ account.name | snakeCase }}; + {% endif %} {% else %} - self.instruction.{{ account.name | snakeCase }} = Some({{ account.name | snakeCase }}); + {% if account.isSigner === 'either' %} + self.instruction.{{ account.name | snakeCase }} = Some(({{ account.name | snakeCase }}, as_signer)); + {% else %} + self.instruction.{{ account.name | snakeCase }} = Some({{ account.name | snakeCase }}); + {% endif %} {% endif %} - {% endif %} - self - } + self + } + {% endif %} {% endfor %} {% for arg in instructionArgs %} - {% if not arg.default %} + {% if not arg.default and (arg.optional or arg.innerOptionType) %} {{'/// `[optional argument]`\n' if arg.innerOptionType }} {{- "/// `[optional argument, defaults to '" + arg.value + "']`\n" if not arg.innerOptionType and arg.value -}} {{- macros.docblock(arg.docs) -}} @@ -105,8 +133,10 @@ impl<'a, 'b> {{ instruction.name | pascalCase }}CpiBuilder<'a, 'b> { {% else %} {{ arg.name | snakeCase }}: self.instruction.{{ arg.name | snakeCase }}.clone(){{ '.unwrap_or(' + arg.value + ')' if arg.value else '.expect(\"' + arg.name | snakeCase + ' is not set\")' }}, {% endif %} + {% elif arg.innerOptionType %} + {{ arg.name | snakeCase }}: self.instruction.{{ arg.name | snakeCase }}.clone(), {% else %} - {{ arg.name | snakeCase }}: self.instruction.{{ arg.name | snakeCase }}.clone(){{ '.expect(\"' + arg.name | snakeCase + ' is not set\")' if not arg.innerOptionType }}, + {{ arg.name | snakeCase }}: self.instruction.{{ arg.name | snakeCase }}.clone(), {% endif %} {% endif %} {% endfor %} @@ -114,8 +144,17 @@ impl<'a, 'b> {{ instruction.name | pascalCase }}CpiBuilder<'a, 'b> { {% endif %} let instruction = {{ instruction.name | pascalCase }}Cpi { __program: self.instruction.__program, - {% for account in instruction.accounts %} - {{ account.name | snakeCase }}: self.instruction.{{ account.name | snakeCase }}{{ '.expect(\"' + account.name | snakeCase + ' is not set\")' if not account.isOptional }}, + {% for account in instruction.accounts %} + {% set isBuilderOptional = account.name in cpiBuilderOptionalAccounts %} + {% if account.isOptional %} + {{ account.name | snakeCase }}: self.instruction.{{ account.name | snakeCase }}, + {% elif not isBuilderOptional %} + {{ account.name | snakeCase }}: self.instruction.{{ account.name | snakeCase }}, + {% elif account.defaultValue.kind === 'programIdValueNode' %} + {{ account.name | snakeCase }}: self.instruction.{{ account.name | snakeCase }}.unwrap_or(self.instruction.__program), + {% else %} + {{ account.name | snakeCase }}: self.instruction.{{ account.name | snakeCase }}.expect("{{ account.name | snakeCase }} is not set"), + {% endif %} {% endfor %} {% if hasArgs %} __args: args, @@ -129,15 +168,29 @@ impl<'a, 'b> {{ instruction.name | pascalCase }}CpiBuilder<'a, 'b> { struct {{ instruction.name | pascalCase }}CpiBuilderInstruction<'a, 'b> { __program: &'b solana_account_info::AccountInfo<'a>, {% for account in instruction.accounts %} + {% set isBuilderOptional = account.name in cpiBuilderOptionalAccounts %} {% if account.isSigner === 'either' %} - {{ account.name | snakeCase }}: Option<(&'b solana_account_info::AccountInfo<'a>, bool)>, + {% if isBuilderOptional %} + {{ account.name | snakeCase }}: Option<(&'b solana_account_info::AccountInfo<'a>, bool)>, + {% else %} + {{ account.name | snakeCase }}: (&'b solana_account_info::AccountInfo<'a>, bool), + {% endif %} {% else %} - {{ account.name | snakeCase }}: Option<&'b solana_account_info::AccountInfo<'a>>, + {% if isBuilderOptional %} + {{ account.name | snakeCase }}: Option<&'b solana_account_info::AccountInfo<'a>>, + {% else %} + {{ account.name | snakeCase }}: &'b solana_account_info::AccountInfo<'a>, + {% endif %} {% endif %} {% endfor %} {% for arg in instructionArgs %} {% if not arg.default %} - {{ arg.name | snakeCase }}: {{ arg.type if arg.innerOptionType else 'Option<' + arg.type + '>' }}, + {% set isArgOptional = arg.optional or arg.innerOptionType %} + {% if isArgOptional %} + {{ arg.name | snakeCase }}: {{ arg.type if arg.innerOptionType else 'Option<' + arg.type + '>' }}, + {% else %} + {{ arg.name | snakeCase }}: {{ arg.type }}, + {% endif %} {% endif %} {% endfor %} /// Additional instruction accounts `(AccountInfo, is_writable, is_signer)`. diff --git a/public/templates/instructionsPageBuilder.njk b/public/templates/instructionsPageBuilder.njk index ac73d21..46fe008 100644 --- a/public/templates/instructionsPageBuilder.njk +++ b/public/templates/instructionsPageBuilder.njk @@ -16,67 +16,113 @@ {% if account.isSigner %} {% set modifiers = modifiers + ', signer' if modifiers.length > 0 else 'signer' %} {% endif %} - {% if account.isOptional or account.defaultValue.kind === 'publicKeyValueNode' or (account.defaultValue.kind === 'pdaValueNode' and account.name in pdaResolved) %} + {% set isBuilderOptional = account.name in builderOptionalAccounts %} + {% if isBuilderOptional %} {% set modifiers = modifiers + ', optional' if modifiers.length > 0 else 'optional' %} {% endif %} {{ '/// ' + loop.index0 + '. `[' + modifiers + ']` ' + account.name | snakeCase }} {{- " (default to `" + account.defaultValue.publicKey + "`)" if account.defaultValue.kind === 'publicKeyValueNode' }} {{- " (default to PDA derived from '" + account.defaultValue.pda.name + "')" if account.defaultValue.kind === 'pdaValueNode' and account.name in pdaResolved }} {% endfor %} -#[derive(Clone, Debug, Default)] +#[derive(Clone, Debug{{ ', Default' if not hasRequiredAccounts and not hasRequiredArgs }})] pub struct {{ instruction.name | pascalCase }}Builder { {% for account in instruction.accounts %} + {% set isBuilderOptional = account.name in builderOptionalAccounts %} {% if account.isSigner === 'either' %} - {{ account.name | snakeCase }}: Option<(solana_address::Address, bool)>, + {{ account.name | snakeCase }}: {{ 'Option<(solana_address::Address, bool)>' if isBuilderOptional else '(solana_address::Address, bool)' }}, {% else %} - {{ account.name | snakeCase }}: Option, + {{ account.name | snakeCase }}: {{ 'Option' if isBuilderOptional else 'solana_address::Address' }}, {% endif %} {% endfor %} {% for arg in instructionArgs %} {% if not arg.default %} - {{ arg.name | snakeCase }}: {{ arg.type if arg.innerOptionType else 'Option<' + arg.type + '>' }}, + {% set isArgOptional = arg.optional or arg.innerOptionType %} + {% if isArgOptional %} + {{ arg.name | snakeCase }}: {{ arg.type if arg.innerOptionType else 'Option<' + arg.type + '>' }}, + {% else %} + {{ arg.name | snakeCase }}: {{ arg.type }}, + {% endif %} {% endif %} {% endfor %} __remaining_accounts: Vec, } impl {{ instruction.name | pascalCase }}Builder { - pub fn new() -> Self { - Self::default() - } + {% if hasRequiredAccounts or hasRequiredArgs %} + pub fn new( + {% for account in instruction.accounts %} + {% set isBuilderOptional = account.name in builderOptionalAccounts %} + {% if not isBuilderOptional %} + {{ account.name | snakeCase }}: {{ '(solana_address::Address, bool)' if account.isSigner === 'either' else 'solana_address::Address' }}, + {% endif %} + {% endfor %} + {% for arg in instructionArgs %} + {% if not arg.default and not arg.optional and not arg.innerOptionType %} + {{ arg.name | snakeCase }}: {{ arg.type }}, + {% endif %} + {% endfor %} + ) -> Self { + Self { + {% for account in instruction.accounts %} + {% set isBuilderOptional = account.name in builderOptionalAccounts %} + {% if isBuilderOptional %} + {{ account.name | snakeCase }}: None, + {% else %} + {{ account.name | snakeCase }}, + {% endif %} + {% endfor %} + {% for arg in instructionArgs %} + {% if not arg.default %} + {% if not arg.optional and not arg.innerOptionType %} + {{ arg.name | snakeCase }}, + {% else %} + {{ arg.name | snakeCase }}: None, + {% endif %} + {% endif %} + {% endfor %} + __remaining_accounts: Vec::new(), + } + } + {% else %} + pub fn new() -> Self { + Self::default() + } + {% endif %} {% for account in instruction.accounts %} - {% if account.isOptional %} - {{ '/// `[optional account]`\n' -}} - {% elif account.defaultValue.kind === 'publicKeyValueNode' %} - {{ "/// `[optional account, default to '" + account.defaultValue.publicKey + "']`\n" -}} - {% elif account.defaultValue.kind === 'pdaValueNode' and account.name in pdaResolved %} - {{ "/// `[optional account, default to PDA derived from '" + account.defaultValue.pda.name + "']`\n" -}} - {% endif %} - {{- macros.docblock(account.docs) -}} - #[inline(always)] - pub fn {{ account.name | snakeCase }}(&mut self, {{ account.name | snakeCase }}: {{ 'Option' if account.isOptional else 'solana_address::Address' }}{{ ', as_signer: bool' if account.isSigner === 'either' }}) -> &mut Self { + {% set isBuilderOptional = account.name in builderOptionalAccounts %} + {% if isBuilderOptional %} {% if account.isOptional %} - {% if account.isSigner === 'either' %} - if let Some({{ account.name | snakeCase }}) = {{ account.name | snakeCase }} { - self.{{ account.name | snakeCase }} = Some(({{ account.name | snakeCase }}, as_signer)); - } else { - self.{{ account.name | snakeCase }} = None; - } - {% else %} - self.{{ account.name | snakeCase }} = {{ account.name | snakeCase }}; - {% endif %} + {{ '/// `[optional account]`\n' -}} {% else %} - {% if account.isSigner === 'either' %} - self.{{ account.name | snakeCase }} = Some(({{ account.name | snakeCase }}, as_signer)); + {{ "/// `[optional account, default to '" + account.defaultValue.publicKey + "']`\n" if account.defaultValue.kind === 'publicKeyValueNode' -}} + {{ "/// `[optional account, default to PDA derived from '" + account.defaultValue.pda.name + "']`\n" if account.defaultValue.kind === 'pdaValueNode' and account.name in pdaResolved -}} + {% endif %} + {{- macros.docblock(account.docs) -}} + #[inline(always)] + pub fn {{ account.name | snakeCase }}(&mut self, {{ account.name | snakeCase }}: {{ 'Option' if account.isOptional else 'solana_address::Address' }}{{ ', as_signer: bool' if account.isSigner === 'either' }}) -> &mut Self { + {% if account.isOptional %} + {% if account.isSigner === 'either' %} + if let Some({{ account.name | snakeCase }}) = {{ account.name | snakeCase }} { + self.{{ account.name | snakeCase }} = Some(({{ account.name | snakeCase }}, as_signer)); + } else { + self.{{ account.name | snakeCase }} = None; + } + {% else %} + self.{{ account.name | snakeCase }} = {{ account.name | snakeCase }}; + {% endif %} {% else %} - self.{{ account.name | snakeCase }} = Some({{ account.name | snakeCase }}); + {% if account.isSigner === 'either' %} + self.{{ account.name | snakeCase }} = Some(({{ account.name | snakeCase }}, as_signer)); + {% else %} + self.{{ account.name | snakeCase }} = Some({{ account.name | snakeCase }}); + {% endif %} {% endif %} - {% endif %} - self - } + self + } + {% endif %} {% endfor %} {% for arg in instructionArgs %} - {% if not arg.default %} + {% if not arg.default and (arg.optional or arg.innerOptionType) %} {{ '/// `[optional argument]`\n' if arg.innerOptionType }} {{- "/// `[optional argument, defaults to '" + arg.value + "']`\n" if not arg.innerOptionType and arg.value -}} {{- macros.docblock(arg.docs) -}} @@ -135,21 +181,19 @@ impl {{ instruction.name | pascalCase }}Builder { {% endif %} }); {% endif %} + {% elif account.isOptional %} + let {{ account.name | snakeCase }} = self.{{ account.name | snakeCase }}; + {% elif account.defaultValue.kind === 'programIdValueNode' %} + let {{ account.name | snakeCase }} = self.{{ account.name | snakeCase }}.unwrap_or(crate::{{ program.name | snakeCase | upper }}_ID); + {% elif account.defaultValue.kind === 'publicKeyValueNode' %} + let {{ account.name | snakeCase }} = self.{{ account.name | snakeCase }}.unwrap_or(solana_address::address!("{{ account.defaultValue.publicKey }}")); + {% else %} + let {{ account.name | snakeCase }} = self.{{ account.name | snakeCase }}; {% endif %} {% endfor %} let accounts = {{ instruction.name | pascalCase }} { {% for account in instruction.accounts %} - {% if account.isOptional %} - {{ account.name | snakeCase }}: self.{{ account.name | snakeCase }}, - {% elif account.defaultValue.kind === 'programId' %} - {{ account.name | snakeCase }}: self.{{ account.name | snakeCase }}, - {% elif account.defaultValue.kind === 'publicKeyValueNode' %} - {{ account.name | snakeCase }}: self.{{ account.name | snakeCase }}.unwrap_or(solana_address::address!("{{ account.defaultValue.publicKey }}")), - {% elif account.name in pdaResolved %} {{ account.name | snakeCase }}, - {% else %} - {{ account.name | snakeCase }}: self.{{ account.name | snakeCase }}.expect("{{ account.name | snakeCase }} is not set"), - {% endif %} {% endfor %} }; {% if hasArgs %} @@ -162,8 +206,10 @@ impl {{ instruction.name | pascalCase }}Builder { {% else %} {{ arg.name | snakeCase }}: self.{{ arg.name | snakeCase }}.clone(){{ '.unwrap_or(' + arg.value + ')' if arg.value else '.expect(\"' + arg.name | snakeCase + ' is not set\")' }}, {% endif %} + {% elif arg.innerOptionType %} + {{ arg.name | snakeCase }}: self.{{ arg.name | snakeCase }}.clone(), {% else %} - {{ arg.name | snakeCase }}: self.{{ arg.name | snakeCase }}.clone(){{ '.expect(\"' + arg.name | snakeCase + ' is not set\")' if not arg.innerOptionType }}, + {{ arg.name | snakeCase }}: self.{{ arg.name | snakeCase }}.clone(), {% endif %} {% endif %} {% endfor %} diff --git a/src/getRenderMapVisitor.ts b/src/getRenderMapVisitor.ts index 4618ba1..2c7c9a1 100644 --- a/src/getRenderMapVisitor.ts +++ b/src/getRenderMapVisitor.ts @@ -276,30 +276,68 @@ export function getRenderMapVisitor(options: GetRenderMapOptions = {}) { .mergeWith(discriminatorConstants.imports) .remove(`generatedInstructions::${pascalCase(node.name)}`); + // Accounts that are optional in the builder (have defaults or are IDL-optional). + const builderOptionalAccounts = new Set( + node.accounts + .filter( + account => + account.isOptional || + (account.defaultValue != null && + (isNode(account.defaultValue, ['publicKeyValueNode', 'programIdValueNode']) || + account.defaultValue.kind === 'pdaValueNode')), + ) + .map(a => a.name), + ); + // CPI can't derive AccountInfo from PDA/publicKey defaults. + const cpiBuilderOptionalAccounts = new Set( + node.accounts + .filter( + account => + account.isOptional || + (account.defaultValue != null && + isNode(account.defaultValue, ['programIdValueNode'])), + ) + .map(a => a.name), + ); + const hasRequiredAccounts = node.accounts.some(a => !builderOptionalAccounts.has(a.name)); + const hasRequiredArgs = instructionArgs.some( + arg => !arg.default && !arg.optional && !arg.innerOptionType, + ); + const requiredArgNames = instructionArgs + .filter(arg => !arg.default && !arg.optional && !arg.innerOptionType) + .map(arg => snakeCase(arg.name)); + // Resolve PDA defaults and topologically sort accounts by dependency. const resolvedAccounts = resolveInstructionPdaDefaults({ accounts: node.accounts, accountsAndArgsConflicts, + builderOptionalAccounts, getImportFrom, imports, instructionArguments: node.arguments, instructionName: node.name, linkables, program, + requiredArgNames, stack, }); return createRenderMap(`instructions/${snakeCase(node.name)}.rs`, { content: render('instructionsPage.njk', { accountsAndArgsConflicts, + builderOptionalAccounts: [...builderOptionalAccounts], + cpiBuilderOptionalAccounts: [...cpiBuilderOptionalAccounts], dataTraits: dataTraits.render, discriminatorConstants: discriminatorConstants.render, hasArgs, hasOptional, + hasRequiredAccounts, + hasRequiredArgs, imports: imports.toString(dependencyMap), instruction: node, instructionArgs, program, + requiredArgNames, resolvedAccounts, typeManifest, }), @@ -501,23 +539,27 @@ type ResolvedAccount = InstructionAccountNode & { function resolveInstructionPdaDefaults(ctx: { accounts: readonly InstructionAccountNode[]; accountsAndArgsConflicts: string[]; + builderOptionalAccounts: Set; getImportFrom: GetImportFromFunction; imports: ImportMap; instructionArguments: readonly InstructionArgumentNode[]; instructionName: string; linkables: LinkableDictionary; program: ProgramNode; + requiredArgNames: string[]; stack: NodeStack; }): ResolvedAccount[] { const { accounts, accountsAndArgsConflicts, + builderOptionalAccounts, getImportFrom, imports, instructionArguments, instructionName, linkables, program, + requiredArgNames, stack, } = ctx; @@ -592,11 +634,19 @@ function resolveInstructionPdaDefaults(ctx: { if (isNode(seedValue, 'accountValueNode')) { const refName = snakeCase(seedValue.name); const isEither = eitherSignerAccounts.has(seedValue.name); - const eitherExtract = isEither ? '.map(|(k, _)| k)' : ''; + const isOptional = builderOptionalAccounts.has(seedValue.name); + const eitherExtract = isEither ? (isOptional ? '.map(|(k, _)| k)' : '.0') : ''; if (pdaDefaultedNames.has(seedValue.name)) { accountDeps.push(seedValue.name); renderedSeeds.push({ kind: 'accountRef', rawName: refName, render: `&${refName}` }); + } else if (!isOptional) { + // Required account — direct field access, no Option unwrap. + renderedSeeds.push({ + kind: 'accountRef', + rawName: refName, + render: `&self.${refName}${eitherExtract}`, + }); } else { const defaultExpr = accountDefaults[seedValue.name]; let render: string; @@ -612,6 +662,7 @@ function resolveInstructionPdaDefaults(ctx: { ? `${seedValue.name}_arg` : seedValue.name; const fieldName = snakeCase(argFieldName); + const isRequiredArg = requiredArgNames.includes(fieldName); const arg = instructionArguments.find(a => a.name === seedValue.name); let argDefault: { isOmitted: boolean; value: string } | null = null; @@ -636,6 +687,12 @@ function resolveInstructionPdaDefaults(ctx: { kind: 'argumentRef', render: `${isByRef ? '&' : ''}${argDefault.value}`, }); + } else if (isRequiredArg) { + // Required arg — direct field access, no Option unwrap. + renderedSeeds.push({ + kind: 'argumentRef', + render: `${isByRef ? '&' : ''}self.${fieldName}.clone()`, + }); } else { renderedSeeds.push({ kind: 'argumentRef', @@ -679,7 +736,8 @@ function resolveInstructionPdaDefaults(ctx: { if (isNode(seedValue, 'accountValueNode')) { const refName = snakeCase(seedValue.name); const isEither = eitherSignerAccounts.has(seedValue.name); - const eitherExtract = isEither ? '.map(|(k, _)| k)' : ''; + const isOptional = builderOptionalAccounts.has(seedValue.name); + const eitherExtract = isEither ? (isOptional ? '.map(|(k, _)| k)' : '.0') : ''; const defaultExpr = accountDefaults[seedValue.name]; if (pdaDefaultedNames.has(seedValue.name)) { @@ -689,6 +747,9 @@ function resolveInstructionPdaDefaults(ctx: { let valueExpr: string; if (pdaDefaultedNames.has(seedValue.name)) { valueExpr = refName; + } else if (!isOptional) { + // Required account — direct field access. + valueExpr = `self.${refName}${eitherExtract}`; } else if (defaultExpr) { valueExpr = `self.${refName}${eitherExtract}.unwrap_or(${defaultExpr})`; } else { @@ -711,6 +772,7 @@ function resolveInstructionPdaDefaults(ctx: { ? `${seedValue.name}_arg` : seedValue.name; const fieldName = snakeCase(argFieldName); + const isRequiredArg = requiredArgNames.includes(fieldName); const arg = instructionArguments.find(a => a.name === seedValue.name); let argDefault: { isOmitted: boolean; value: string } | null = null; @@ -730,6 +792,19 @@ function resolveInstructionPdaDefaults(ctx: { render: `${argDefault.value}.to_string().as_ref()`, }); } + } else if (isRequiredArg) { + // Required arg — direct field access, no Option unwrap. + const valueExpr = `self.${fieldName}.clone()`; + if (resolvedType.kind === 'publicKeyTypeNode') { + renderedSeeds.push({ kind: 'argumentRef', render: `${valueExpr}.as_ref()` }); + } else if (resolvedType.kind === 'bytesTypeNode') { + renderedSeeds.push({ kind: 'argumentRef', render: `&${valueExpr}` }); + } else { + renderedSeeds.push({ + kind: 'argumentRef', + render: `${valueExpr}.to_string().as_ref()`, + }); + } } else { const valueExpr = `self.${fieldName}.clone().expect("${fieldName} is needed for ${snakeCase(account.name)} PDA")`; if (resolvedType.kind === 'publicKeyTypeNode') { diff --git a/test/instructionsPage.test.ts b/test/instructionsPage.test.ts index 2ca8013..5d1e93a 100644 --- a/test/instructionsPage.test.ts +++ b/test/instructionsPage.test.ts @@ -110,9 +110,9 @@ test('it auto-derives PDA accounts from pdaLinkNode defaults', () => { codeContains(content, [ `unwrap_or_else(|| {`, `crate::pdas::find_record_pda(`, - `&self.realm.expect("realm is needed for record PDA")`, - `&self.mint.expect("mint is needed for record PDA")`, - `&self.owner.expect("owner is needed for record PDA")`, + `&self.realm,`, + `&self.mint,`, + `&self.owner,`, `.0`, `default to PDA derived from 'record'`, ]); @@ -157,12 +157,9 @@ test('it passes argument seeds by value for non-Pubkey types', () => { const renderMap = visit(node, getRenderMapVisitor()); const content = getFromRenderMap(renderMap, 'instructions/create_record.rs').content; - // Then we expect by-ref for the account seed and by-value for the argument seed. - codeContains(content, [ - `crate::pdas::find_record_pda(`, - `&self.owner.expect("owner is needed for record PDA")`, - `self.label.clone().expect("label is needed for record PDA")`, - ]); + // Then we expect by-ref for the account seed (required, direct access) + // and by-value for the argument seed (required, direct clone). + codeContains(content, [`crate::pdas::find_record_pda(`, `&self.owner,`, `self.label.clone(),`]); }); test('it resolves upstream account defaults as PDA seeds', () => { @@ -206,9 +203,9 @@ test('it resolves upstream account defaults as PDA seeds', () => { // Then we expect the tokenProgram seed to use unwrap_or with its default. codeContains(content, [ `crate::pdas::find_ata_pda(`, - `&self.owner.expect("owner is needed for ata PDA")`, + `&self.owner,`, `&self.token_program.unwrap_or(solana_address::address!("TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA"))`, - `&self.mint.expect("mint is needed for ata PDA")`, + `&self.mint,`, ]); }); @@ -292,11 +289,8 @@ test('it passes Pubkey argument seeds by reference', () => { const renderMap = visit(node, getRenderMapVisitor()); const content = getFromRenderMap(renderMap, 'instructions/create_record.rs').content; - // Then we expect the Pubkey argument seed to use by-ref. - codeContains(content, [ - `&self.owner.expect("owner is needed for record PDA")`, - `&self.delegate.clone().expect("delegate is needed for record PDA")`, - ]); + // owner is required (direct), delegate is a required arg (direct clone). + codeContains(content, [`&self.owner,`, `&self.delegate.clone(),`]); }); test('it handles argument/account name conflicts in PDA seeds', () => { @@ -338,10 +332,8 @@ test('it handles argument/account name conflicts in PDA seeds', () => { visit(stringConflict, getRenderMapVisitor()), 'instructions/create_record.rs', ).content; - codeContains(content1, [ - `&self.owner.expect("owner is needed for record PDA")`, - `self.owner_arg.clone().expect("owner_arg is needed for record PDA")`, - ]); + // owner is required (direct), owner_arg is a required arg (direct clone). + codeContains(content1, [`&self.owner,`, `self.owner_arg.clone(),`]); // And a Pubkey argument that conflicts — should also get _arg suffix with by-ref. const pubkeyConflict = programNode({ @@ -381,10 +373,8 @@ test('it handles argument/account name conflicts in PDA seeds', () => { visit(pubkeyConflict, getRenderMapVisitor()), 'instructions/create_record.rs', ).content; - codeContains(content2, [ - `&self.delegate.expect("delegate is needed for record PDA")`, - `&self.delegate_arg.clone().expect("delegate_arg is needed for record PDA")`, - ]); + // delegate is required (direct), delegate_arg is a required arg (direct clone). + codeContains(content2, [`&self.delegate,`, `&self.delegate_arg.clone(),`]); }); test('it handles argument defaults in PDA seeds', () => { @@ -516,8 +506,8 @@ test('it extracts Pubkey from either-signer tuple for PDA seeds', () => { const renderMap = visit(node, getRenderMapVisitor()); const content = getFromRenderMap(renderMap, 'instructions/create_record.rs').content; - // Then we expect the seed to extract the Pubkey from the tuple. - codeContains(content, [`.map(|(k, _)| k).expect("authority is needed for record PDA")`]); + // authority is required either-signer — direct .0 extraction, no expect. + codeContains(content, [`&self.authority.0,`]); }); test('it extracts Pubkey from either-signer tuple for inline pdaNode seeds', () => { @@ -557,8 +547,9 @@ test('it extracts Pubkey from either-signer tuple for inline pdaNode seeds', () const renderMap = visit(node, getRenderMapVisitor()); const content = getFromRenderMap(renderMap, 'instructions/create_record.rs').content; - // Then we expect the seed to extract the Pubkey from the tuple. - codeContains(content, [`.map(|(k, _)| k).expect("authority is needed for record PDA")`]); + // Then we expect the seed to extract the Pubkey from the (Pubkey, bool) tuple. + // authority is a required constructor arg, so the field is (Pubkey, bool) directly. + codeContains(content, [`self.authority.0.as_ref()`]); }); test('it renders a builder that auto-derives inline pdaNode accounts', () => { @@ -600,8 +591,11 @@ test('it renders a builder that auto-derives inline pdaNode accounts', () => { codeContains(content, [ `unwrap_or_else(|| {`, `solana_address::Address::find_program_address(`, + // Constant seed rendered as byte array reference. /&\[109, 121, 95, 115, 101, 101, 100\]/, - `self.mint.expect("mint is needed for guard PDA").as_ref()`, + // Variable seed — mint is required, direct .as_ref(). + `self.mint.as_ref()`, + // Uses default program ID. `&crate::TEST_PROGRAM_ID`, `.0`, `default to PDA derived from 'guard'`, @@ -649,10 +643,7 @@ test('it renders inline pdaNode with argumentValueNode variable seed using type const content = getFromRenderMap(renderMap, 'instructions/create_record.rs').content; // Then argument seeds use .to_string().as_ref() for string types (not bare .as_ref()). - codeContains(content, [ - `self.mint.expect("mint is needed for record PDA").as_ref()`, - `self.label.clone().expect("label is needed for record PDA").to_string().as_ref()`, - ]); + codeContains(content, [`self.mint.as_ref()`, `self.label.clone().to_string().as_ref()`]); }); test('it renders inline pdaNode with custom programId', () => { @@ -746,10 +737,7 @@ test('it resolves upstream account defaults when used as inline PDA seeds', () = `self.token_program.unwrap_or(solana_address::address!("TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA")).as_ref()`, ]); // And required accounts without defaults still use expect. - codeContains(content, [ - `self.owner.expect("owner is needed for ata PDA").as_ref()`, - `self.mint.expect("mint is needed for ata PDA").as_ref()`, - ]); + codeContains(content, [`self.owner.as_ref()`, `self.mint.as_ref()`]); }); test('it renders inline pdaNode with programIdValueNode constant seed', () => { @@ -868,8 +856,8 @@ test('it resolves cascading PDA defaults via let bindings', () => { codeContains(content, [`let pool = self.pool.unwrap_or_else(|| {`, `find_pool_pda(`]); // And vault is also a let binding that references the local `pool`, not self.pool. codeContains(content, [`let vault = self.vault.unwrap_or_else(|| {`, `pool.as_ref()`]); - // And the struct literal uses the locals. - codeContains(content, [/Swap \{\s*mint:/]); + // And the struct literal uses shorthand field names. + codeContains(content, [/Swap \{\s*mint,/]); // Verify vault does NOT read self.pool (which would panic). expect(content).not.toContain('self.pool.expect'); }); @@ -977,9 +965,9 @@ test('it handles argument/account name conflicts in inline pdaNode seeds', () => const content = getFromRenderMap(renderMap, 'instructions/create_record.rs').content; // The account seed should reference self.owner (the account field). - codeContains(content, [`self.owner.expect("owner is needed for record PDA").as_ref()`]); + codeContains(content, [`self.owner.as_ref()`]); // The argument seed should reference self.owner_arg (the _arg suffixed field). - codeContains(content, [`self.owner_arg.clone().expect("owner_arg is needed for record PDA")`]); + codeContains(content, [`self.owner_arg.clone()`]); }); test('it handles omitted-default argument seeds in inline pdaNode', () => { @@ -1075,11 +1063,9 @@ test('it falls back to .expect() for both accounts in a circular PDA dependency' const renderMap = visit(node, getRenderMapVisitor()); const content = getFromRenderMap(renderMap, 'instructions/circular.rs').content; - // Then BOTH accounts must fall back to .expect() — neither PDA can be resolved. - codeContains(content, [ - 'self.account_a.expect("account_a is not set")', - 'self.account_b.expect("account_b is not set")', - ]); + // Then BOTH accounts lose PDA resolution and become required constructor params. + // They resolve via let-bindings with direct field access. + codeContains(content, ['let account_a = self.account_a', 'let account_b = self.account_b']); // No PDA derivation code should be emitted for either. codeDoesNotContains(content, ['find_program_address', 'unwrap_or_else']); }); @@ -1119,9 +1105,497 @@ test('it bails entire PDA resolution when a variable seed has no binding', () => const renderMap = visit(node, getRenderMapVisitor()); const content = getFromRenderMap(renderMap, 'instructions/deposit.rs').content; - // The account should fall back to .expect() — no PDA derivation with incomplete seeds. - codeContains(content, ['self.vault.expect("vault is not set")']); - codeDoesNotContains(content, ['find_program_address', 'unwrap_or_else']); + // PDA resolution fails — vault becomes a required constructor param. + // Resolved via let-binding with direct field access. + codeContains(content, ['let vault = self.vault']); + codeDoesNotContains(content, ['find_program_address', 'unwrap_or_else', '.expect(']); +}); + +test('it renders required args as constructor params', () => { + const node = programNode({ + instructions: [ + instructionNode({ + accounts: [instructionAccountNode({ isSigner: false, isWritable: true, name: 'myAccount' })], + arguments: [instructionArgumentNode({ name: 'amount', type: numberTypeNode('u64') })], + name: 'myInstruction', + }), + ], + name: 'myProgram', + publicKey: 'Dummy11111111111111111111111111111111111111', + }); + + const renderMap = visit(node, getRenderMapVisitor()); + const code = getFromRenderMap(renderMap, 'instructions/my_instruction.rs').content; + + codeContains(code, [ + /pub struct MyInstructionBuilder \{[^}]*amount: u64,/, + /pub fn new\([^)]*amount: u64/, + `#[derive(Clone, Debug)]`, + ]); + + codeDoesNotContains(code, [ + `pub fn amount(&mut self`, + `expect("amount is not set")`, + `#[derive(Clone, Debug, Default)]`, + ]); +}); + +test('it renders required args as constructor params even without required accounts', () => { + const node = programNode({ + instructions: [ + instructionNode({ + arguments: [instructionArgumentNode({ name: 'amount', type: numberTypeNode('u64') })], + name: 'myInstruction', + }), + ], + name: 'myProgram', + publicKey: 'Dummy11111111111111111111111111111111111111', + }); + + const renderMap = visit(node, getRenderMapVisitor()); + const code = getFromRenderMap(renderMap, 'instructions/my_instruction.rs').content; + + codeContains(code, [`#[derive(Clone, Debug)]`, /pub fn new\([^)]*amount: u64/]); + + codeDoesNotContains(code, [`#[derive(Clone, Debug, Default)]`, `Self::default()`]); +}); + +test('it renders required accounts as constructor params with PDA accounts staying optional', () => { + const node = programNode({ + instructions: [ + instructionNode({ + accounts: [ + instructionAccountNode({ isOptional: false, isSigner: false, isWritable: false, name: 'realm' }), + instructionAccountNode({ isOptional: false, isSigner: false, isWritable: false, name: 'mint' }), + instructionAccountNode({ + defaultValue: pdaValueNode(pdaLinkNode('record'), [ + pdaSeedValueNode('realm', accountValueNode('realm')), + pdaSeedValueNode('mint', accountValueNode('mint')), + ]), + isOptional: false, + isSigner: false, + isWritable: true, + name: 'record', + }), + ], + name: 'createRecord', + }), + ], + name: 'testProgram', + publicKey: '11111111111111111111111111111111', + }); + + const renderMap = visit(node, getRenderMapVisitor()); + const content = getFromRenderMap(renderMap, 'instructions/create_record.rs').content; + + // Required accounts in new(). + codeContains(content, [ + `#[derive(Clone, Debug)]`, + /pub fn new\(\s*realm: solana_address::Address,\s*mint: solana_address::Address,/, + ]); + + // PDA account is NOT in new(), stays Option. + codeContains(content, [/record: Option/, `pub fn record(&mut self`]); + + // Required accounts are bare types, not Option. + codeContains(content, [ + /realm: solana_address::Address,\s*mint: solana_address::Address,\s*record: Option/, + ]); + + // No setters for required accounts. + codeDoesNotContains(content, [`pub fn realm(&mut self`, `pub fn mint(&mut self`]); +}); + +test('it renders required account as pdaLinkNode seed without expect', () => { + const node = programNode({ + instructions: [ + instructionNode({ + accounts: [ + instructionAccountNode({ isOptional: false, isSigner: false, isWritable: false, name: 'owner' }), + instructionAccountNode({ + defaultValue: pdaValueNode(pdaLinkNode('record'), [ + pdaSeedValueNode('owner', accountValueNode('owner')), + ]), + isOptional: false, + isSigner: false, + isWritable: true, + name: 'record', + }), + ], + name: 'createRecord', + }), + ], + name: 'testProgram', + publicKey: '11111111111111111111111111111111', + }); + + const renderMap = visit(node, getRenderMapVisitor()); + const content = getFromRenderMap(renderMap, 'instructions/create_record.rs').content; + + // Required account used as PDA seed — direct access, no expect. + codeContains(content, [`&self.owner,`]); + codeDoesNotContains(content, [`self.owner.expect`]); +}); + +test('it renders required either-signer account as pdaLinkNode seed with .0 extraction', () => { + const node = programNode({ + instructions: [ + instructionNode({ + accounts: [ + instructionAccountNode({ + isOptional: false, + isSigner: 'either', + isWritable: false, + name: 'authority', + }), + instructionAccountNode({ + defaultValue: pdaValueNode(pdaLinkNode('record'), [ + pdaSeedValueNode('authority', accountValueNode('authority')), + ]), + isOptional: false, + isSigner: false, + isWritable: true, + name: 'record', + }), + ], + name: 'createRecord', + }), + ], + name: 'testProgram', + publicKey: '11111111111111111111111111111111', + }); + + const renderMap = visit(node, getRenderMapVisitor()); + const content = getFromRenderMap(renderMap, 'instructions/create_record.rs').content; + + // Required either-signer: bare tuple type, new() param, .0 in seed. + codeContains(content, [ + /authority: \(solana_address::Address, bool\),/, + /pub fn new\([^)]*authority: \(solana_address::Address, bool\)/, + `&self.authority.0,`, + ]); + codeDoesNotContains(content, [ + `Option<(solana_address::Address, bool)>`, + `.map(|(k, _)| k).expect`, + `pub fn authority(&mut self`, + ]); +}); + +test('it renders required account as inline pdaNode seed without expect', () => { + const node = programNode({ + instructions: [ + instructionNode({ + accounts: [ + instructionAccountNode({ isOptional: false, isSigner: false, isWritable: false, name: 'mint' }), + instructionAccountNode({ + defaultValue: pdaValueNode( + pdaNode({ + name: 'guard', + seeds: [ + constantPdaSeedNode(bytesTypeNode(), bytesValueNode('utf8', 'my_seed')), + variablePdaSeedNode('mint', publicKeyTypeNode()), + ], + }), + [pdaSeedValueNode('mint', accountValueNode('mint'))], + ), + isOptional: false, + isSigner: false, + isWritable: true, + name: 'guard', + }), + ], + name: 'createGuard', + }), + ], + name: 'testProgram', + publicKey: '11111111111111111111111111111111', + }); + + const renderMap = visit(node, getRenderMapVisitor()); + const content = getFromRenderMap(renderMap, 'instructions/create_guard.rs').content; + + // Required account as inline PDA seed — direct .as_ref(), no expect. + codeContains(content, [`self.mint.as_ref()`]); + codeDoesNotContains(content, [`self.mint.expect`]); +}); + +test('it renders required arg as pdaLinkNode seed without expect', () => { + const node = programNode({ + instructions: [ + instructionNode({ + accounts: [ + instructionAccountNode({ isOptional: false, isSigner: true, isWritable: false, name: 'owner' }), + instructionAccountNode({ + defaultValue: pdaValueNode(pdaLinkNode('record'), [ + pdaSeedValueNode('owner', accountValueNode('owner')), + pdaSeedValueNode('label', argumentValueNode('label')), + ]), + isOptional: false, + isSigner: false, + isWritable: true, + name: 'record', + }), + ], + arguments: [instructionArgumentNode({ name: 'label', type: stringTypeNode('utf8') })], + name: 'createRecord', + }), + ], + name: 'testProgram', + pdas: [ + pdaNode({ + name: 'record', + seeds: [ + variablePdaSeedNode('owner', publicKeyTypeNode()), + variablePdaSeedNode('label', stringTypeNode('utf8')), + ], + }), + ], + publicKey: '11111111111111111111111111111111', + }); + + const renderMap = visit(node, getRenderMapVisitor()); + const content = getFromRenderMap(renderMap, 'instructions/create_record.rs').content; + + // Required arg in new(). + codeContains(content, [/pub fn new\([^)]*label: TrailingStr/]); + // Required arg as PDA seed — no expect. + codeContains(content, [`self.label.clone(),`]); + codeDoesNotContains(content, [`self.label.clone().expect`]); +}); + +test('it renders mixed required accounts, PDA defaults, and publicKey defaults', () => { + const node = programNode({ + instructions: [ + instructionNode({ + accounts: [ + instructionAccountNode({ isOptional: false, isSigner: true, isWritable: false, name: 'owner' }), + instructionAccountNode({ isOptional: false, isSigner: false, isWritable: false, name: 'mint' }), + instructionAccountNode({ + defaultValue: publicKeyValueNode('TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA'), + isOptional: false, + isSigner: false, + isWritable: false, + name: 'tokenProgram', + }), + instructionAccountNode({ + defaultValue: pdaValueNode(pdaLinkNode('ata'), [ + pdaSeedValueNode('owner', accountValueNode('owner')), + pdaSeedValueNode('tokenProgram', accountValueNode('tokenProgram')), + pdaSeedValueNode('mint', accountValueNode('mint')), + ]), + isOptional: false, + isSigner: false, + isWritable: true, + name: 'ata', + }), + ], + arguments: [instructionArgumentNode({ name: 'amount', type: numberTypeNode('u64') })], + name: 'createAta', + }), + ], + name: 'testProgram', + publicKey: '11111111111111111111111111111111', + }); + + const renderMap = visit(node, getRenderMapVisitor()); + const content = getFromRenderMap(renderMap, 'instructions/create_ata.rs').content; + + // Required accounts and args in new(). + codeContains(content, [ + /pub fn new\(\s*owner: solana_address::Address,\s*mint: solana_address::Address,\s*amount: u64,/, + `#[derive(Clone, Debug)]`, + ]); + + // publicKey default stays optional with setter. + codeContains(content, [ + `pub fn token_program(&mut self`, + `unwrap_or(solana_address::address!("TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA"))`, + ]); + + // PDA account stays optional with setter. + codeContains(content, [`pub fn ata(&mut self`, /ata: Option/]); + + // Required accounts: no setters, no expect. + codeDoesNotContains(content, [ + `pub fn owner(&mut self`, + `pub fn mint(&mut self`, + `pub fn amount(&mut self`, + `expect("owner is not set")`, + `expect("mint is not set")`, + `expect("amount is not set")`, + ]); + + // PDA seed for required accounts uses direct access. + codeContains(content, [`&self.owner,`]); + // PDA seed for publicKey default uses unwrap_or. + codeContains(content, [ + `&self.token_program.unwrap_or(solana_address::address!("TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA"))`, + ]); + // PDA seed for required account 'mint' uses direct access. + codeContains(content, [`&self.mint,`]); +}); + +test('it renders programIdValueNode default account with unwrap_or program ID', () => { + const node = programNode({ + instructions: [ + instructionNode({ + accounts: [ + instructionAccountNode({ isOptional: false, isSigner: false, isWritable: false, name: 'owner' }), + instructionAccountNode({ + defaultValue: programIdValueNode(), + isOptional: false, + isSigner: false, + isWritable: false, + name: 'selfProgram', + }), + ], + name: 'myInstruction', + }), + ], + name: 'testProgram', + publicKey: '11111111111111111111111111111111', + }); + + const renderMap = visit(node, getRenderMapVisitor()); + const content = getFromRenderMap(renderMap, 'instructions/my_instruction.rs').content; + + // programIdValueNode account is builder-optional (Option in struct). + codeContains(content, [`self_program: Option`, `pub fn self_program(&mut self`]); + // In struct literal, unwraps with program ID default. + codeContains(content, [`self.self_program.unwrap_or(crate::TEST_PROGRAM_ID)`]); + // Required account 'owner' is in new(). + codeContains(content, [/pub fn new\([^)]*owner: solana_address::Address/]); + // programIdValueNode account is NOT in new(). + codeDoesNotContains(content, [/pub fn new\([^)]*self_program/]); +}); + +test('it renders CPI builder with required accounts, args, and defaults', () => { + const node = programNode({ + instructions: [ + instructionNode({ + accounts: [ + instructionAccountNode({ isOptional: false, isSigner: true, isWritable: false, name: 'owner' }), + instructionAccountNode({ + defaultValue: publicKeyValueNode('TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA'), + isOptional: false, + isSigner: false, + isWritable: false, + name: 'tokenProgram', + }), + instructionAccountNode({ + defaultValue: programIdValueNode(), + isOptional: false, + isSigner: false, + isWritable: false, + name: 'selfProgram', + }), + ], + arguments: [instructionArgumentNode({ name: 'amount', type: numberTypeNode('u64') })], + name: 'myInstruction', + }), + ], + name: 'testProgram', + publicKey: '11111111111111111111111111111111', + }); + + const renderMap = visit(node, getRenderMapVisitor()); + const content = getFromRenderMap(renderMap, 'instructions/my_instruction.rs').content; + + const cpiSection = content.substring(content.indexOf('Instruction builder for `MyInstruction` via CPI')); + + codeContains(cpiSection, [ + /MyInstructionCpiBuilder<'a, 'b>/, + /pub fn new\(\s*__program: &'b solana_account_info::AccountInfo<'a>,\s*owner: &'b solana_account_info::AccountInfo<'a>,\s*token_program: &'b solana_account_info::AccountInfo<'a>,\s*amount: u64,/, + ]); + codeContains(cpiSection, [ + /owner: &'b solana_account_info::AccountInfo<'a>,\s*token_program: &'b solana_account_info::AccountInfo<'a>,\s*self_program: Option<&'b solana_account_info::AccountInfo<'a>>,/, + ]); + codeContains(cpiSection, [/amount: u64,\s*\/\/\//]); + codeContains(cpiSection, [`self.instruction.self_program.unwrap_or(self.instruction.__program)`]); + codeContains(cpiSection, [/token_program: self\.instruction\.token_program,/]); + codeContains(cpiSection, [/\[signer\].*owner/, /\[optional\].*self_program/]); + codeDoesNotContains(cpiSection, [/\[optional\].*token_program/]); + codeDoesNotContains(cpiSection, [`pub fn token_program(`]); +}); + +test('it renders CPI builder with PDA-defaulted accounts as required constructor params', () => { + const node = programNode({ + instructions: [ + instructionNode({ + accounts: [ + instructionAccountNode({ isOptional: false, isSigner: true, isWritable: false, name: 'owner' }), + instructionAccountNode({ isOptional: false, isSigner: false, isWritable: false, name: 'mint' }), + instructionAccountNode({ + defaultValue: pdaValueNode(pdaLinkNode('record'), [ + pdaSeedValueNode('owner', accountValueNode('owner')), + pdaSeedValueNode('mint', accountValueNode('mint')), + ]), + isOptional: false, + isSigner: false, + isWritable: true, + name: 'record', + }), + instructionAccountNode({ + defaultValue: programIdValueNode(), + isOptional: false, + isSigner: false, + isWritable: false, + name: 'selfProgram', + }), + ], + name: 'createRecord', + }), + ], + name: 'testProgram', + publicKey: '11111111111111111111111111111111', + }); + + const renderMap = visit(node, getRenderMapVisitor()); + const content = getFromRenderMap(renderMap, 'instructions/create_record.rs').content; + + const cpiSection = content.substring(content.indexOf('Instruction builder for `CreateRecord` via CPI')); + + codeContains(cpiSection, [ + /CreateRecordCpiBuilder<'a, 'b>/, + /pub fn new\(\s*__program: &'b solana_account_info::AccountInfo<'a>,\s*owner: &'b solana_account_info::AccountInfo<'a>,\s*mint: &'b solana_account_info::AccountInfo<'a>,\s*record: &'b solana_account_info::AccountInfo<'a>,/, + ]); + codeContains(cpiSection, [ + /record: &'b solana_account_info::AccountInfo<'a>,\s*self_program: Option<&'b solana_account_info::AccountInfo<'a>>,/, + ]); + codeContains(cpiSection, [/record: self\.instruction\.record,/]); + codeContains(cpiSection, [`self.instruction.self_program.unwrap_or(self.instruction.__program)`]); + codeDoesNotContains(cpiSection, [`pub fn record(`]); + codeContains(cpiSection, [`pub fn self_program(`]); + codeDoesNotContains(cpiSection, [/\[optional\].*record/]); + codeContains(cpiSection, [/\[optional\].*self_program/]); + + // Regular Builder still has record as optional (PDA auto-derived). + codeContains(content, [/pub struct CreateRecordBuilder \{[^}]*record: Option/]); +}); + +test('it avoids CPI builder param name collision when instruction has an account named program', () => { + const node = programNode({ + instructions: [ + instructionNode({ + accounts: [ + instructionAccountNode({ isOptional: false, isSigner: true, isWritable: false, name: 'user' }), + instructionAccountNode({ isOptional: false, isSigner: false, isWritable: false, name: 'program' }), + ], + name: 'myInstruction', + }), + ], + name: 'testProgram', + publicKey: '11111111111111111111111111111111', + }); + + const renderMap = visit(node, getRenderMapVisitor()); + const content = getFromRenderMap(renderMap, 'instructions/my_instruction.rs').content; + const cpiSection = content.substring(content.indexOf('Instruction builder for `MyInstruction` via CPI')); + + // CPI builder first param is __program (not program) to avoid collision. + codeContains(cpiSection, [/pub fn new\(\s*__program: &'b solana_account_info::AccountInfo<'a>,/]); + // The instruction account named 'program' is a separate param. + codeContains(cpiSection, [/program: &'b solana_account_info::AccountInfo<'a>,/]); }); test('it uses unwrap_or with precomputed address for zero-variable-seed linked PDA', () => { From 699bc835f8d9910ca9294725a2e939ac789a9d15 Mon Sep 17 00:00:00 2001 From: ioxde <228087182+ioxde@users.noreply.github.com> Date: Sat, 4 Apr 2026 16:14:20 -0700 Subject: [PATCH 19/24] Fix featureFlags not emitting cfg_attr for traits absent from defaults --- src/utils/traitOptions.ts | 20 +++++- test/utils/traitOptions.test.ts | 117 ++++++++++++++++++++++++++++++++ 2 files changed, 134 insertions(+), 3 deletions(-) diff --git a/src/utils/traitOptions.ts b/src/utils/traitOptions.ts index da98dd9..f8f7b61 100644 --- a/src/utils/traitOptions.ts +++ b/src/utils/traitOptions.ts @@ -144,7 +144,10 @@ function partitionTraitsInFeatures( const unfeaturedTraits: string[] = []; const featuredTraits: Record = {}; + const seenTraits = new Set(); + for (const trait of traits) { + seenTraits.add(trait); const feature: string | undefined = reverseFeatureFlags[trait]; if (feature === undefined) { unfeaturedTraits.push(trait); @@ -154,6 +157,16 @@ function partitionTraitsInFeatures( } } + // Inject feature-flagged traits that weren't already in the defaults/overrides. + for (const [feature, flaggedTraits] of Object.entries(featureFlags)) { + for (const trait of flaggedTraits) { + if (!seenTraits.has(trait)) { + if (!featuredTraits[feature]) featuredTraits[feature] = []; + featuredTraits[feature].push(trait); + } + } + } + return [unfeaturedTraits, featuredTraits]; } @@ -191,9 +204,10 @@ export function getSerdeFieldAttribute( const nodeOverrides: string[] | undefined = sanitizedOverrides[node.name]; const allTraits = nodeOverrides === undefined ? getDefaultTraits(nodeType, options) : nodeOverrides; - // Check if serde traits are present. - const hasSerdeSerialize = allTraits.some(t => t === 'serde::Serialize' || t === 'Serialize'); - const hasSerdeDeserialize = allTraits.some(t => t === 'serde::Deserialize' || t === 'Deserialize'); + // Check if serde traits are present in defaults/overrides or feature flags. + const allTraitsAndFeatured = [...allTraits, ...Object.values(options.featureFlags).flat()]; + const hasSerdeSerialize = allTraitsAndFeatured.some(t => t === 'serde::Serialize' || t === 'Serialize'); + const hasSerdeDeserialize = allTraitsAndFeatured.some(t => t === 'serde::Deserialize' || t === 'Deserialize'); if (!hasSerdeSerialize && !hasSerdeDeserialize) { return ''; diff --git a/test/utils/traitOptions.test.ts b/test/utils/traitOptions.test.ts index 5609923..6953cb7 100644 --- a/test/utils/traitOptions.test.ts +++ b/test/utils/traitOptions.test.ts @@ -342,6 +342,95 @@ describe('overridden traits', () => { }); }); +describe('feature-flag-only traits (not in defaults)', () => { + test('it injects feature-flagged traits that are not in any defaults', () => { + // Given a struct defined type with no serde in defaults. + const node = definedTypeNode({ + name: 'MyStruct', + type: structTypeNode([structFieldTypeNode({ name: 'value', type: numberTypeNode('u64') })]), + }); + + // When we specify traits only in featureFlags (not in baseDefaults). + const { render } = getTraitsFromNode(node, { + ...RESET_OPTIONS, + baseDefaults: ['Clone', 'Debug'], + featureFlags: { + serde: ['serde::Serialize'], + }, + }); + + // Then we expect the feature-only trait to appear in cfg_attr. + expect(render).toBe(`#[derive(Clone, Debug)]\n` + `#[cfg_attr(feature = "serde", derive(serde::Serialize))]\n`); + }); + + test('it injects multiple feature-flag-only traits across different features', () => { + // Given a struct defined type. + const node = definedTypeNode({ + name: 'MyStruct', + type: structTypeNode([structFieldTypeNode({ name: 'value', type: numberTypeNode('u64') })]), + }); + + // When we specify traits only in featureFlags with multiple features. + const { render } = getTraitsFromNode(node, { + ...RESET_OPTIONS, + baseDefaults: ['Clone'], + featureFlags: { + extra: ['MyExtraTrait'], + serde: ['serde::Serialize', 'serde::Deserialize'], + }, + }); + + // Then all feature-only traits appear in their respective cfg_attr blocks. + expect(render).toBe( + `#[derive(Clone)]\n` + + `#[cfg_attr(feature = "extra", derive(MyExtraTrait))]\n` + + `#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]\n`, + ); + }); + + test('it mixes default-partitioned and feature-only traits correctly', () => { + // Given a struct defined type. + const node = definedTypeNode({ + name: 'MyStruct', + type: structTypeNode([structFieldTypeNode({ name: 'value', type: numberTypeNode('u64') })]), + }); + + // When some featureFlags traits are in defaults and some are not. + const { render } = getTraitsFromNode(node, { + ...RESET_OPTIONS, + baseDefaults: ['Clone', 'Debug', 'serde::Serialize'], + featureFlags: { + serde: ['serde::Serialize', 'serde::Deserialize'], + }, + }); + + // Then Serialize (in defaults) and Deserialize (not in defaults) both appear under serde. + expect(render).toBe( + `#[derive(Clone, Debug)]\n` + + `#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]\n`, + ); + }); + + test('it works with feature-only traits and no defaults at all', () => { + // Given a struct defined type. + const node = definedTypeNode({ + name: 'MyStruct', + type: structTypeNode([structFieldTypeNode({ name: 'value', type: numberTypeNode('u64') })]), + }); + + // When all traits are only in featureFlags. + const { render } = getTraitsFromNode(node, { + ...RESET_OPTIONS, + featureFlags: { + serde: ['serde::Serialize'], + }, + }); + + // Then only cfg_attr is rendered with no #[derive(...)]. + expect(render).toBe(`#[cfg_attr(feature = "serde", derive(serde::Serialize))]\n`); + }); +}); + describe('fully qualified name traits', () => { test('it can use fully qualified names for traits instead of importing them', () => { // Given a scalar enum defined type. @@ -635,4 +724,32 @@ describe('conditional serde field attributes', () => { expect(account).toContain('#[serde(with = "serde_with::As::")]'); expect(account).not.toContain('#[cfg_attr(feature = "serde"'); }); + + test('it emits serde field attributes when serde is only in featureFlags (not in defaults)', () => { + // Given an account with a Pubkey field. + const node = accountNode({ + data: structTypeNode([structFieldTypeNode({ name: 'authority', type: publicKeyTypeNode() })]), + name: 'myAccount', + }); + + // When serde traits are only in featureFlags, not in baseDefaults. + const renderMap = visit( + rootNode(programNode({ accounts: [node], name: 'myProgram', publicKey: '1111' })), + getRenderMapVisitor({ + traitOptions: { + baseDefaults: ['BorshSerialize', 'BorshDeserialize', 'Clone', 'Debug'], + featureFlags: { + serde: ['serde::Serialize', 'serde::Deserialize'], + }, + }, + }), + ); + + // Then we expect both cfg_attr derive and cfg_attr serde field attributes. + const account = getFromRenderMap(renderMap, 'accounts/my_account.rs').content; + expect(account).toContain('#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]'); + expect(account).toContain( + '#[cfg_attr(feature = "serde", serde(with = "serde_with::As::"))]', + ); + }); }); From 8c1970ccb84d6ae2bc76432ed260aa7dc9b7bbda Mon Sep 17 00:00:00 2001 From: ioxde <228087182+ioxde@users.noreply.github.com> Date: Fri, 3 Apr 2026 10:51:22 -0700 Subject: [PATCH 20/24] Add camelCase rename_all and DisplayFromStr for u64/i64/u128/i128 to serde feature --- src/getTypeManifestVisitor.ts | 12 ++ src/utils/traitOptions.ts | 74 ++++++---- test/utils/traitOptions.test.ts | 248 ++++++++++++++++++++++++++++++-- 3 files changed, 299 insertions(+), 35 deletions(-) diff --git a/src/getTypeManifestVisitor.ts b/src/getTypeManifestVisitor.ts index 5bddf8e..6639448 100644 --- a/src/getTypeManifestVisitor.ts +++ b/src/getTypeManifestVisitor.ts @@ -231,6 +231,12 @@ export function getTypeManifestVisitor(options: { parentNode, traitOptions, ); + } else if (parentNode && ['(u64)', '(i64)', '(u128)', '(i128)'].includes(childManifest.type)) { + derive = getSerdeFieldAttribute( + 'serde_with::As::', + parentNode, + traitOptions, + ); } return { @@ -419,6 +425,12 @@ export function getTypeManifestVisitor(options: { parentNode, traitOptions, ); + } else if (['u64', 'i64', 'u128', 'i128'].includes(fieldManifest.type)) { + derive = getSerdeFieldAttribute( + 'serde_with::As::', + parentNode, + traitOptions, + ); } else if ( isNode(resolvedNestedType, 'arrayTypeNode') && isNode(resolvedNestedType.count, 'fixedCountNode') && diff --git a/src/utils/traitOptions.ts b/src/utils/traitOptions.ts index f8f7b61..fa39e6c 100644 --- a/src/utils/traitOptions.ts +++ b/src/utils/traitOptions.ts @@ -95,6 +95,17 @@ export function getTraitsFromNode( }), ]; + // Add serde rename_all = "camelCase" container attribute for structs only. + // Enums keep PascalCase variant names to match the JS SDK. + const { featureName, hasSerde } = findSerdeFeature(allTraits, options.featureFlags); + if (hasSerde && nodeType === 'struct') { + if (featureName) { + traitLines.push(`#[cfg_attr(feature = "${featureName}", serde(rename_all = "camelCase"))]\n`); + } else { + traitLines.push(`#[serde(rename_all = "camelCase")]\n`); + } + } + return { imports, render: traitLines.join('') }; } @@ -179,6 +190,40 @@ function extractFullyQualifiedNames(traits: string[], imports: ImportMap): strin }); } +/** + * Determines whether serde traits are present and which feature flag (if any) they are behind. + */ +function findSerdeFeature( + allTraits: string[], + featureFlags: Record, +): { featureName: string | undefined; hasSerde: boolean } { + const allTraitsAndFeatured = [...allTraits, ...Object.values(featureFlags).flat()]; + const hasSerde = allTraitsAndFeatured.some( + t => t === 'serde::Serialize' || t === 'Serialize' || t === 'serde::Deserialize' || t === 'Deserialize', + ); + + if (!hasSerde) { + return { featureName: undefined, hasSerde: false }; + } + + const partitioned = partitionTraitsInFeatures(allTraits, featureFlags); + const featured = partitioned[1]; + + let featureName: string | undefined; + for (const [feature, traits] of Object.entries(featured)) { + if ( + traits.some( + t => t === 'serde::Serialize' || t === 'serde::Deserialize' || t === 'Serialize' || t === 'Deserialize', + ) + ) { + featureName = feature; + break; + } + } + + return { featureName, hasSerde: true }; +} + /** * Helper function to get the serde field attribute format based on trait configuration. * Returns the appropriate attribute string for serde field customization, or empty string if no serde traits. @@ -204,34 +249,13 @@ export function getSerdeFieldAttribute( const nodeOverrides: string[] | undefined = sanitizedOverrides[node.name]; const allTraits = nodeOverrides === undefined ? getDefaultTraits(nodeType, options) : nodeOverrides; - // Check if serde traits are present in defaults/overrides or feature flags. - const allTraitsAndFeatured = [...allTraits, ...Object.values(options.featureFlags).flat()]; - const hasSerdeSerialize = allTraitsAndFeatured.some(t => t === 'serde::Serialize' || t === 'Serialize'); - const hasSerdeDeserialize = allTraitsAndFeatured.some(t => t === 'serde::Deserialize' || t === 'Deserialize'); - - if (!hasSerdeSerialize && !hasSerdeDeserialize) { + const { featureName, hasSerde } = findSerdeFeature(allTraits, options.featureFlags); + if (!hasSerde) { return ''; } - // Check if serde is feature-flagged. - const partitionedTraits = partitionTraitsInFeatures(allTraits, options.featureFlags); - const featuredTraits = partitionedTraits[1]; - - // Find which feature flag contains serde traits. - let serdeFeatureName: string | undefined; - for (const [feature, traits] of Object.entries(featuredTraits)) { - if ( - traits.some( - t => t === 'serde::Serialize' || t === 'serde::Deserialize' || t === 'Serialize' || t === 'Deserialize', - ) - ) { - serdeFeatureName = feature; - break; - } - } - - if (serdeFeatureName) { - return `#[cfg_attr(feature = "${serdeFeatureName}", serde(with = "${serdeWith}"))]\n`; + if (featureName) { + return `#[cfg_attr(feature = "${featureName}", serde(with = "${serdeWith}"))]\n`; } else { return `#[serde(with = "${serdeWith}")]\n`; } diff --git a/test/utils/traitOptions.test.ts b/test/utils/traitOptions.test.ts index 6953cb7..68f677b 100644 --- a/test/utils/traitOptions.test.ts +++ b/test/utils/traitOptions.test.ts @@ -131,8 +131,8 @@ describe('default values', () => { overrides: { coordinates: ['My', 'special::Traits', 'serde::Serialize'] }, }); - // Then we expect the following traits to be rendered. - expect(render).toBe(`#[derive(My, Traits, Serialize)]\n`); + // Then we expect the following traits to be rendered (including rename_all since serde is present). + expect(render).toBe(`#[derive(My, Traits, Serialize)]\n#[serde(rename_all = "camelCase")]\n`); }); }); @@ -359,8 +359,12 @@ describe('feature-flag-only traits (not in defaults)', () => { }, }); - // Then we expect the feature-only trait to appear in cfg_attr. - expect(render).toBe(`#[derive(Clone, Debug)]\n` + `#[cfg_attr(feature = "serde", derive(serde::Serialize))]\n`); + // Then we expect the feature-only trait to appear in cfg_attr (with rename_all). + expect(render).toBe( + `#[derive(Clone, Debug)]\n` + + `#[cfg_attr(feature = "serde", derive(serde::Serialize))]\n` + + `#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]\n`, + ); }); test('it injects multiple feature-flag-only traits across different features', () => { @@ -380,11 +384,12 @@ describe('feature-flag-only traits (not in defaults)', () => { }, }); - // Then all feature-only traits appear in their respective cfg_attr blocks. + // Then all feature-only traits appear in their respective cfg_attr blocks (with rename_all for serde). expect(render).toBe( `#[derive(Clone)]\n` + `#[cfg_attr(feature = "extra", derive(MyExtraTrait))]\n` + - `#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]\n`, + `#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]\n` + + `#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]\n`, ); }); @@ -404,10 +409,11 @@ describe('feature-flag-only traits (not in defaults)', () => { }, }); - // Then Serialize (in defaults) and Deserialize (not in defaults) both appear under serde. + // Then Serialize (in defaults) and Deserialize (not in defaults) both appear under serde (with rename_all). expect(render).toBe( `#[derive(Clone, Debug)]\n` + - `#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]\n`, + `#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]\n` + + `#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]\n`, ); }); @@ -426,8 +432,11 @@ describe('feature-flag-only traits (not in defaults)', () => { }, }); - // Then only cfg_attr is rendered with no #[derive(...)]. - expect(render).toBe(`#[cfg_attr(feature = "serde", derive(serde::Serialize))]\n`); + // Then only cfg_attr is rendered with no #[derive(...)] (with rename_all). + expect(render).toBe( + `#[cfg_attr(feature = "serde", derive(serde::Serialize))]\n` + + `#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]\n`, + ); }); }); @@ -752,4 +761,223 @@ describe('conditional serde field attributes', () => { '#[cfg_attr(feature = "serde", serde(with = "serde_with::As::"))]', ); }); + + test('it generates DisplayFromStr for u64 fields when serde is feature-flagged', () => { + const node = accountNode({ + data: structTypeNode([structFieldTypeNode({ name: 'amount', type: numberTypeNode('u64') })]), + name: 'myAccount', + }); + + const renderMap = visit( + rootNode(programNode({ accounts: [node], name: 'myProgram', publicKey: '1111' })), + getRenderMapVisitor({ + traitOptions: { + baseDefaults: ['BorshSerialize', 'BorshDeserialize', 'Clone', 'Debug'], + featureFlags: { + serde: ['serde::Serialize', 'serde::Deserialize'], + }, + }, + }), + ); + + const account = getFromRenderMap(renderMap, 'accounts/my_account.rs').content; + expect(account).toContain( + '#[cfg_attr(feature = "serde", serde(with = "serde_with::As::"))]', + ); + }); + + test('it generates DisplayFromStr for i64 fields when serde is not feature-flagged', () => { + const node = accountNode({ + data: structTypeNode([structFieldTypeNode({ name: 'timestamp', type: numberTypeNode('i64') })]), + name: 'myAccount', + }); + + const renderMap = visit( + rootNode(programNode({ accounts: [node], name: 'myProgram', publicKey: '1111' })), + getRenderMapVisitor({ + traitOptions: { + baseDefaults: ['serde::Serialize', 'serde::Deserialize', 'Clone', 'Debug'], + featureFlags: {}, + }, + }), + ); + + const account = getFromRenderMap(renderMap, 'accounts/my_account.rs').content; + expect(account).toContain('#[serde(with = "serde_with::As::")]'); + expect(account).not.toContain('#[cfg_attr(feature = "serde"'); + }); + + test('it generates DisplayFromStr for u128 and i128 fields', () => { + const node = accountNode({ + data: structTypeNode([ + structFieldTypeNode({ name: 'bigUnsigned', type: numberTypeNode('u128') }), + structFieldTypeNode({ name: 'bigSigned', type: numberTypeNode('i128') }), + ]), + name: 'myAccount', + }); + + const renderMap = visit( + rootNode(programNode({ accounts: [node], name: 'myProgram', publicKey: '1111' })), + getRenderMapVisitor({ + traitOptions: { + baseDefaults: ['BorshSerialize', 'BorshDeserialize', 'Clone', 'Debug'], + featureFlags: { + serde: ['serde::Serialize', 'serde::Deserialize'], + }, + }, + }), + ); + + const account = getFromRenderMap(renderMap, 'accounts/my_account.rs').content; + // Both u128 and i128 fields should have DisplayFromStr. + const matches = account.match( + /#\[cfg_attr\(feature = "serde", serde\(with = "serde_with::As::"\)\)\]/g, + ); + expect(matches).toHaveLength(2); + }); + + test('it does not generate DisplayFromStr for u32 fields', () => { + const node = accountNode({ + data: structTypeNode([structFieldTypeNode({ name: 'count', type: numberTypeNode('u32') })]), + name: 'myAccount', + }); + + const renderMap = visit( + rootNode(programNode({ accounts: [node], name: 'myProgram', publicKey: '1111' })), + getRenderMapVisitor({ + traitOptions: { + baseDefaults: ['BorshSerialize', 'BorshDeserialize', 'Clone', 'Debug'], + featureFlags: { + serde: ['serde::Serialize', 'serde::Deserialize'], + }, + }, + }), + ); + + const account = getFromRenderMap(renderMap, 'accounts/my_account.rs').content; + expect(account).not.toContain('DisplayFromStr'); + }); + + test('it does not generate DisplayFromStr for u64 fields when serde is absent', () => { + const node = accountNode({ + data: structTypeNode([structFieldTypeNode({ name: 'amount', type: numberTypeNode('u64') })]), + name: 'myAccount', + }); + + const renderMap = visit( + rootNode(programNode({ accounts: [node], name: 'myProgram', publicKey: '1111' })), + getRenderMapVisitor({ + traitOptions: { + baseDefaults: ['BorshSerialize', 'BorshDeserialize', 'Clone', 'Debug'], + featureFlags: {}, + }, + }), + ); + + const account = getFromRenderMap(renderMap, 'accounts/my_account.rs').content; + expect(account).not.toContain('DisplayFromStr'); + }); +}); + +describe('serde rename_all container attribute', () => { + test('it adds rename_all when serde is in baseDefaults (not feature-flagged)', () => { + const node = definedTypeNode({ + name: 'MyStruct', + type: structTypeNode([structFieldTypeNode({ name: 'myField', type: numberTypeNode('u32') })]), + }); + + const { render } = getTraitsFromNode(node, { + baseDefaults: ['serde::Serialize', 'serde::Deserialize', 'Clone', 'Debug'], + featureFlags: {}, + }); + + expect(render).toContain('#[serde(rename_all = "camelCase")]'); + expect(render).not.toContain('cfg_attr'); + }); + + test('it adds rename_all with cfg_attr when serde is feature-flagged', () => { + const node = definedTypeNode({ + name: 'MyStruct', + type: structTypeNode([structFieldTypeNode({ name: 'myField', type: numberTypeNode('u32') })]), + }); + + const { render } = getTraitsFromNode(node, { + baseDefaults: ['Clone', 'Debug'], + featureFlags: { + serde: ['serde::Serialize', 'serde::Deserialize'], + }, + }); + + expect(render).toContain('#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]'); + }); + + test('it does not add rename_all when no serde traits are present', () => { + const node = definedTypeNode({ + name: 'MyStruct', + type: structTypeNode([structFieldTypeNode({ name: 'myField', type: numberTypeNode('u32') })]), + }); + + const { render } = getTraitsFromNode(node, { + baseDefaults: ['Clone', 'Debug'], + featureFlags: {}, + }); + + expect(render).not.toContain('rename_all'); + expect(render).not.toContain('serde'); + }); + + test('it does not add rename_all on scalar enums', () => { + const node = definedTypeNode({ + name: 'MyEnum', + type: enumTypeNode([enumEmptyVariantTypeNode('VariantA'), enumEmptyVariantTypeNode('VariantB')]), + }); + + const { render } = getTraitsFromNode(node, { + baseDefaults: ['Clone', 'Debug'], + featureFlags: { + serde: ['serde::Serialize', 'serde::Deserialize'], + }, + }); + + expect(render).not.toContain('rename_all'); + }); + + test('it does not add rename_all on data enums', () => { + const node = definedTypeNode({ + name: 'MyEnum', + type: enumTypeNode([ + enumEmptyVariantTypeNode('VariantA'), + enumStructVariantTypeNode( + 'VariantB', + structTypeNode([structFieldTypeNode({ name: 'someField', type: numberTypeNode('u64') })]), + ), + ]), + }); + + const { render } = getTraitsFromNode(node, { + baseDefaults: ['Clone', 'Debug'], + featureFlags: { + serde: ['serde::Serialize', 'serde::Deserialize'], + }, + }); + + expect(render).not.toContain('rename_all'); + }); + + test('it uses custom feature name for rename_all', () => { + const node = definedTypeNode({ + name: 'MyStruct', + type: structTypeNode([structFieldTypeNode({ name: 'myField', type: numberTypeNode('u32') })]), + }); + + const { render } = getTraitsFromNode(node, { + baseDefaults: ['Clone', 'Debug'], + featureFlags: { + json_support: ['serde::Serialize', 'serde::Deserialize'], + }, + }); + + expect(render).toContain('#[cfg_attr(feature = "json_support", serde(rename_all = "camelCase"))]'); + expect(render).not.toContain('feature = "serde"'); + }); }); From 4ea7a3522a89178885411e5d2b0b24c39a6fe195 Mon Sep 17 00:00:00 2001 From: ioxde <228087182+ioxde@users.noreply.github.com> Date: Tue, 2 Jun 2026 20:54:03 -0700 Subject: [PATCH 21/24] Regenerate governance e2e fixture for solana-rpc-client --- Cargo.lock | 406 +++--------------- e2e/governance/Cargo.toml | 4 +- .../src/generated/accounts/governance_v1.rs | 8 +- .../src/generated/accounts/governance_v2.rs | 8 +- .../accounts/legacy_token_owner_record.rs | 8 +- .../generated/accounts/program_metadata.rs | 8 +- .../generated/accounts/proposal_deposit.rs | 8 +- .../accounts/proposal_instruction_v1.rs | 8 +- .../accounts/proposal_transaction_v2.rs | 8 +- .../src/generated/accounts/proposal_v1.rs | 8 +- .../src/generated/accounts/proposal_v2.rs | 8 +- .../accounts/realm_config_account.rs | 8 +- .../src/generated/accounts/realm_v1.rs | 8 +- .../src/generated/accounts/realm_v2.rs | 8 +- .../generated/accounts/required_signatory.rs | 8 +- .../generated/accounts/signatory_record_v1.rs | 8 +- .../generated/accounts/signatory_record_v2.rs | 8 +- .../accounts/token_owner_record_v1.rs | 8 +- .../accounts/token_owner_record_v2.rs | 8 +- .../src/generated/accounts/vote_record_v1.rs | 8 +- .../src/generated/accounts/vote_record_v2.rs | 8 +- 21 files changed, 128 insertions(+), 434 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 128cf19..6fd7a89 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -584,17 +584,6 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" -[[package]] -name = "cfg_eval" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "45565fc9416b9896014f5732ac776f810ee53a66730c17e4020c3ec064a8f88f" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.117", -] - [[package]] name = "chrono" version = "0.4.44" @@ -652,11 +641,11 @@ dependencies = [ "solana-account 3.0.0", "solana-account-info 3.1.0", "solana-address 2.2.0", - "solana-client", "solana-cpi 3.1.0", "solana-decode-error", "solana-instruction 3.2.0", "solana-program-error 3.0.0", + "solana-rpc-client", "spl-collections", "thiserror 1.0.69", ] @@ -782,6 +771,12 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7c74b8349d32d297c9134b8c88677813a227df8f779daa29bfc29c183fe3dca6" +[[package]] +name = "core-foundation-sys" +version = "0.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" + [[package]] name = "cpufeatures" version = "0.2.17" @@ -879,49 +874,6 @@ dependencies = [ "syn 2.0.117", ] -[[package]] -name = "dashmap" -version = "5.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "978747c1d849a7d2ee5e8adc0159961c48fb7e5db2f06af6723b80123bb53856" -dependencies = [ - "cfg-if", - "hashbrown 0.14.5", - "lock_api", - "once_cell", - "parking_lot_core", -] - -[[package]] -name = "data-encoding" -version = "2.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a2330da5de22e8a3cb63252ce2abb30116bf5265e89c0e01bc17015ce30a476" - -[[package]] -name = "der" -version = "0.7.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7c1832837b905bbfb5101e07cc24c8deddf52f93225eee6ead5f4d63d53ddcb" -dependencies = [ - "const-oid", - "zeroize", -] - -[[package]] -name = "der-parser" -version = "8.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dbd676fbbab537128ef0278adb5576cf363cff6aa22a7b24effe97347cfab61e" -dependencies = [ - "asn1-rs", - "displaydoc", - "nom", - "num-bigint 0.4.6", - "num-traits", - "rusticata-macros", -] - [[package]] name = "deranged" version = "0.5.4" @@ -963,60 +915,12 @@ dependencies = [ "syn 2.0.117", ] -[[package]] -name = "dlopen2" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09b4f5f101177ff01b8ec4ecc81eead416a8aa42819a2869311b3420fa114ffa" -dependencies = [ - "dlopen2_derive", - "libc", - "once_cell", - "winapi", -] - -[[package]] -name = "dlopen2_derive" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a6cbae11b3de8fce2a456e8ea3dada226b35fe791f0dc1d360c0941f0bb681f3" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.117", -] - [[package]] name = "dyn-clone" version = "1.0.20" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d0881ea181b1df73ff77ffaaf9c7544ecc11e82fba9b5f27b262a3c73a332555" -[[package]] -name = "ed25519" -version = "2.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "115531babc129696a58c64a4fef0a8bf9e9698629fb97e9e40767d235cfbcd53" -dependencies = [ - "pkcs8", - "signature", -] - -[[package]] -name = "ed25519-dalek" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70e796c081cee67dc755e1a36a0a172b897fab85fc3f6bc48307991f64e4eca9" -dependencies = [ - "curve25519-dalek", - "ed25519", - "rand_core 0.6.4", - "serde", - "sha2 0.10.9", - "subtle", - "zeroize", -] - [[package]] name = "either" version = "1.15.0" @@ -1302,44 +1206,12 @@ dependencies = [ "unicode-segmentation", ] -[[package]] -name = "hermit-abi" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc0fef456e4baa96da950455cd02c081ca953b141298e41db3fc7e36b1da849c" - [[package]] name = "hex" version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" -[[package]] -name = "histogram" -version = "0.6.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12cb882ccb290b8646e554b157ab0b71e64e8d5bef775cd66b6531e52d302669" - -[[package]] -name = "hmac" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" -dependencies = [ - "digest 0.10.7", -] - -[[package]] -name = "http" -version = "0.2.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "601cbb57e577e2f5ef5be8e7b83f0f63994f25aa94d673e54a92d5c516d101f1" -dependencies = [ - "bytes", - "fnv", - "itoa", -] - [[package]] name = "http" version = "1.4.0" @@ -1830,6 +1702,12 @@ dependencies = [ "num-traits", ] +[[package]] +name = "num-conv" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c6673768db2d862beb9b39a78fdcb1a69439615d5794a1be50caa9bc92c81967" + [[package]] name = "num-derive" version = "0.4.2" @@ -1948,6 +1826,12 @@ dependencies = [ "zerovec", ] +[[package]] +name = "powerfmt" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" + [[package]] name = "ppv-lite86" version = "0.2.21" @@ -2349,24 +2233,6 @@ version = "1.0.20" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" -[[package]] -name = "same-file" -version = "1.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" -dependencies = [ - "winapi-util", -] - -[[package]] -name = "schannel" -version = "0.1.28" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "891d81b926048e76efe18581bf793546b4c0eaf8448d72be8de2bbee5fd166e1" -dependencies = [ - "windows-sys 0.61.1", -] - [[package]] name = "schemars" version = "0.9.0" @@ -2518,17 +2384,6 @@ dependencies = [ "syn 2.0.117", ] -[[package]] -name = "sha1" -version = "0.10.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba" -dependencies = [ - "cfg-if", - "cpufeatures", - "digest 0.10.7", -] - [[package]] name = "sha2" version = "0.9.9" @@ -2788,73 +2643,6 @@ dependencies = [ "borsh 1.5.7", ] -[[package]] -name = "solana-client" -version = "3.0.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99541c3b3571d6675a9bfc032c776712b3f4da0d5e7f4a5019e044885f716137" -dependencies = [ - "async-trait", - "bincode", - "dashmap", - "futures", - "futures-util", - "indexmap 2.11.4", - "indicatif", - "log", - "quinn", - "rayon", - "solana-account 3.0.0", - "solana-client-traits", - "solana-commitment-config", - "solana-connection-cache", - "solana-epoch-info", - "solana-hash 3.1.0", - "solana-instruction 3.2.0", - "solana-keypair", - "solana-measure", - "solana-message 3.1.0", - "solana-pubkey 3.0.0", - "solana-pubsub-client", - "solana-quic-client", - "solana-quic-definitions", - "solana-rpc-client", - "solana-rpc-client-api", - "solana-rpc-client-nonce-utils", - "solana-signature", - "solana-signer", - "solana-streamer", - "solana-time-utils", - "solana-tpu-client", - "solana-transaction", - "solana-transaction-error 3.1.0", - "solana-transaction-status-client-types", - "solana-udp-client", - "thiserror 2.0.18", - "tokio", -] - -[[package]] -name = "solana-client-traits" -version = "3.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08618ed587e128105510c54ae3e456b9a06d674d8640db75afe66dad65cb4e02" -dependencies = [ - "solana-account 3.0.0", - "solana-commitment-config", - "solana-epoch-info", - "solana-hash 3.1.0", - "solana-instruction 3.2.0", - "solana-keypair", - "solana-message 3.1.0", - "solana-pubkey 3.0.0", - "solana-signature", - "solana-signer", - "solana-system-interface 2.0.0", - "solana-transaction", - "solana-transaction-error 3.1.0", -] - [[package]] name = "solana-clock" version = "2.2.2" @@ -2891,29 +2679,6 @@ dependencies = [ "serde_derive", ] -[[package]] -name = "solana-connection-cache" -version = "3.0.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec08ad33264b1159feea22346deae240d3b38b103346ecf3bfc008a02509afe0" -dependencies = [ - "async-trait", - "bincode", - "crossbeam-channel", - "futures-util", - "indexmap 2.11.4", - "log", - "rand 0.8.5", - "rayon", - "solana-keypair", - "solana-measure", - "solana-metrics", - "solana-time-utils", - "solana-transaction-error 3.1.0", - "thiserror 2.0.18", - "tokio", -] - [[package]] name = "solana-cpi" version = "2.2.1" @@ -3992,55 +3757,6 @@ dependencies = [ "solana-sysvar-id 2.2.1", ] -[[package]] -name = "solana-streamer" -version = "3.0.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "acb28f9c11b3f549dc49694c3dddef34a1531fe2d19c7ead36b7254786379f87" -dependencies = [ - "arc-swap", - "async-channel", - "bytes", - "crossbeam-channel", - "dashmap", - "futures", - "futures-util", - "governor", - "histogram", - "indexmap 2.11.4", - "itertools", - "libc", - "log", - "nix", - "num_cpus", - "pem", - "percentage", - "quinn", - "quinn-proto", - "rand 0.8.5", - "rustls 0.23.32", - "smallvec", - "socket2", - "solana-keypair", - "solana-measure", - "solana-metrics", - "solana-net-utils", - "solana-packet", - "solana-perf", - "solana-pubkey 3.0.0", - "solana-quic-definitions", - "solana-signature", - "solana-signer", - "solana-time-utils", - "solana-tls-utils", - "solana-transaction-error 3.1.0", - "solana-transaction-metrics-tracker", - "thiserror 2.0.18", - "tokio", - "tokio-util", - "x509-parser", -] - [[package]] name = "solana-svm-feature-set" version = "3.0.14" @@ -4152,59 +3868,6 @@ dependencies = [ "solana-sdk-ids 3.1.0", ] -[[package]] -name = "solana-time-utils" -version = "3.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ced92c60aa76ec4780a9d93f3bd64dfa916e1b998eacc6f1c110f3f444f02c9" - -[[package]] -name = "solana-tls-utils" -version = "3.0.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "475766b71bafcaa6af326c54d35dc09ca4a334e5866b42d09b354291b7aa5819" -dependencies = [ - "rustls 0.23.32", - "solana-keypair", - "solana-pubkey 3.0.0", - "solana-signer", - "x509-parser", -] - -[[package]] -name = "solana-tpu-client" -version = "3.0.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "313159134696b2c482fa9a7188fd4daac638d69f5962fe842c3f4cfece1a27f3" -dependencies = [ - "async-trait", - "bincode", - "futures-util", - "indexmap 2.11.4", - "indicatif", - "log", - "rayon", - "solana-client-traits", - "solana-clock 3.0.1", - "solana-commitment-config", - "solana-connection-cache", - "solana-epoch-schedule 3.0.0", - "solana-measure", - "solana-message 3.1.0", - "solana-net-utils", - "solana-pubkey 3.0.0", - "solana-pubsub-client", - "solana-quic-definitions", - "solana-rpc-client", - "solana-rpc-client-api", - "solana-signature", - "solana-signer", - "solana-transaction", - "solana-transaction-error 3.1.0", - "thiserror 2.0.18", - "tokio", -] - [[package]] name = "solana-transaction" version = "3.1.0" @@ -4468,6 +4131,37 @@ dependencies = [ "syn 2.0.117", ] +[[package]] +name = "time" +version = "0.3.47" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "743bd48c283afc0388f9b8827b976905fb217ad9e647fae3a379a9283c4def2c" +dependencies = [ + "deranged", + "itoa", + "num-conv", + "powerfmt", + "serde_core", + "time-core", + "time-macros", +] + +[[package]] +name = "time-core" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7694e1cfe791f8d31026952abf09c69ca6f6fa4e1a1229e18988f06a04a12dca" + +[[package]] +name = "time-macros" +version = "0.2.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e70e4c5a0e0a8a4823ad65dfe1a6930e4f4d756dcd9dd7939022b5e8c501215" +dependencies = [ + "num-conv", + "time-core", +] + [[package]] name = "tinystr" version = "0.8.1" diff --git a/e2e/governance/Cargo.toml b/e2e/governance/Cargo.toml index 989aedd..60d62c1 100644 --- a/e2e/governance/Cargo.toml +++ b/e2e/governance/Cargo.toml @@ -6,7 +6,7 @@ edition = "2021" [features] anchor = ["dep:anchor-lang"] anchor-idl-build = ["anchor", "anchor-lang?/idl-build"] -fetch = ["dep:solana-client"] +fetch = ["dep:solana-rpc-client"] serde = ["dep:serde", "dep:serde_with", "dep:serde-big-array"] test-sbf = [] @@ -21,7 +21,7 @@ serde-big-array = { workspace = true, optional = true } serde_with = { workspace = true, optional = true } solana-account = { workspace = true } solana-account-info = { workspace = true } -solana-client = { workspace = true, optional = true } +solana-rpc-client = { workspace = true, optional = true } solana-cpi = { workspace = true } solana-decode-error = { workspace = true } solana-instruction = { workspace = true } diff --git a/e2e/governance/src/generated/accounts/governance_v1.rs b/e2e/governance/src/generated/accounts/governance_v1.rs index 35e33c2..f12d692 100644 --- a/e2e/governance/src/generated/accounts/governance_v1.rs +++ b/e2e/governance/src/generated/accounts/governance_v1.rs @@ -77,7 +77,7 @@ impl<'a> TryFrom<&solana_account_info::AccountInfo<'a>> for GovernanceV1 { #[cfg(feature = "fetch")] pub fn fetch_governance_v1( - rpc: &solana_client::rpc_client::RpcClient, + rpc: &solana_rpc_client::rpc_client::RpcClient, address: &solana_address::Address, ) -> Result, std::io::Error> { let accounts = fetch_all_governance_v1(rpc, &[*address])?; @@ -86,7 +86,7 @@ pub fn fetch_governance_v1( #[cfg(feature = "fetch")] pub fn fetch_all_governance_v1( - rpc: &solana_client::rpc_client::RpcClient, + rpc: &solana_rpc_client::rpc_client::RpcClient, addresses: &[solana_address::Address], ) -> Result>, std::io::Error> { let accounts = rpc @@ -115,7 +115,7 @@ pub fn fetch_all_governance_v1( #[cfg(feature = "fetch")] pub fn fetch_maybe_governance_v1( - rpc: &solana_client::rpc_client::RpcClient, + rpc: &solana_rpc_client::rpc_client::RpcClient, address: &solana_address::Address, ) -> Result, std::io::Error> { let accounts = fetch_all_maybe_governance_v1(rpc, &[*address])?; @@ -124,7 +124,7 @@ pub fn fetch_maybe_governance_v1( #[cfg(feature = "fetch")] pub fn fetch_all_maybe_governance_v1( - rpc: &solana_client::rpc_client::RpcClient, + rpc: &solana_rpc_client::rpc_client::RpcClient, addresses: &[solana_address::Address], ) -> Result>, std::io::Error> { let accounts = rpc diff --git a/e2e/governance/src/generated/accounts/governance_v2.rs b/e2e/governance/src/generated/accounts/governance_v2.rs index 4814a88..b5b9081 100644 --- a/e2e/governance/src/generated/accounts/governance_v2.rs +++ b/e2e/governance/src/generated/accounts/governance_v2.rs @@ -81,7 +81,7 @@ impl<'a> TryFrom<&solana_account_info::AccountInfo<'a>> for GovernanceV2 { #[cfg(feature = "fetch")] pub fn fetch_governance_v2( - rpc: &solana_client::rpc_client::RpcClient, + rpc: &solana_rpc_client::rpc_client::RpcClient, address: &solana_address::Address, ) -> Result, std::io::Error> { let accounts = fetch_all_governance_v2(rpc, &[*address])?; @@ -90,7 +90,7 @@ pub fn fetch_governance_v2( #[cfg(feature = "fetch")] pub fn fetch_all_governance_v2( - rpc: &solana_client::rpc_client::RpcClient, + rpc: &solana_rpc_client::rpc_client::RpcClient, addresses: &[solana_address::Address], ) -> Result>, std::io::Error> { let accounts = rpc @@ -119,7 +119,7 @@ pub fn fetch_all_governance_v2( #[cfg(feature = "fetch")] pub fn fetch_maybe_governance_v2( - rpc: &solana_client::rpc_client::RpcClient, + rpc: &solana_rpc_client::rpc_client::RpcClient, address: &solana_address::Address, ) -> Result, std::io::Error> { let accounts = fetch_all_maybe_governance_v2(rpc, &[*address])?; @@ -128,7 +128,7 @@ pub fn fetch_maybe_governance_v2( #[cfg(feature = "fetch")] pub fn fetch_all_maybe_governance_v2( - rpc: &solana_client::rpc_client::RpcClient, + rpc: &solana_rpc_client::rpc_client::RpcClient, addresses: &[solana_address::Address], ) -> Result>, std::io::Error> { let accounts = rpc diff --git a/e2e/governance/src/generated/accounts/legacy_token_owner_record.rs b/e2e/governance/src/generated/accounts/legacy_token_owner_record.rs index cbc690d..d62e596 100644 --- a/e2e/governance/src/generated/accounts/legacy_token_owner_record.rs +++ b/e2e/governance/src/generated/accounts/legacy_token_owner_record.rs @@ -94,7 +94,7 @@ impl<'a> TryFrom<&solana_account_info::AccountInfo<'a>> for LegacyTokenOwnerReco #[cfg(feature = "fetch")] pub fn fetch_legacy_token_owner_record( - rpc: &solana_client::rpc_client::RpcClient, + rpc: &solana_rpc_client::rpc_client::RpcClient, address: &solana_address::Address, ) -> Result, std::io::Error> { let accounts = fetch_all_legacy_token_owner_record(rpc, &[*address])?; @@ -103,7 +103,7 @@ pub fn fetch_legacy_token_owner_record( #[cfg(feature = "fetch")] pub fn fetch_all_legacy_token_owner_record( - rpc: &solana_client::rpc_client::RpcClient, + rpc: &solana_rpc_client::rpc_client::RpcClient, addresses: &[solana_address::Address], ) -> Result>, std::io::Error> { let accounts = rpc @@ -133,7 +133,7 @@ pub fn fetch_all_legacy_token_owner_record( #[cfg(feature = "fetch")] pub fn fetch_maybe_legacy_token_owner_record( - rpc: &solana_client::rpc_client::RpcClient, + rpc: &solana_rpc_client::rpc_client::RpcClient, address: &solana_address::Address, ) -> Result, std::io::Error> { let accounts = fetch_all_maybe_legacy_token_owner_record(rpc, &[*address])?; @@ -142,7 +142,7 @@ pub fn fetch_maybe_legacy_token_owner_record( #[cfg(feature = "fetch")] pub fn fetch_all_maybe_legacy_token_owner_record( - rpc: &solana_client::rpc_client::RpcClient, + rpc: &solana_rpc_client::rpc_client::RpcClient, addresses: &[solana_address::Address], ) -> Result>, std::io::Error> { let accounts = rpc diff --git a/e2e/governance/src/generated/accounts/program_metadata.rs b/e2e/governance/src/generated/accounts/program_metadata.rs index dfe5617..3f69835 100644 --- a/e2e/governance/src/generated/accounts/program_metadata.rs +++ b/e2e/governance/src/generated/accounts/program_metadata.rs @@ -43,7 +43,7 @@ impl<'a> TryFrom<&solana_account_info::AccountInfo<'a>> for ProgramMetadata { #[cfg(feature = "fetch")] pub fn fetch_program_metadata( - rpc: &solana_client::rpc_client::RpcClient, + rpc: &solana_rpc_client::rpc_client::RpcClient, address: &solana_address::Address, ) -> Result, std::io::Error> { let accounts = fetch_all_program_metadata(rpc, &[*address])?; @@ -52,7 +52,7 @@ pub fn fetch_program_metadata( #[cfg(feature = "fetch")] pub fn fetch_all_program_metadata( - rpc: &solana_client::rpc_client::RpcClient, + rpc: &solana_rpc_client::rpc_client::RpcClient, addresses: &[solana_address::Address], ) -> Result>, std::io::Error> { let accounts = rpc @@ -81,7 +81,7 @@ pub fn fetch_all_program_metadata( #[cfg(feature = "fetch")] pub fn fetch_maybe_program_metadata( - rpc: &solana_client::rpc_client::RpcClient, + rpc: &solana_rpc_client::rpc_client::RpcClient, address: &solana_address::Address, ) -> Result, std::io::Error> { let accounts = fetch_all_maybe_program_metadata(rpc, &[*address])?; @@ -90,7 +90,7 @@ pub fn fetch_maybe_program_metadata( #[cfg(feature = "fetch")] pub fn fetch_all_maybe_program_metadata( - rpc: &solana_client::rpc_client::RpcClient, + rpc: &solana_rpc_client::rpc_client::RpcClient, addresses: &[solana_address::Address], ) -> Result>, std::io::Error> { let accounts = rpc diff --git a/e2e/governance/src/generated/accounts/proposal_deposit.rs b/e2e/governance/src/generated/accounts/proposal_deposit.rs index ed75d1e..e69f999 100644 --- a/e2e/governance/src/generated/accounts/proposal_deposit.rs +++ b/e2e/governance/src/generated/accounts/proposal_deposit.rs @@ -79,7 +79,7 @@ impl<'a> TryFrom<&solana_account_info::AccountInfo<'a>> for ProposalDeposit { #[cfg(feature = "fetch")] pub fn fetch_proposal_deposit( - rpc: &solana_client::rpc_client::RpcClient, + rpc: &solana_rpc_client::rpc_client::RpcClient, address: &solana_address::Address, ) -> Result, std::io::Error> { let accounts = fetch_all_proposal_deposit(rpc, &[*address])?; @@ -88,7 +88,7 @@ pub fn fetch_proposal_deposit( #[cfg(feature = "fetch")] pub fn fetch_all_proposal_deposit( - rpc: &solana_client::rpc_client::RpcClient, + rpc: &solana_rpc_client::rpc_client::RpcClient, addresses: &[solana_address::Address], ) -> Result>, std::io::Error> { let accounts = rpc @@ -117,7 +117,7 @@ pub fn fetch_all_proposal_deposit( #[cfg(feature = "fetch")] pub fn fetch_maybe_proposal_deposit( - rpc: &solana_client::rpc_client::RpcClient, + rpc: &solana_rpc_client::rpc_client::RpcClient, address: &solana_address::Address, ) -> Result, std::io::Error> { let accounts = fetch_all_maybe_proposal_deposit(rpc, &[*address])?; @@ -126,7 +126,7 @@ pub fn fetch_maybe_proposal_deposit( #[cfg(feature = "fetch")] pub fn fetch_all_maybe_proposal_deposit( - rpc: &solana_client::rpc_client::RpcClient, + rpc: &solana_rpc_client::rpc_client::RpcClient, addresses: &[solana_address::Address], ) -> Result>, std::io::Error> { let accounts = rpc diff --git a/e2e/governance/src/generated/accounts/proposal_instruction_v1.rs b/e2e/governance/src/generated/accounts/proposal_instruction_v1.rs index f52a3a1..d5122a0 100644 --- a/e2e/governance/src/generated/accounts/proposal_instruction_v1.rs +++ b/e2e/governance/src/generated/accounts/proposal_instruction_v1.rs @@ -93,7 +93,7 @@ impl<'a> TryFrom<&solana_account_info::AccountInfo<'a>> for ProposalInstructionV #[cfg(feature = "fetch")] pub fn fetch_proposal_instruction_v1( - rpc: &solana_client::rpc_client::RpcClient, + rpc: &solana_rpc_client::rpc_client::RpcClient, address: &solana_address::Address, ) -> Result, std::io::Error> { let accounts = fetch_all_proposal_instruction_v1(rpc, &[*address])?; @@ -102,7 +102,7 @@ pub fn fetch_proposal_instruction_v1( #[cfg(feature = "fetch")] pub fn fetch_all_proposal_instruction_v1( - rpc: &solana_client::rpc_client::RpcClient, + rpc: &solana_rpc_client::rpc_client::RpcClient, addresses: &[solana_address::Address], ) -> Result>, std::io::Error> { let accounts = rpc @@ -132,7 +132,7 @@ pub fn fetch_all_proposal_instruction_v1( #[cfg(feature = "fetch")] pub fn fetch_maybe_proposal_instruction_v1( - rpc: &solana_client::rpc_client::RpcClient, + rpc: &solana_rpc_client::rpc_client::RpcClient, address: &solana_address::Address, ) -> Result, std::io::Error> { let accounts = fetch_all_maybe_proposal_instruction_v1(rpc, &[*address])?; @@ -141,7 +141,7 @@ pub fn fetch_maybe_proposal_instruction_v1( #[cfg(feature = "fetch")] pub fn fetch_all_maybe_proposal_instruction_v1( - rpc: &solana_client::rpc_client::RpcClient, + rpc: &solana_rpc_client::rpc_client::RpcClient, addresses: &[solana_address::Address], ) -> Result>, std::io::Error> { let accounts = rpc diff --git a/e2e/governance/src/generated/accounts/proposal_transaction_v2.rs b/e2e/governance/src/generated/accounts/proposal_transaction_v2.rs index 673cab9..05d5391 100644 --- a/e2e/governance/src/generated/accounts/proposal_transaction_v2.rs +++ b/e2e/governance/src/generated/accounts/proposal_transaction_v2.rs @@ -95,7 +95,7 @@ impl<'a> TryFrom<&solana_account_info::AccountInfo<'a>> for ProposalTransactionV #[cfg(feature = "fetch")] pub fn fetch_proposal_transaction_v2( - rpc: &solana_client::rpc_client::RpcClient, + rpc: &solana_rpc_client::rpc_client::RpcClient, address: &solana_address::Address, ) -> Result, std::io::Error> { let accounts = fetch_all_proposal_transaction_v2(rpc, &[*address])?; @@ -104,7 +104,7 @@ pub fn fetch_proposal_transaction_v2( #[cfg(feature = "fetch")] pub fn fetch_all_proposal_transaction_v2( - rpc: &solana_client::rpc_client::RpcClient, + rpc: &solana_rpc_client::rpc_client::RpcClient, addresses: &[solana_address::Address], ) -> Result>, std::io::Error> { let accounts = rpc @@ -134,7 +134,7 @@ pub fn fetch_all_proposal_transaction_v2( #[cfg(feature = "fetch")] pub fn fetch_maybe_proposal_transaction_v2( - rpc: &solana_client::rpc_client::RpcClient, + rpc: &solana_rpc_client::rpc_client::RpcClient, address: &solana_address::Address, ) -> Result, std::io::Error> { let accounts = fetch_all_maybe_proposal_transaction_v2(rpc, &[*address])?; @@ -143,7 +143,7 @@ pub fn fetch_maybe_proposal_transaction_v2( #[cfg(feature = "fetch")] pub fn fetch_all_maybe_proposal_transaction_v2( - rpc: &solana_client::rpc_client::RpcClient, + rpc: &solana_rpc_client::rpc_client::RpcClient, addresses: &[solana_address::Address], ) -> Result>, std::io::Error> { let accounts = rpc diff --git a/e2e/governance/src/generated/accounts/proposal_v1.rs b/e2e/governance/src/generated/accounts/proposal_v1.rs index f85d14c..3655f8f 100644 --- a/e2e/governance/src/generated/accounts/proposal_v1.rs +++ b/e2e/governance/src/generated/accounts/proposal_v1.rs @@ -112,7 +112,7 @@ impl<'a> TryFrom<&solana_account_info::AccountInfo<'a>> for ProposalV1 { #[cfg(feature = "fetch")] pub fn fetch_proposal_v1( - rpc: &solana_client::rpc_client::RpcClient, + rpc: &solana_rpc_client::rpc_client::RpcClient, address: &solana_address::Address, ) -> Result, std::io::Error> { let accounts = fetch_all_proposal_v1(rpc, &[*address])?; @@ -121,7 +121,7 @@ pub fn fetch_proposal_v1( #[cfg(feature = "fetch")] pub fn fetch_all_proposal_v1( - rpc: &solana_client::rpc_client::RpcClient, + rpc: &solana_rpc_client::rpc_client::RpcClient, addresses: &[solana_address::Address], ) -> Result>, std::io::Error> { let accounts = rpc @@ -150,7 +150,7 @@ pub fn fetch_all_proposal_v1( #[cfg(feature = "fetch")] pub fn fetch_maybe_proposal_v1( - rpc: &solana_client::rpc_client::RpcClient, + rpc: &solana_rpc_client::rpc_client::RpcClient, address: &solana_address::Address, ) -> Result, std::io::Error> { let accounts = fetch_all_maybe_proposal_v1(rpc, &[*address])?; @@ -159,7 +159,7 @@ pub fn fetch_maybe_proposal_v1( #[cfg(feature = "fetch")] pub fn fetch_all_maybe_proposal_v1( - rpc: &solana_client::rpc_client::RpcClient, + rpc: &solana_rpc_client::rpc_client::RpcClient, addresses: &[solana_address::Address], ) -> Result>, std::io::Error> { let accounts = rpc diff --git a/e2e/governance/src/generated/accounts/proposal_v2.rs b/e2e/governance/src/generated/accounts/proposal_v2.rs index 103cf8f..ba8be19 100644 --- a/e2e/governance/src/generated/accounts/proposal_v2.rs +++ b/e2e/governance/src/generated/accounts/proposal_v2.rs @@ -118,7 +118,7 @@ impl<'a> TryFrom<&solana_account_info::AccountInfo<'a>> for ProposalV2 { #[cfg(feature = "fetch")] pub fn fetch_proposal_v2( - rpc: &solana_client::rpc_client::RpcClient, + rpc: &solana_rpc_client::rpc_client::RpcClient, address: &solana_address::Address, ) -> Result, std::io::Error> { let accounts = fetch_all_proposal_v2(rpc, &[*address])?; @@ -127,7 +127,7 @@ pub fn fetch_proposal_v2( #[cfg(feature = "fetch")] pub fn fetch_all_proposal_v2( - rpc: &solana_client::rpc_client::RpcClient, + rpc: &solana_rpc_client::rpc_client::RpcClient, addresses: &[solana_address::Address], ) -> Result>, std::io::Error> { let accounts = rpc @@ -156,7 +156,7 @@ pub fn fetch_all_proposal_v2( #[cfg(feature = "fetch")] pub fn fetch_maybe_proposal_v2( - rpc: &solana_client::rpc_client::RpcClient, + rpc: &solana_rpc_client::rpc_client::RpcClient, address: &solana_address::Address, ) -> Result, std::io::Error> { let accounts = fetch_all_maybe_proposal_v2(rpc, &[*address])?; @@ -165,7 +165,7 @@ pub fn fetch_maybe_proposal_v2( #[cfg(feature = "fetch")] pub fn fetch_all_maybe_proposal_v2( - rpc: &solana_client::rpc_client::RpcClient, + rpc: &solana_rpc_client::rpc_client::RpcClient, addresses: &[solana_address::Address], ) -> Result>, std::io::Error> { let accounts = rpc diff --git a/e2e/governance/src/generated/accounts/realm_config_account.rs b/e2e/governance/src/generated/accounts/realm_config_account.rs index 4e77661..a49e893 100644 --- a/e2e/governance/src/generated/accounts/realm_config_account.rs +++ b/e2e/governance/src/generated/accounts/realm_config_account.rs @@ -71,7 +71,7 @@ impl<'a> TryFrom<&solana_account_info::AccountInfo<'a>> for RealmConfigAccount { #[cfg(feature = "fetch")] pub fn fetch_realm_config_account( - rpc: &solana_client::rpc_client::RpcClient, + rpc: &solana_rpc_client::rpc_client::RpcClient, address: &solana_address::Address, ) -> Result, std::io::Error> { let accounts = fetch_all_realm_config_account(rpc, &[*address])?; @@ -80,7 +80,7 @@ pub fn fetch_realm_config_account( #[cfg(feature = "fetch")] pub fn fetch_all_realm_config_account( - rpc: &solana_client::rpc_client::RpcClient, + rpc: &solana_rpc_client::rpc_client::RpcClient, addresses: &[solana_address::Address], ) -> Result>, std::io::Error> { let accounts = rpc @@ -109,7 +109,7 @@ pub fn fetch_all_realm_config_account( #[cfg(feature = "fetch")] pub fn fetch_maybe_realm_config_account( - rpc: &solana_client::rpc_client::RpcClient, + rpc: &solana_rpc_client::rpc_client::RpcClient, address: &solana_address::Address, ) -> Result, std::io::Error> { let accounts = fetch_all_maybe_realm_config_account(rpc, &[*address])?; @@ -118,7 +118,7 @@ pub fn fetch_maybe_realm_config_account( #[cfg(feature = "fetch")] pub fn fetch_all_maybe_realm_config_account( - rpc: &solana_client::rpc_client::RpcClient, + rpc: &solana_rpc_client::rpc_client::RpcClient, addresses: &[solana_address::Address], ) -> Result>, std::io::Error> { let accounts = rpc diff --git a/e2e/governance/src/generated/accounts/realm_v1.rs b/e2e/governance/src/generated/accounts/realm_v1.rs index 567bfe6..b7a2a95 100644 --- a/e2e/governance/src/generated/accounts/realm_v1.rs +++ b/e2e/governance/src/generated/accounts/realm_v1.rs @@ -73,7 +73,7 @@ impl<'a> TryFrom<&solana_account_info::AccountInfo<'a>> for RealmV1 { #[cfg(feature = "fetch")] pub fn fetch_realm_v1( - rpc: &solana_client::rpc_client::RpcClient, + rpc: &solana_rpc_client::rpc_client::RpcClient, address: &solana_address::Address, ) -> Result, std::io::Error> { let accounts = fetch_all_realm_v1(rpc, &[*address])?; @@ -82,7 +82,7 @@ pub fn fetch_realm_v1( #[cfg(feature = "fetch")] pub fn fetch_all_realm_v1( - rpc: &solana_client::rpc_client::RpcClient, + rpc: &solana_rpc_client::rpc_client::RpcClient, addresses: &[solana_address::Address], ) -> Result>, std::io::Error> { let accounts = rpc @@ -111,7 +111,7 @@ pub fn fetch_all_realm_v1( #[cfg(feature = "fetch")] pub fn fetch_maybe_realm_v1( - rpc: &solana_client::rpc_client::RpcClient, + rpc: &solana_rpc_client::rpc_client::RpcClient, address: &solana_address::Address, ) -> Result, std::io::Error> { let accounts = fetch_all_maybe_realm_v1(rpc, &[*address])?; @@ -120,7 +120,7 @@ pub fn fetch_maybe_realm_v1( #[cfg(feature = "fetch")] pub fn fetch_all_maybe_realm_v1( - rpc: &solana_client::rpc_client::RpcClient, + rpc: &solana_rpc_client::rpc_client::RpcClient, addresses: &[solana_address::Address], ) -> Result>, std::io::Error> { let accounts = rpc diff --git a/e2e/governance/src/generated/accounts/realm_v2.rs b/e2e/governance/src/generated/accounts/realm_v2.rs index 52873d9..c9be104 100644 --- a/e2e/governance/src/generated/accounts/realm_v2.rs +++ b/e2e/governance/src/generated/accounts/realm_v2.rs @@ -74,7 +74,7 @@ impl<'a> TryFrom<&solana_account_info::AccountInfo<'a>> for RealmV2 { #[cfg(feature = "fetch")] pub fn fetch_realm_v2( - rpc: &solana_client::rpc_client::RpcClient, + rpc: &solana_rpc_client::rpc_client::RpcClient, address: &solana_address::Address, ) -> Result, std::io::Error> { let accounts = fetch_all_realm_v2(rpc, &[*address])?; @@ -83,7 +83,7 @@ pub fn fetch_realm_v2( #[cfg(feature = "fetch")] pub fn fetch_all_realm_v2( - rpc: &solana_client::rpc_client::RpcClient, + rpc: &solana_rpc_client::rpc_client::RpcClient, addresses: &[solana_address::Address], ) -> Result>, std::io::Error> { let accounts = rpc @@ -112,7 +112,7 @@ pub fn fetch_all_realm_v2( #[cfg(feature = "fetch")] pub fn fetch_maybe_realm_v2( - rpc: &solana_client::rpc_client::RpcClient, + rpc: &solana_rpc_client::rpc_client::RpcClient, address: &solana_address::Address, ) -> Result, std::io::Error> { let accounts = fetch_all_maybe_realm_v2(rpc, &[*address])?; @@ -121,7 +121,7 @@ pub fn fetch_maybe_realm_v2( #[cfg(feature = "fetch")] pub fn fetch_all_maybe_realm_v2( - rpc: &solana_client::rpc_client::RpcClient, + rpc: &solana_rpc_client::rpc_client::RpcClient, addresses: &[solana_address::Address], ) -> Result>, std::io::Error> { let accounts = rpc diff --git a/e2e/governance/src/generated/accounts/required_signatory.rs b/e2e/governance/src/generated/accounts/required_signatory.rs index 9c6ba22..6c901f0 100644 --- a/e2e/governance/src/generated/accounts/required_signatory.rs +++ b/e2e/governance/src/generated/accounts/required_signatory.rs @@ -79,7 +79,7 @@ impl<'a> TryFrom<&solana_account_info::AccountInfo<'a>> for RequiredSignatory { #[cfg(feature = "fetch")] pub fn fetch_required_signatory( - rpc: &solana_client::rpc_client::RpcClient, + rpc: &solana_rpc_client::rpc_client::RpcClient, address: &solana_address::Address, ) -> Result, std::io::Error> { let accounts = fetch_all_required_signatory(rpc, &[*address])?; @@ -88,7 +88,7 @@ pub fn fetch_required_signatory( #[cfg(feature = "fetch")] pub fn fetch_all_required_signatory( - rpc: &solana_client::rpc_client::RpcClient, + rpc: &solana_rpc_client::rpc_client::RpcClient, addresses: &[solana_address::Address], ) -> Result>, std::io::Error> { let accounts = rpc @@ -117,7 +117,7 @@ pub fn fetch_all_required_signatory( #[cfg(feature = "fetch")] pub fn fetch_maybe_required_signatory( - rpc: &solana_client::rpc_client::RpcClient, + rpc: &solana_rpc_client::rpc_client::RpcClient, address: &solana_address::Address, ) -> Result, std::io::Error> { let accounts = fetch_all_maybe_required_signatory(rpc, &[*address])?; @@ -126,7 +126,7 @@ pub fn fetch_maybe_required_signatory( #[cfg(feature = "fetch")] pub fn fetch_all_maybe_required_signatory( - rpc: &solana_client::rpc_client::RpcClient, + rpc: &solana_rpc_client::rpc_client::RpcClient, addresses: &[solana_address::Address], ) -> Result>, std::io::Error> { let accounts = rpc diff --git a/e2e/governance/src/generated/accounts/signatory_record_v1.rs b/e2e/governance/src/generated/accounts/signatory_record_v1.rs index 4e5ae19..065a15e 100644 --- a/e2e/governance/src/generated/accounts/signatory_record_v1.rs +++ b/e2e/governance/src/generated/accounts/signatory_record_v1.rs @@ -75,7 +75,7 @@ impl<'a> TryFrom<&solana_account_info::AccountInfo<'a>> for SignatoryRecordV1 { #[cfg(feature = "fetch")] pub fn fetch_signatory_record_v1( - rpc: &solana_client::rpc_client::RpcClient, + rpc: &solana_rpc_client::rpc_client::RpcClient, address: &solana_address::Address, ) -> Result, std::io::Error> { let accounts = fetch_all_signatory_record_v1(rpc, &[*address])?; @@ -84,7 +84,7 @@ pub fn fetch_signatory_record_v1( #[cfg(feature = "fetch")] pub fn fetch_all_signatory_record_v1( - rpc: &solana_client::rpc_client::RpcClient, + rpc: &solana_rpc_client::rpc_client::RpcClient, addresses: &[solana_address::Address], ) -> Result>, std::io::Error> { let accounts = rpc @@ -113,7 +113,7 @@ pub fn fetch_all_signatory_record_v1( #[cfg(feature = "fetch")] pub fn fetch_maybe_signatory_record_v1( - rpc: &solana_client::rpc_client::RpcClient, + rpc: &solana_rpc_client::rpc_client::RpcClient, address: &solana_address::Address, ) -> Result, std::io::Error> { let accounts = fetch_all_maybe_signatory_record_v1(rpc, &[*address])?; @@ -122,7 +122,7 @@ pub fn fetch_maybe_signatory_record_v1( #[cfg(feature = "fetch")] pub fn fetch_all_maybe_signatory_record_v1( - rpc: &solana_client::rpc_client::RpcClient, + rpc: &solana_rpc_client::rpc_client::RpcClient, addresses: &[solana_address::Address], ) -> Result>, std::io::Error> { let accounts = rpc diff --git a/e2e/governance/src/generated/accounts/signatory_record_v2.rs b/e2e/governance/src/generated/accounts/signatory_record_v2.rs index 0d983f7..7b476d1 100644 --- a/e2e/governance/src/generated/accounts/signatory_record_v2.rs +++ b/e2e/governance/src/generated/accounts/signatory_record_v2.rs @@ -76,7 +76,7 @@ impl<'a> TryFrom<&solana_account_info::AccountInfo<'a>> for SignatoryRecordV2 { #[cfg(feature = "fetch")] pub fn fetch_signatory_record_v2( - rpc: &solana_client::rpc_client::RpcClient, + rpc: &solana_rpc_client::rpc_client::RpcClient, address: &solana_address::Address, ) -> Result, std::io::Error> { let accounts = fetch_all_signatory_record_v2(rpc, &[*address])?; @@ -85,7 +85,7 @@ pub fn fetch_signatory_record_v2( #[cfg(feature = "fetch")] pub fn fetch_all_signatory_record_v2( - rpc: &solana_client::rpc_client::RpcClient, + rpc: &solana_rpc_client::rpc_client::RpcClient, addresses: &[solana_address::Address], ) -> Result>, std::io::Error> { let accounts = rpc @@ -114,7 +114,7 @@ pub fn fetch_all_signatory_record_v2( #[cfg(feature = "fetch")] pub fn fetch_maybe_signatory_record_v2( - rpc: &solana_client::rpc_client::RpcClient, + rpc: &solana_rpc_client::rpc_client::RpcClient, address: &solana_address::Address, ) -> Result, std::io::Error> { let accounts = fetch_all_maybe_signatory_record_v2(rpc, &[*address])?; @@ -123,7 +123,7 @@ pub fn fetch_maybe_signatory_record_v2( #[cfg(feature = "fetch")] pub fn fetch_all_maybe_signatory_record_v2( - rpc: &solana_client::rpc_client::RpcClient, + rpc: &solana_rpc_client::rpc_client::RpcClient, addresses: &[solana_address::Address], ) -> Result>, std::io::Error> { let accounts = rpc diff --git a/e2e/governance/src/generated/accounts/token_owner_record_v1.rs b/e2e/governance/src/generated/accounts/token_owner_record_v1.rs index ec598ec..43528b7 100644 --- a/e2e/governance/src/generated/accounts/token_owner_record_v1.rs +++ b/e2e/governance/src/generated/accounts/token_owner_record_v1.rs @@ -93,7 +93,7 @@ impl<'a> TryFrom<&solana_account_info::AccountInfo<'a>> for TokenOwnerRecordV1 { #[cfg(feature = "fetch")] pub fn fetch_token_owner_record_v1( - rpc: &solana_client::rpc_client::RpcClient, + rpc: &solana_rpc_client::rpc_client::RpcClient, address: &solana_address::Address, ) -> Result, std::io::Error> { let accounts = fetch_all_token_owner_record_v1(rpc, &[*address])?; @@ -102,7 +102,7 @@ pub fn fetch_token_owner_record_v1( #[cfg(feature = "fetch")] pub fn fetch_all_token_owner_record_v1( - rpc: &solana_client::rpc_client::RpcClient, + rpc: &solana_rpc_client::rpc_client::RpcClient, addresses: &[solana_address::Address], ) -> Result>, std::io::Error> { let accounts = rpc @@ -131,7 +131,7 @@ pub fn fetch_all_token_owner_record_v1( #[cfg(feature = "fetch")] pub fn fetch_maybe_token_owner_record_v1( - rpc: &solana_client::rpc_client::RpcClient, + rpc: &solana_rpc_client::rpc_client::RpcClient, address: &solana_address::Address, ) -> Result, std::io::Error> { let accounts = fetch_all_maybe_token_owner_record_v1(rpc, &[*address])?; @@ -140,7 +140,7 @@ pub fn fetch_maybe_token_owner_record_v1( #[cfg(feature = "fetch")] pub fn fetch_all_maybe_token_owner_record_v1( - rpc: &solana_client::rpc_client::RpcClient, + rpc: &solana_rpc_client::rpc_client::RpcClient, addresses: &[solana_address::Address], ) -> Result>, std::io::Error> { let accounts = rpc diff --git a/e2e/governance/src/generated/accounts/token_owner_record_v2.rs b/e2e/governance/src/generated/accounts/token_owner_record_v2.rs index d2cbf3d..1edc54b 100644 --- a/e2e/governance/src/generated/accounts/token_owner_record_v2.rs +++ b/e2e/governance/src/generated/accounts/token_owner_record_v2.rs @@ -94,7 +94,7 @@ impl<'a> TryFrom<&solana_account_info::AccountInfo<'a>> for TokenOwnerRecordV2 { #[cfg(feature = "fetch")] pub fn fetch_token_owner_record_v2( - rpc: &solana_client::rpc_client::RpcClient, + rpc: &solana_rpc_client::rpc_client::RpcClient, address: &solana_address::Address, ) -> Result, std::io::Error> { let accounts = fetch_all_token_owner_record_v2(rpc, &[*address])?; @@ -103,7 +103,7 @@ pub fn fetch_token_owner_record_v2( #[cfg(feature = "fetch")] pub fn fetch_all_token_owner_record_v2( - rpc: &solana_client::rpc_client::RpcClient, + rpc: &solana_rpc_client::rpc_client::RpcClient, addresses: &[solana_address::Address], ) -> Result>, std::io::Error> { let accounts = rpc @@ -132,7 +132,7 @@ pub fn fetch_all_token_owner_record_v2( #[cfg(feature = "fetch")] pub fn fetch_maybe_token_owner_record_v2( - rpc: &solana_client::rpc_client::RpcClient, + rpc: &solana_rpc_client::rpc_client::RpcClient, address: &solana_address::Address, ) -> Result, std::io::Error> { let accounts = fetch_all_maybe_token_owner_record_v2(rpc, &[*address])?; @@ -141,7 +141,7 @@ pub fn fetch_maybe_token_owner_record_v2( #[cfg(feature = "fetch")] pub fn fetch_all_maybe_token_owner_record_v2( - rpc: &solana_client::rpc_client::RpcClient, + rpc: &solana_rpc_client::rpc_client::RpcClient, addresses: &[solana_address::Address], ) -> Result>, std::io::Error> { let accounts = rpc diff --git a/e2e/governance/src/generated/accounts/vote_record_v1.rs b/e2e/governance/src/generated/accounts/vote_record_v1.rs index 33f964d..a874558 100644 --- a/e2e/governance/src/generated/accounts/vote_record_v1.rs +++ b/e2e/governance/src/generated/accounts/vote_record_v1.rs @@ -84,7 +84,7 @@ impl<'a> TryFrom<&solana_account_info::AccountInfo<'a>> for VoteRecordV1 { #[cfg(feature = "fetch")] pub fn fetch_vote_record_v1( - rpc: &solana_client::rpc_client::RpcClient, + rpc: &solana_rpc_client::rpc_client::RpcClient, address: &solana_address::Address, ) -> Result, std::io::Error> { let accounts = fetch_all_vote_record_v1(rpc, &[*address])?; @@ -93,7 +93,7 @@ pub fn fetch_vote_record_v1( #[cfg(feature = "fetch")] pub fn fetch_all_vote_record_v1( - rpc: &solana_client::rpc_client::RpcClient, + rpc: &solana_rpc_client::rpc_client::RpcClient, addresses: &[solana_address::Address], ) -> Result>, std::io::Error> { let accounts = rpc @@ -122,7 +122,7 @@ pub fn fetch_all_vote_record_v1( #[cfg(feature = "fetch")] pub fn fetch_maybe_vote_record_v1( - rpc: &solana_client::rpc_client::RpcClient, + rpc: &solana_rpc_client::rpc_client::RpcClient, address: &solana_address::Address, ) -> Result, std::io::Error> { let accounts = fetch_all_maybe_vote_record_v1(rpc, &[*address])?; @@ -131,7 +131,7 @@ pub fn fetch_maybe_vote_record_v1( #[cfg(feature = "fetch")] pub fn fetch_all_maybe_vote_record_v1( - rpc: &solana_client::rpc_client::RpcClient, + rpc: &solana_rpc_client::rpc_client::RpcClient, addresses: &[solana_address::Address], ) -> Result>, std::io::Error> { let accounts = rpc diff --git a/e2e/governance/src/generated/accounts/vote_record_v2.rs b/e2e/governance/src/generated/accounts/vote_record_v2.rs index 5a6ebd6..19660e6 100644 --- a/e2e/governance/src/generated/accounts/vote_record_v2.rs +++ b/e2e/governance/src/generated/accounts/vote_record_v2.rs @@ -86,7 +86,7 @@ impl<'a> TryFrom<&solana_account_info::AccountInfo<'a>> for VoteRecordV2 { #[cfg(feature = "fetch")] pub fn fetch_vote_record_v2( - rpc: &solana_client::rpc_client::RpcClient, + rpc: &solana_rpc_client::rpc_client::RpcClient, address: &solana_address::Address, ) -> Result, std::io::Error> { let accounts = fetch_all_vote_record_v2(rpc, &[*address])?; @@ -95,7 +95,7 @@ pub fn fetch_vote_record_v2( #[cfg(feature = "fetch")] pub fn fetch_all_vote_record_v2( - rpc: &solana_client::rpc_client::RpcClient, + rpc: &solana_rpc_client::rpc_client::RpcClient, addresses: &[solana_address::Address], ) -> Result>, std::io::Error> { let accounts = rpc @@ -124,7 +124,7 @@ pub fn fetch_all_vote_record_v2( #[cfg(feature = "fetch")] pub fn fetch_maybe_vote_record_v2( - rpc: &solana_client::rpc_client::RpcClient, + rpc: &solana_rpc_client::rpc_client::RpcClient, address: &solana_address::Address, ) -> Result, std::io::Error> { let accounts = fetch_all_maybe_vote_record_v2(rpc, &[*address])?; @@ -133,7 +133,7 @@ pub fn fetch_maybe_vote_record_v2( #[cfg(feature = "fetch")] pub fn fetch_all_maybe_vote_record_v2( - rpc: &solana_client::rpc_client::RpcClient, + rpc: &solana_rpc_client::rpc_client::RpcClient, addresses: &[solana_address::Address], ) -> Result>, std::io::Error> { let accounts = rpc From 564ac58771513bc7fdde14d4e31f8424b070e00e Mon Sep 17 00:00:00 2001 From: ioxde <228087182+ioxde@users.noreply.github.com> Date: Wed, 3 Jun 2026 21:20:46 -0700 Subject: [PATCH 22/24] Bump pinned codama fork --- pnpm-lock.yaml | 142 ++++++++++++++++++++++---------------------- pnpm-workspace.yaml | 18 +++--- 2 files changed, 80 insertions(+), 80 deletions(-) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index da49978..64c9068 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -5,31 +5,31 @@ settings: excludeLinksFromLockfile: false overrides: - '@codama/errors': https://pkg.pr.new/ioxde/codama/@codama/errors@963c0dbe9c2651348789fd8f583164d9b20619c1 - '@codama/node-types': https://pkg.pr.new/ioxde/codama/@codama/node-types@963c0dbe9c2651348789fd8f583164d9b20619c1 - '@codama/nodes': https://pkg.pr.new/ioxde/codama/@codama/nodes@963c0dbe9c2651348789fd8f583164d9b20619c1 - '@codama/nodes-from-anchor': https://pkg.pr.new/ioxde/codama/@codama/nodes-from-anchor@963c0dbe9c2651348789fd8f583164d9b20619c1 - '@codama/renderers-core': https://pkg.pr.new/ioxde/codama/@codama/renderers-core@963c0dbe9c2651348789fd8f583164d9b20619c1 - '@codama/visitors': https://pkg.pr.new/ioxde/codama/@codama/visitors@963c0dbe9c2651348789fd8f583164d9b20619c1 - '@codama/visitors-core': https://pkg.pr.new/ioxde/codama/@codama/visitors-core@963c0dbe9c2651348789fd8f583164d9b20619c1 - '@codama/validators': https://pkg.pr.new/ioxde/codama/@codama/validators@963c0dbe9c2651348789fd8f583164d9b20619c1 + '@codama/errors': https://pkg.pr.new/ioxde/codama/@codama/errors@c8c4954ff716d41c81c9aad5d306470b83715b27 + '@codama/node-types': https://pkg.pr.new/ioxde/codama/@codama/node-types@c8c4954ff716d41c81c9aad5d306470b83715b27 + '@codama/nodes': https://pkg.pr.new/ioxde/codama/@codama/nodes@c8c4954ff716d41c81c9aad5d306470b83715b27 + '@codama/nodes-from-anchor': https://pkg.pr.new/ioxde/codama/@codama/nodes-from-anchor@c8c4954ff716d41c81c9aad5d306470b83715b27 + '@codama/renderers-core': https://pkg.pr.new/ioxde/codama/@codama/renderers-core@c8c4954ff716d41c81c9aad5d306470b83715b27 + '@codama/visitors': https://pkg.pr.new/ioxde/codama/@codama/visitors@c8c4954ff716d41c81c9aad5d306470b83715b27 + '@codama/visitors-core': https://pkg.pr.new/ioxde/codama/@codama/visitors-core@c8c4954ff716d41c81c9aad5d306470b83715b27 + '@codama/validators': https://pkg.pr.new/ioxde/codama/@codama/validators@c8c4954ff716d41c81c9aad5d306470b83715b27 importers: .: dependencies: '@codama/errors': - specifier: https://pkg.pr.new/ioxde/codama/@codama/errors@963c0dbe9c2651348789fd8f583164d9b20619c1 - version: https://pkg.pr.new/ioxde/codama/@codama/errors@963c0dbe9c2651348789fd8f583164d9b20619c1 + specifier: https://pkg.pr.new/ioxde/codama/@codama/errors@c8c4954ff716d41c81c9aad5d306470b83715b27 + version: https://pkg.pr.new/ioxde/codama/@codama/errors@c8c4954ff716d41c81c9aad5d306470b83715b27 '@codama/nodes': - specifier: https://pkg.pr.new/ioxde/codama/@codama/nodes@963c0dbe9c2651348789fd8f583164d9b20619c1 - version: https://pkg.pr.new/ioxde/codama/@codama/nodes@963c0dbe9c2651348789fd8f583164d9b20619c1 + specifier: https://pkg.pr.new/ioxde/codama/@codama/nodes@c8c4954ff716d41c81c9aad5d306470b83715b27 + version: https://pkg.pr.new/ioxde/codama/@codama/nodes@c8c4954ff716d41c81c9aad5d306470b83715b27 '@codama/renderers-core': - specifier: https://pkg.pr.new/ioxde/codama/@codama/renderers-core@963c0dbe9c2651348789fd8f583164d9b20619c1 - version: https://pkg.pr.new/ioxde/codama/@codama/renderers-core@963c0dbe9c2651348789fd8f583164d9b20619c1 + specifier: https://pkg.pr.new/ioxde/codama/@codama/renderers-core@c8c4954ff716d41c81c9aad5d306470b83715b27 + version: https://pkg.pr.new/ioxde/codama/@codama/renderers-core@c8c4954ff716d41c81c9aad5d306470b83715b27 '@codama/visitors-core': - specifier: https://pkg.pr.new/ioxde/codama/@codama/visitors-core@963c0dbe9c2651348789fd8f583164d9b20619c1 - version: https://pkg.pr.new/ioxde/codama/@codama/visitors-core@963c0dbe9c2651348789fd8f583164d9b20619c1 + specifier: https://pkg.pr.new/ioxde/codama/@codama/visitors-core@c8c4954ff716d41c81c9aad5d306470b83715b27 + version: https://pkg.pr.new/ioxde/codama/@codama/visitors-core@c8c4954ff716d41c81c9aad5d306470b83715b27 '@iarna/toml': specifier: ^2.2.5 version: 2.2.5 @@ -53,8 +53,8 @@ importers: specifier: ^2.29.7 version: 2.29.8(@types/node@25.2.3) '@codama/nodes-from-anchor': - specifier: https://pkg.pr.new/ioxde/codama/@codama/nodes-from-anchor@963c0dbe9c2651348789fd8f583164d9b20619c1 - version: https://pkg.pr.new/ioxde/codama/@codama/nodes-from-anchor@963c0dbe9c2651348789fd8f583164d9b20619c1(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) + specifier: https://pkg.pr.new/ioxde/codama/@codama/nodes-from-anchor@c8c4954ff716d41c81c9aad5d306470b83715b27 + version: https://pkg.pr.new/ioxde/codama/@codama/nodes-from-anchor@c8c4954ff716d41c81c9aad5d306470b83715b27(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) '@solana/eslint-config-solana': specifier: ^5.0.0 version: 5.0.0(@eslint/js@9.39.1)(@types/eslint__js@8.42.3)(eslint-plugin-jest@29.0.1(@typescript-eslint/eslint-plugin@8.43.0(@typescript-eslint/parser@8.43.0(eslint@9.39.1)(typescript@5.9.3))(eslint@9.39.1)(typescript@5.9.3))(eslint@9.39.1)(jest@30.1.3(@types/node@25.2.3))(typescript@5.9.3))(eslint-plugin-react-hooks@5.2.0(eslint@9.39.1))(eslint-plugin-simple-import-sort@12.1.1(eslint@9.39.1))(eslint-plugin-sort-keys-fix@1.1.2)(eslint-plugin-typescript-sort-keys@3.3.0(@typescript-eslint/parser@8.43.0(eslint@9.39.1)(typescript@5.9.3))(eslint@9.39.1)(typescript@5.9.3))(eslint@9.39.1)(globals@14.0.0)(jest@30.1.3(@types/node@25.2.3))(typescript-eslint@8.43.0(eslint@9.39.1)(typescript@5.9.3))(typescript@5.9.3) @@ -327,37 +327,37 @@ packages: '@changesets/write@0.4.0': resolution: {integrity: sha512-CdTLvIOPiCNuH71pyDu3rA+Q0n65cmAbXnwWH84rKGiFumFzkmHNT8KHTMEchcxN+Kl8I54xGUhJ7l3E7X396Q==} - '@codama/errors@https://pkg.pr.new/ioxde/codama/@codama/errors@963c0dbe9c2651348789fd8f583164d9b20619c1': - resolution: {tarball: https://pkg.pr.new/ioxde/codama/@codama/errors@963c0dbe9c2651348789fd8f583164d9b20619c1} + '@codama/errors@https://pkg.pr.new/ioxde/codama/@codama/errors@c8c4954ff716d41c81c9aad5d306470b83715b27': + resolution: {tarball: https://pkg.pr.new/ioxde/codama/@codama/errors@c8c4954ff716d41c81c9aad5d306470b83715b27} version: 1.7.0 hasBin: true - '@codama/fragments@https://pkg.pr.new/ioxde/codama/@codama/fragments@963c0db': - resolution: {tarball: https://pkg.pr.new/ioxde/codama/@codama/fragments@963c0db} + '@codama/fragments@https://pkg.pr.new/ioxde/codama/@codama/fragments@c8c4954': + resolution: {tarball: https://pkg.pr.new/ioxde/codama/@codama/fragments@c8c4954} version: 0.1.0 - '@codama/node-types@https://pkg.pr.new/ioxde/codama/@codama/node-types@963c0dbe9c2651348789fd8f583164d9b20619c1': - resolution: {tarball: https://pkg.pr.new/ioxde/codama/@codama/node-types@963c0dbe9c2651348789fd8f583164d9b20619c1} + '@codama/node-types@https://pkg.pr.new/ioxde/codama/@codama/node-types@c8c4954ff716d41c81c9aad5d306470b83715b27': + resolution: {tarball: https://pkg.pr.new/ioxde/codama/@codama/node-types@c8c4954ff716d41c81c9aad5d306470b83715b27} version: 1.7.0 - '@codama/nodes-from-anchor@https://pkg.pr.new/ioxde/codama/@codama/nodes-from-anchor@963c0dbe9c2651348789fd8f583164d9b20619c1': - resolution: {tarball: https://pkg.pr.new/ioxde/codama/@codama/nodes-from-anchor@963c0dbe9c2651348789fd8f583164d9b20619c1} + '@codama/nodes-from-anchor@https://pkg.pr.new/ioxde/codama/@codama/nodes-from-anchor@c8c4954ff716d41c81c9aad5d306470b83715b27': + resolution: {tarball: https://pkg.pr.new/ioxde/codama/@codama/nodes-from-anchor@c8c4954ff716d41c81c9aad5d306470b83715b27} version: 1.5.0 - '@codama/nodes@https://pkg.pr.new/ioxde/codama/@codama/nodes@963c0dbe9c2651348789fd8f583164d9b20619c1': - resolution: {tarball: https://pkg.pr.new/ioxde/codama/@codama/nodes@963c0dbe9c2651348789fd8f583164d9b20619c1} + '@codama/nodes@https://pkg.pr.new/ioxde/codama/@codama/nodes@c8c4954ff716d41c81c9aad5d306470b83715b27': + resolution: {tarball: https://pkg.pr.new/ioxde/codama/@codama/nodes@c8c4954ff716d41c81c9aad5d306470b83715b27} version: 1.7.0 - '@codama/renderers-core@https://pkg.pr.new/ioxde/codama/@codama/renderers-core@963c0dbe9c2651348789fd8f583164d9b20619c1': - resolution: {tarball: https://pkg.pr.new/ioxde/codama/@codama/renderers-core@963c0dbe9c2651348789fd8f583164d9b20619c1} + '@codama/renderers-core@https://pkg.pr.new/ioxde/codama/@codama/renderers-core@c8c4954ff716d41c81c9aad5d306470b83715b27': + resolution: {tarball: https://pkg.pr.new/ioxde/codama/@codama/renderers-core@c8c4954ff716d41c81c9aad5d306470b83715b27} version: 1.3.8 - '@codama/visitors-core@https://pkg.pr.new/ioxde/codama/@codama/visitors-core@963c0dbe9c2651348789fd8f583164d9b20619c1': - resolution: {tarball: https://pkg.pr.new/ioxde/codama/@codama/visitors-core@963c0dbe9c2651348789fd8f583164d9b20619c1} + '@codama/visitors-core@https://pkg.pr.new/ioxde/codama/@codama/visitors-core@c8c4954ff716d41c81c9aad5d306470b83715b27': + resolution: {tarball: https://pkg.pr.new/ioxde/codama/@codama/visitors-core@c8c4954ff716d41c81c9aad5d306470b83715b27} version: 1.7.0 - '@codama/visitors@https://pkg.pr.new/ioxde/codama/@codama/visitors@963c0dbe9c2651348789fd8f583164d9b20619c1': - resolution: {tarball: https://pkg.pr.new/ioxde/codama/@codama/visitors@963c0dbe9c2651348789fd8f583164d9b20619c1} + '@codama/visitors@https://pkg.pr.new/ioxde/codama/@codama/visitors@c8c4954ff716d41c81c9aad5d306470b83715b27': + resolution: {tarball: https://pkg.pr.new/ioxde/codama/@codama/visitors@c8c4954ff716d41c81c9aad5d306470b83715b27} version: 1.7.0 '@emnapi/core@1.9.1': @@ -1763,8 +1763,8 @@ packages: resolution: {integrity: sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==} engines: {node: '>= 0.4'} - call-bind@1.0.8: - resolution: {integrity: sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww==} + call-bind@1.0.9: + resolution: {integrity: sha512-a/hy+pNsFUTR+Iz8TCJvXudKVLAnz/DyeSUo10I5yvFDQJBFU2s9uqQpoSrJlroHUKoKqzg+epxyP9lqFdzfBQ==} engines: {node: '>= 0.4'} call-bound@1.0.4: @@ -1956,8 +1956,8 @@ packages: es-module-lexer@1.7.0: resolution: {integrity: sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==} - es-object-atoms@1.1.1: - resolution: {integrity: sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==} + es-object-atoms@1.1.2: + resolution: {integrity: sha512-HWcBoN6NileqtSydK2FqHbS/LoDd2pqrnQHLyJzBj4kOp/ky2MWMN694xOfkK8/SnUsW2DH7EfyVlydKCsm1Zw==} engines: {node: '>= 0.4'} esbuild@0.25.12: @@ -2264,8 +2264,8 @@ packages: resolution: {integrity: sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==} engines: {node: '>= 0.4'} - hasown@2.0.2: - resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} + hasown@2.0.4: + resolution: {integrity: sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A==} engines: {node: '>= 0.4'} html-escaper@2.0.2: @@ -3712,52 +3712,52 @@ snapshots: human-id: 4.1.3 prettier: 2.8.8 - '@codama/errors@https://pkg.pr.new/ioxde/codama/@codama/errors@963c0dbe9c2651348789fd8f583164d9b20619c1': + '@codama/errors@https://pkg.pr.new/ioxde/codama/@codama/errors@c8c4954ff716d41c81c9aad5d306470b83715b27': dependencies: - '@codama/node-types': https://pkg.pr.new/ioxde/codama/@codama/node-types@963c0dbe9c2651348789fd8f583164d9b20619c1 + '@codama/node-types': https://pkg.pr.new/ioxde/codama/@codama/node-types@c8c4954ff716d41c81c9aad5d306470b83715b27 commander: 14.0.3 picocolors: 1.1.1 - '@codama/fragments@https://pkg.pr.new/ioxde/codama/@codama/fragments@963c0db': + '@codama/fragments@https://pkg.pr.new/ioxde/codama/@codama/fragments@c8c4954': dependencies: - '@codama/errors': https://pkg.pr.new/ioxde/codama/@codama/errors@963c0dbe9c2651348789fd8f583164d9b20619c1 + '@codama/errors': https://pkg.pr.new/ioxde/codama/@codama/errors@c8c4954ff716d41c81c9aad5d306470b83715b27 - '@codama/node-types@https://pkg.pr.new/ioxde/codama/@codama/node-types@963c0dbe9c2651348789fd8f583164d9b20619c1': {} + '@codama/node-types@https://pkg.pr.new/ioxde/codama/@codama/node-types@c8c4954ff716d41c81c9aad5d306470b83715b27': {} - '@codama/nodes-from-anchor@https://pkg.pr.new/ioxde/codama/@codama/nodes-from-anchor@963c0dbe9c2651348789fd8f583164d9b20619c1(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)': + '@codama/nodes-from-anchor@https://pkg.pr.new/ioxde/codama/@codama/nodes-from-anchor@c8c4954ff716d41c81c9aad5d306470b83715b27(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)': dependencies: - '@codama/errors': https://pkg.pr.new/ioxde/codama/@codama/errors@963c0dbe9c2651348789fd8f583164d9b20619c1 - '@codama/nodes': https://pkg.pr.new/ioxde/codama/@codama/nodes@963c0dbe9c2651348789fd8f583164d9b20619c1 - '@codama/visitors': https://pkg.pr.new/ioxde/codama/@codama/visitors@963c0dbe9c2651348789fd8f583164d9b20619c1 + '@codama/errors': https://pkg.pr.new/ioxde/codama/@codama/errors@c8c4954ff716d41c81c9aad5d306470b83715b27 + '@codama/nodes': https://pkg.pr.new/ioxde/codama/@codama/nodes@c8c4954ff716d41c81c9aad5d306470b83715b27 + '@codama/visitors': https://pkg.pr.new/ioxde/codama/@codama/visitors@c8c4954ff716d41c81c9aad5d306470b83715b27 '@noble/hashes': 2.0.1 '@solana/codecs': 5.5.1(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) transitivePeerDependencies: - fastestsmallesttextencoderdecoder - typescript - '@codama/nodes@https://pkg.pr.new/ioxde/codama/@codama/nodes@963c0dbe9c2651348789fd8f583164d9b20619c1': + '@codama/nodes@https://pkg.pr.new/ioxde/codama/@codama/nodes@c8c4954ff716d41c81c9aad5d306470b83715b27': dependencies: - '@codama/errors': https://pkg.pr.new/ioxde/codama/@codama/errors@963c0dbe9c2651348789fd8f583164d9b20619c1 - '@codama/node-types': https://pkg.pr.new/ioxde/codama/@codama/node-types@963c0dbe9c2651348789fd8f583164d9b20619c1 + '@codama/errors': https://pkg.pr.new/ioxde/codama/@codama/errors@c8c4954ff716d41c81c9aad5d306470b83715b27 + '@codama/node-types': https://pkg.pr.new/ioxde/codama/@codama/node-types@c8c4954ff716d41c81c9aad5d306470b83715b27 - '@codama/renderers-core@https://pkg.pr.new/ioxde/codama/@codama/renderers-core@963c0dbe9c2651348789fd8f583164d9b20619c1': + '@codama/renderers-core@https://pkg.pr.new/ioxde/codama/@codama/renderers-core@c8c4954ff716d41c81c9aad5d306470b83715b27': dependencies: - '@codama/errors': https://pkg.pr.new/ioxde/codama/@codama/errors@963c0dbe9c2651348789fd8f583164d9b20619c1 - '@codama/fragments': https://pkg.pr.new/ioxde/codama/@codama/fragments@963c0db - '@codama/nodes': https://pkg.pr.new/ioxde/codama/@codama/nodes@963c0dbe9c2651348789fd8f583164d9b20619c1 - '@codama/visitors-core': https://pkg.pr.new/ioxde/codama/@codama/visitors-core@963c0dbe9c2651348789fd8f583164d9b20619c1 + '@codama/errors': https://pkg.pr.new/ioxde/codama/@codama/errors@c8c4954ff716d41c81c9aad5d306470b83715b27 + '@codama/fragments': https://pkg.pr.new/ioxde/codama/@codama/fragments@c8c4954 + '@codama/nodes': https://pkg.pr.new/ioxde/codama/@codama/nodes@c8c4954ff716d41c81c9aad5d306470b83715b27 + '@codama/visitors-core': https://pkg.pr.new/ioxde/codama/@codama/visitors-core@c8c4954ff716d41c81c9aad5d306470b83715b27 - '@codama/visitors-core@https://pkg.pr.new/ioxde/codama/@codama/visitors-core@963c0dbe9c2651348789fd8f583164d9b20619c1': + '@codama/visitors-core@https://pkg.pr.new/ioxde/codama/@codama/visitors-core@c8c4954ff716d41c81c9aad5d306470b83715b27': dependencies: - '@codama/errors': https://pkg.pr.new/ioxde/codama/@codama/errors@963c0dbe9c2651348789fd8f583164d9b20619c1 - '@codama/nodes': https://pkg.pr.new/ioxde/codama/@codama/nodes@963c0dbe9c2651348789fd8f583164d9b20619c1 + '@codama/errors': https://pkg.pr.new/ioxde/codama/@codama/errors@c8c4954ff716d41c81c9aad5d306470b83715b27 + '@codama/nodes': https://pkg.pr.new/ioxde/codama/@codama/nodes@c8c4954ff716d41c81c9aad5d306470b83715b27 json-stable-stringify: 1.3.0 - '@codama/visitors@https://pkg.pr.new/ioxde/codama/@codama/visitors@963c0dbe9c2651348789fd8f583164d9b20619c1': + '@codama/visitors@https://pkg.pr.new/ioxde/codama/@codama/visitors@c8c4954ff716d41c81c9aad5d306470b83715b27': dependencies: - '@codama/errors': https://pkg.pr.new/ioxde/codama/@codama/errors@963c0dbe9c2651348789fd8f583164d9b20619c1 - '@codama/nodes': https://pkg.pr.new/ioxde/codama/@codama/nodes@963c0dbe9c2651348789fd8f583164d9b20619c1 - '@codama/visitors-core': https://pkg.pr.new/ioxde/codama/@codama/visitors-core@963c0dbe9c2651348789fd8f583164d9b20619c1 + '@codama/errors': https://pkg.pr.new/ioxde/codama/@codama/errors@c8c4954ff716d41c81c9aad5d306470b83715b27 + '@codama/nodes': https://pkg.pr.new/ioxde/codama/@codama/nodes@c8c4954ff716d41c81c9aad5d306470b83715b27 + '@codama/visitors-core': https://pkg.pr.new/ioxde/codama/@codama/visitors-core@c8c4954ff716d41c81c9aad5d306470b83715b27 '@emnapi/core@1.9.1': dependencies: @@ -5076,7 +5076,7 @@ snapshots: es-errors: 1.3.0 function-bind: 1.1.2 - call-bind@1.0.8: + call-bind@1.0.9: dependencies: call-bind-apply-helpers: 1.0.2 es-define-property: 1.0.1 @@ -5216,7 +5216,7 @@ snapshots: es-module-lexer@1.7.0: {} - es-object-atoms@1.1.1: + es-object-atoms@1.1.2: dependencies: es-errors: 1.3.0 @@ -5530,12 +5530,12 @@ snapshots: call-bind-apply-helpers: 1.0.2 es-define-property: 1.0.1 es-errors: 1.3.0 - es-object-atoms: 1.1.1 + es-object-atoms: 1.1.2 function-bind: 1.1.2 get-proto: 1.0.1 gopd: 1.2.0 has-symbols: 1.1.0 - hasown: 2.0.2 + hasown: 2.0.4 math-intrinsics: 1.1.0 get-package-type@0.1.0: {} @@ -5543,7 +5543,7 @@ snapshots: get-proto@1.0.1: dependencies: dunder-proto: 1.0.1 - es-object-atoms: 1.1.1 + es-object-atoms: 1.1.2 get-stream@6.0.1: {} @@ -5610,7 +5610,7 @@ snapshots: has-symbols@1.1.0: {} - hasown@2.0.2: + hasown@2.0.4: dependencies: function-bind: 1.1.2 @@ -6084,7 +6084,7 @@ snapshots: json-stable-stringify@1.3.0: dependencies: - call-bind: 1.0.8 + call-bind: 1.0.9 call-bound: 1.0.4 isarray: 2.0.5 jsonify: 0.0.1 diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index f76cf52..6cccea3 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -1,14 +1,14 @@ # Forked codama packages, served as prebuilt tarballs by pkg.pr.new # (producer: ioxde/codama .github/workflows/main.yml `publish-preview` job). -# Pinned to ioxde/codama@963c0db (main). workspace:* deps are rewritten by +# Pinned to ioxde/codama@c8c4954 (main). workspace:* deps are rewritten by # pkg.pr.new at publish time, so installing these resolves the whole fork set. # These are overrides only — not part of the published @codama/renderers-rust. overrides: - '@codama/errors': 'https://pkg.pr.new/ioxde/codama/@codama/errors@963c0dbe9c2651348789fd8f583164d9b20619c1' - '@codama/node-types': 'https://pkg.pr.new/ioxde/codama/@codama/node-types@963c0dbe9c2651348789fd8f583164d9b20619c1' - '@codama/nodes': 'https://pkg.pr.new/ioxde/codama/@codama/nodes@963c0dbe9c2651348789fd8f583164d9b20619c1' - '@codama/nodes-from-anchor': 'https://pkg.pr.new/ioxde/codama/@codama/nodes-from-anchor@963c0dbe9c2651348789fd8f583164d9b20619c1' - '@codama/renderers-core': 'https://pkg.pr.new/ioxde/codama/@codama/renderers-core@963c0dbe9c2651348789fd8f583164d9b20619c1' - '@codama/visitors': 'https://pkg.pr.new/ioxde/codama/@codama/visitors@963c0dbe9c2651348789fd8f583164d9b20619c1' - '@codama/visitors-core': 'https://pkg.pr.new/ioxde/codama/@codama/visitors-core@963c0dbe9c2651348789fd8f583164d9b20619c1' - '@codama/validators': 'https://pkg.pr.new/ioxde/codama/@codama/validators@963c0dbe9c2651348789fd8f583164d9b20619c1' + '@codama/errors': 'https://pkg.pr.new/ioxde/codama/@codama/errors@c8c4954ff716d41c81c9aad5d306470b83715b27' + '@codama/node-types': 'https://pkg.pr.new/ioxde/codama/@codama/node-types@c8c4954ff716d41c81c9aad5d306470b83715b27' + '@codama/nodes': 'https://pkg.pr.new/ioxde/codama/@codama/nodes@c8c4954ff716d41c81c9aad5d306470b83715b27' + '@codama/nodes-from-anchor': 'https://pkg.pr.new/ioxde/codama/@codama/nodes-from-anchor@c8c4954ff716d41c81c9aad5d306470b83715b27' + '@codama/renderers-core': 'https://pkg.pr.new/ioxde/codama/@codama/renderers-core@c8c4954ff716d41c81c9aad5d306470b83715b27' + '@codama/visitors': 'https://pkg.pr.new/ioxde/codama/@codama/visitors@c8c4954ff716d41c81c9aad5d306470b83715b27' + '@codama/visitors-core': 'https://pkg.pr.new/ioxde/codama/@codama/visitors-core@c8c4954ff716d41c81c9aad5d306470b83715b27' + '@codama/validators': 'https://pkg.pr.new/ioxde/codama/@codama/validators@c8c4954ff716d41c81c9aad5d306470b83715b27' From 641b9bba5d75df9e59577d257370a35fb05fd746 Mon Sep 17 00:00:00 2001 From: ioxde <228087182+ioxde@users.noreply.github.com> Date: Wed, 3 Jun 2026 10:58:07 -0700 Subject: [PATCH 23/24] Support dynamic program IDs and extra arguments in PDA derivation - Honor pdaValueNode.programId: builders derive PDAs against runtime account/argument program refs; helpers for dynamic-only PDAs take a program_address parameter, or bake in the IDL-pinned canonical address as a _PROGRAM_ADDRESS constant - Render instruction extraArguments (Anchor account-data seeds lowered to argument values) as required builder fields that feed PDA derivation without entering instruction data - Replace the local topological sort with codama's getResolvedInstructionInputsVisitor for dependency-first ordering; unresolvable PDAs (cycles, missing seed args) now hard-error instead of silently falling back to required accounts - Extract renderConstantSeedBytes and support publicKeyValueNode constant seeds as decoded 32-byte arrays - Regenerate anchor and raydium-launchpad e2e fixtures --- .../generated/instructions/create_guard.rs | 13 +- .../src/generated/instructions/execute.rs | 21 +- .../src/generated/instructions/initialize.rs | 23 +- .../generated/instructions/update_guard.rs | 13 +- e2e/anchor/src/lib.rs | 40 ++ .../instructions/create_token_owner_record.rs | 2 +- .../instructions/claim_platform_fee.rs | 2 +- .../generated/instructions/create_config.rs | 2 +- .../src/generated/instructions/initialize.rs | 4 +- .../generated/instructions/migrate_to_amm.rs | 72 +-- .../src/generated/pdas/amm_authority.rs | 14 +- .../src/generated/pdas/amm_base_vault.rs | 31 +- .../src/generated/pdas/amm_config.rs | 11 +- .../src/generated/pdas/amm_lp_mint.rs | 27 +- .../src/generated/pdas/amm_open_orders.rs | 31 +- .../src/generated/pdas/amm_pool.rs | 27 +- .../src/generated/pdas/amm_quote_vault.rs | 31 +- .../src/generated/pdas/amm_target_orders.rs | 29 +- .../src/generated/pdas/cpswap_authority.rs | 14 +- .../src/generated/pdas/cpswap_base_vault.rs | 9 +- .../src/generated/pdas/cpswap_lp_mint.rs | 9 +- .../src/generated/pdas/cpswap_observation.rs | 9 +- .../src/generated/pdas/cpswap_quote_vault.rs | 9 +- .../src/generated/pdas/lock_authority.rs | 14 +- e2e/raydium-launchpad/src/lib.rs | 102 +++++ public/templates/instructionsPageBuilder.njk | 14 +- public/templates/pdasPage.njk | 159 ++++++- src/getRenderMapVisitor.ts | 425 ++++++++++-------- test/instructionsPage.test.ts | 365 ++++++++++++++- test/pdasPage.test.ts | 61 +++ 30 files changed, 1181 insertions(+), 402 deletions(-) diff --git a/e2e/anchor/src/generated/instructions/create_guard.rs b/e2e/anchor/src/generated/instructions/create_guard.rs index 15c45e7..a4b979e 100644 --- a/e2e/anchor/src/generated/instructions/create_guard.rs +++ b/e2e/anchor/src/generated/instructions/create_guard.rs @@ -241,26 +241,25 @@ impl CreateGuardBuilder { } #[allow(clippy::clone_on_copy)] pub fn instruction(&self) -> solana_instruction::Instruction { + let mint = self.mint; let guard = self .guard .unwrap_or_else(|| crate::pdas::find_guard_pda(&self.mint).0); - let mint = self.mint; + let guard_authority = self.guard_authority; let mint_token_account = self.mint_token_account.unwrap_or_else(|| { solana_address::Address::find_program_address( &[ self.guard_authority.as_ref(), - self.token_program - .unwrap_or(solana_address::address!( - "TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb" - )) - .as_ref(), + &[ + 6, 221, 246, 225, 238, 117, 143, 222, 24, 66, 93, 188, 228, 108, 205, 218, + 182, 26, 252, 77, 131, 185, 13, 39, 254, 189, 249, 40, 216, 161, 139, 252, + ], self.mint.as_ref(), ], &solana_address::address!("ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL"), ) .0 }); - let guard_authority = self.guard_authority; let payer = self.payer; let associated_token_program = self.associated_token_program diff --git a/e2e/anchor/src/generated/instructions/execute.rs b/e2e/anchor/src/generated/instructions/execute.rs index 5ce2c95..152cba4 100644 --- a/e2e/anchor/src/generated/instructions/execute.rs +++ b/e2e/anchor/src/generated/instructions/execute.rs @@ -7,6 +7,7 @@ use borsh::BorshDeserialize; use borsh::BorshSerialize; +use solana_address::Address; pub const EXECUTE_DISCRIMINATOR: [u8; 8] = [105, 37, 101, 197, 75, 251, 102, 26]; @@ -122,7 +123,7 @@ impl ExecuteInstructionArgs { /// 2. `[]` destination_account /// 3. `[]` owner_delegate /// 4. `[optional]` extra_metas_account (default to PDA derived from 'extraMetasAccount') -/// 5. `[]` guard +/// 5. `[optional]` guard (default to PDA derived from 'guard') /// 6. `[optional]` instruction_sysvar_account (default to `Sysvar1nstructions1111111111111111111111111`) #[derive(Clone, Debug)] pub struct ExecuteBuilder { @@ -131,9 +132,10 @@ pub struct ExecuteBuilder { destination_account: solana_address::Address, owner_delegate: solana_address::Address, extra_metas_account: Option, - guard: solana_address::Address, + guard: Option, instruction_sysvar_account: Option, amount: u64, + guard_mint: Address, __remaining_accounts: Vec, } @@ -143,8 +145,8 @@ impl ExecuteBuilder { mint: solana_address::Address, destination_account: solana_address::Address, owner_delegate: solana_address::Address, - guard: solana_address::Address, amount: u64, + guard_mint: Address, ) -> Self { Self { source_account, @@ -152,9 +154,10 @@ impl ExecuteBuilder { destination_account, owner_delegate, extra_metas_account: None, - guard, + guard: None, instruction_sysvar_account: None, amount, + guard_mint, __remaining_accounts: Vec::new(), } } @@ -167,6 +170,12 @@ impl ExecuteBuilder { self.extra_metas_account = Some(extra_metas_account); self } + /// `[optional account, default to PDA derived from 'guard']` + #[inline(always)] + pub fn guard(&mut self, guard: solana_address::Address) -> &mut Self { + self.guard = Some(guard); + self + } /// `[optional account, default to 'Sysvar1nstructions1111111111111111111111111']` #[inline(always)] pub fn instruction_sysvar_account( @@ -200,7 +209,9 @@ impl ExecuteBuilder { let extra_metas_account = self .extra_metas_account .unwrap_or_else(|| crate::pdas::find_extra_metas_account_pda(&self.mint).0); - let guard = self.guard; + let guard = self + .guard + .unwrap_or_else(|| crate::pdas::find_guard_pda(&self.guard_mint.clone()).0); let instruction_sysvar_account = self.instruction_sysvar_account .unwrap_or(solana_address::address!( diff --git a/e2e/anchor/src/generated/instructions/initialize.rs b/e2e/anchor/src/generated/instructions/initialize.rs index 9527f44..c972c7c 100644 --- a/e2e/anchor/src/generated/instructions/initialize.rs +++ b/e2e/anchor/src/generated/instructions/initialize.rs @@ -7,6 +7,7 @@ use borsh::BorshDeserialize; use borsh::BorshSerialize; +use solana_address::Address; pub const INITIALIZE_DISCRIMINATOR: [u8; 8] = [43, 34, 13, 49, 167, 88, 235, 235]; @@ -95,7 +96,7 @@ impl Default for InitializeInstructionData { /// ### Accounts: /// /// 0. `[writable, optional]` extra_metas_account (default to PDA derived from 'extraMetasAccount') -/// 1. `[]` guard +/// 1. `[optional]` guard (default to PDA derived from 'guard') /// 2. `[]` mint /// 3. `[writable, signer]` transfer_hook_authority /// 4. `[optional]` system_program (default to `11111111111111111111111111111111`) @@ -103,28 +104,30 @@ impl Default for InitializeInstructionData { #[derive(Clone, Debug)] pub struct InitializeBuilder { extra_metas_account: Option, - guard: solana_address::Address, + guard: Option, mint: solana_address::Address, transfer_hook_authority: solana_address::Address, system_program: Option, payer: solana_address::Address, + guard_mint: Address, __remaining_accounts: Vec, } impl InitializeBuilder { pub fn new( - guard: solana_address::Address, mint: solana_address::Address, transfer_hook_authority: solana_address::Address, payer: solana_address::Address, + guard_mint: Address, ) -> Self { Self { extra_metas_account: None, - guard, + guard: None, mint, transfer_hook_authority, system_program: None, payer, + guard_mint, __remaining_accounts: Vec::new(), } } @@ -137,6 +140,12 @@ impl InitializeBuilder { self.extra_metas_account = Some(extra_metas_account); self } + /// `[optional account, default to PDA derived from 'guard']` + #[inline(always)] + pub fn guard(&mut self, guard: solana_address::Address) -> &mut Self { + self.guard = Some(guard); + self + } /// `[optional account, default to '11111111111111111111111111111111']` #[inline(always)] pub fn system_program(&mut self, system_program: solana_address::Address) -> &mut Self { @@ -160,11 +169,13 @@ impl InitializeBuilder { } #[allow(clippy::clone_on_copy)] pub fn instruction(&self) -> solana_instruction::Instruction { + let mint = self.mint; let extra_metas_account = self .extra_metas_account .unwrap_or_else(|| crate::pdas::find_extra_metas_account_pda(&self.mint).0); - let guard = self.guard; - let mint = self.mint; + let guard = self + .guard + .unwrap_or_else(|| crate::pdas::find_guard_pda(&self.guard_mint.clone()).0); let transfer_hook_authority = self.transfer_hook_authority; let system_program = self .system_program diff --git a/e2e/anchor/src/generated/instructions/update_guard.rs b/e2e/anchor/src/generated/instructions/update_guard.rs index 3d1b0fb..41d0f22 100644 --- a/e2e/anchor/src/generated/instructions/update_guard.rs +++ b/e2e/anchor/src/generated/instructions/update_guard.rs @@ -206,26 +206,25 @@ impl UpdateGuardBuilder { } #[allow(clippy::clone_on_copy)] pub fn instruction(&self) -> solana_instruction::Instruction { + let mint = self.mint; let guard = self .guard .unwrap_or_else(|| crate::pdas::find_guard_pda(&self.mint).0); - let mint = self.mint; + let guard_authority = self.guard_authority; let token_account = self.token_account.unwrap_or_else(|| { solana_address::Address::find_program_address( &[ self.guard_authority.as_ref(), - self.token_program - .unwrap_or(solana_address::address!( - "TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb" - )) - .as_ref(), + &[ + 6, 221, 246, 225, 238, 117, 143, 222, 24, 66, 93, 188, 228, 108, 205, 218, + 182, 26, 252, 77, 131, 185, 13, 39, 254, 189, 249, 40, 216, 161, 139, 252, + ], self.mint.as_ref(), ], &solana_address::address!("ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL"), ) .0 }); - let guard_authority = self.guard_authority; let token_program = self.token_program.unwrap_or(solana_address::address!( "TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb" )); diff --git a/e2e/anchor/src/lib.rs b/e2e/anchor/src/lib.rs index 9974b79..7020a76 100644 --- a/e2e/anchor/src/lib.rs +++ b/e2e/anchor/src/lib.rs @@ -2,3 +2,43 @@ mod generated; pub use generated::programs::WEN_TRANSFER_GUARD_ID as ID; pub use generated::*; + +#[cfg(test)] +mod tests { + use solana_address::Address; + + #[test] + fn execute_auto_derives_guard_from_guard_mint() { + let mint = Address::new_from_array([2u8; 32]); + let guard_mint = Address::new_from_array([7u8; 32]); + let ix = crate::instructions::ExecuteBuilder::new( + Address::new_from_array([1u8; 32]), // source_account + mint, // mint + Address::new_from_array([3u8; 32]), // destination_account + Address::new_from_array([4u8; 32]), // owner_delegate + 42, // amount + guard_mint, + ) + .instruction(); + + let expected = crate::pdas::find_guard_pda(&guard_mint).0; + assert_eq!(ix.accounts[5].pubkey, expected, "guard"); + // The seed must come from `guard_mint`, not the instruction's `mint` account. + assert_ne!(ix.accounts[5].pubkey, crate::pdas::find_guard_pda(&mint).0); + } + + #[test] + fn initialize_auto_derives_guard_from_guard_mint() { + let guard_mint = Address::new_from_array([9u8; 32]); + let ix = crate::instructions::InitializeBuilder::new( + Address::new_from_array([1u8; 32]), // mint + Address::new_from_array([2u8; 32]), // transfer_hook_authority + Address::new_from_array([3u8; 32]), // payer + guard_mint, + ) + .instruction(); + + let expected = crate::pdas::find_guard_pda(&guard_mint).0; + assert_eq!(ix.accounts[1].pubkey, expected, "guard"); + } +} diff --git a/e2e/governance/src/generated/instructions/create_token_owner_record.rs b/e2e/governance/src/generated/instructions/create_token_owner_record.rs index bc91af5..496aa3e 100644 --- a/e2e/governance/src/generated/instructions/create_token_owner_record.rs +++ b/e2e/governance/src/generated/instructions/create_token_owner_record.rs @@ -164,6 +164,7 @@ impl CreateTokenOwnerRecordBuilder { pub fn instruction(&self) -> solana_instruction::Instruction { let realm_account = self.realm_account; let governing_token_owner_account = self.governing_token_owner_account; + let governing_token_mint = self.governing_token_mint; let token_owner_record = self.token_owner_record.unwrap_or_else(|| { crate::pdas::find_token_owner_record_pda( &self.realm_account, @@ -172,7 +173,6 @@ impl CreateTokenOwnerRecordBuilder { ) .0 }); - let governing_token_mint = self.governing_token_mint; let payer = self.payer; let system_program = self .system_program diff --git a/e2e/raydium-launchpad/src/generated/instructions/claim_platform_fee.rs b/e2e/raydium-launchpad/src/generated/instructions/claim_platform_fee.rs index dd43592..cd51c1f 100644 --- a/e2e/raydium-launchpad/src/generated/instructions/claim_platform_fee.rs +++ b/e2e/raydium-launchpad/src/generated/instructions/claim_platform_fee.rs @@ -234,6 +234,7 @@ impl ClaimPlatformFeeBuilder { let pool_state = self.pool_state; let platform_config = self.platform_config; let quote_vault = self.quote_vault; + let quote_mint = self.quote_mint; let recipient_token_account = self.recipient_token_account.unwrap_or_else(|| { solana_address::Address::find_program_address( &[ @@ -249,7 +250,6 @@ impl ClaimPlatformFeeBuilder { ) .0 }); - let quote_mint = self.quote_mint; let token_program = self.token_program.unwrap_or(solana_address::address!( "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA" )); diff --git a/e2e/raydium-launchpad/src/generated/instructions/create_config.rs b/e2e/raydium-launchpad/src/generated/instructions/create_config.rs index bde328d..67804a2 100644 --- a/e2e/raydium-launchpad/src/generated/instructions/create_config.rs +++ b/e2e/raydium-launchpad/src/generated/instructions/create_config.rs @@ -232,6 +232,7 @@ impl CreateConfigBuilder { let owner = self.owner.unwrap_or(solana_address::address!( "GThUX1Atko4tqhN2NaiTazWSeFWMuiUvfFnyJyUghFMJ" )); + let quote_token_mint = self.quote_token_mint; let global_config = self.global_config.unwrap_or_else(|| { crate::pdas::find_global_config_pda( &self.quote_token_mint, @@ -240,7 +241,6 @@ impl CreateConfigBuilder { ) .0 }); - let quote_token_mint = self.quote_token_mint; let protocol_fee_owner = self.protocol_fee_owner; let migrate_fee_owner = self.migrate_fee_owner; let migrate_to_amm_wallet = self.migrate_to_amm_wallet; diff --git a/e2e/raydium-launchpad/src/generated/instructions/initialize.rs b/e2e/raydium-launchpad/src/generated/instructions/initialize.rs index faed751..7bf935a 100644 --- a/e2e/raydium-launchpad/src/generated/instructions/initialize.rs +++ b/e2e/raydium-launchpad/src/generated/instructions/initialize.rs @@ -374,11 +374,11 @@ impl InitializeBuilder { let global_config = self.global_config; let platform_config = self.platform_config; let authority = self.authority.unwrap_or(crate::pdas::AUTHORITY_ADDRESS); + let base_mint = self.base_mint; + let quote_mint = self.quote_mint; let pool_state = self.pool_state.unwrap_or_else(|| { crate::pdas::find_pool_state_pda(&self.base_mint, &self.quote_mint).0 }); - let base_mint = self.base_mint; - let quote_mint = self.quote_mint; let base_vault = self .base_vault .unwrap_or_else(|| crate::pdas::find_base_vault_pda(&pool_state, &self.base_mint).0); diff --git a/e2e/raydium-launchpad/src/generated/instructions/migrate_to_amm.rs b/e2e/raydium-launchpad/src/generated/instructions/migrate_to_amm.rs index 593a5cc..e19f5e6 100644 --- a/e2e/raydium-launchpad/src/generated/instructions/migrate_to_amm.rs +++ b/e2e/raydium-launchpad/src/generated/instructions/migrate_to_amm.rs @@ -532,63 +532,27 @@ impl MigrateToAmmBuilder { let amm_program = self.amm_program.unwrap_or(solana_address::address!( "675kPX9MHTjS2zt1qfr1NYHuzeLXfQM9H24wFSUt1Mp8" )); - let amm_pool = self.amm_pool.unwrap_or_else(|| { - crate::pdas::find_amm_pool_pda( - &self.amm_program.unwrap_or(solana_address::address!( - "675kPX9MHTjS2zt1qfr1NYHuzeLXfQM9H24wFSUt1Mp8" - )), - &self.market, - ) - .0 - }); + let amm_pool = self + .amm_pool + .unwrap_or_else(|| crate::pdas::find_amm_pool_pda(&self.market).0); let amm_authority = self .amm_authority .unwrap_or(crate::pdas::AMM_AUTHORITY_ADDRESS); - let amm_open_orders = self.amm_open_orders.unwrap_or_else(|| { - crate::pdas::find_amm_open_orders_pda( - &self.amm_program.unwrap_or(solana_address::address!( - "675kPX9MHTjS2zt1qfr1NYHuzeLXfQM9H24wFSUt1Mp8" - )), - &self.market, - ) - .0 - }); - let amm_lp_mint = self.amm_lp_mint.unwrap_or_else(|| { - crate::pdas::find_amm_lp_mint_pda( - &self.amm_program.unwrap_or(solana_address::address!( - "675kPX9MHTjS2zt1qfr1NYHuzeLXfQM9H24wFSUt1Mp8" - )), - &self.market, - ) - .0 - }); - let amm_base_vault = self.amm_base_vault.unwrap_or_else(|| { - crate::pdas::find_amm_base_vault_pda( - &self.amm_program.unwrap_or(solana_address::address!( - "675kPX9MHTjS2zt1qfr1NYHuzeLXfQM9H24wFSUt1Mp8" - )), - &self.market, - ) - .0 - }); - let amm_quote_vault = self.amm_quote_vault.unwrap_or_else(|| { - crate::pdas::find_amm_quote_vault_pda( - &self.amm_program.unwrap_or(solana_address::address!( - "675kPX9MHTjS2zt1qfr1NYHuzeLXfQM9H24wFSUt1Mp8" - )), - &self.market, - ) - .0 - }); - let amm_target_orders = self.amm_target_orders.unwrap_or_else(|| { - crate::pdas::find_amm_target_orders_pda( - &self.amm_program.unwrap_or(solana_address::address!( - "675kPX9MHTjS2zt1qfr1NYHuzeLXfQM9H24wFSUt1Mp8" - )), - &self.market, - ) - .0 - }); + let amm_open_orders = self + .amm_open_orders + .unwrap_or_else(|| crate::pdas::find_amm_open_orders_pda(&self.market).0); + let amm_lp_mint = self + .amm_lp_mint + .unwrap_or_else(|| crate::pdas::find_amm_lp_mint_pda(&self.market).0); + let amm_base_vault = self + .amm_base_vault + .unwrap_or_else(|| crate::pdas::find_amm_base_vault_pda(&self.market).0); + let amm_quote_vault = self + .amm_quote_vault + .unwrap_or_else(|| crate::pdas::find_amm_quote_vault_pda(&self.market).0); + let amm_target_orders = self + .amm_target_orders + .unwrap_or_else(|| crate::pdas::find_amm_target_orders_pda(&self.market).0); let amm_config = self.amm_config.unwrap_or(crate::pdas::AMM_CONFIG_ADDRESS); let amm_create_fee_destination = self.amm_create_fee_destination; let authority = self.authority.unwrap_or(crate::pdas::AUTHORITY_ADDRESS); diff --git a/e2e/raydium-launchpad/src/generated/pdas/amm_authority.rs b/e2e/raydium-launchpad/src/generated/pdas/amm_authority.rs index a4e2905..b20cb3c 100644 --- a/e2e/raydium-launchpad/src/generated/pdas/amm_authority.rs +++ b/e2e/raydium-launchpad/src/generated/pdas/amm_authority.rs @@ -5,21 +5,25 @@ //! //! -use crate::RAYDIUM_LAUNCHPAD_ID; - pub const AMM_AUTHORITY_SEED: &'static [u8] = &[97, 109, 109, 32, 97, 117, 116, 104, 111, 114, 105, 116, 121]; pub const AMM_AUTHORITY_ADDRESS: solana_address::Address = - solana_address::address!("8esABrhGmu9d63CV5Km5a2Sy9SHC2jJHwDB67zMhL9ki"); + solana_address::address!("5Q544fKrFoe6tsEbD7S8EmxGTJYAKtTVhAW5Q5pge4j1"); + +pub const AMM_AUTHORITY_PROGRAM_ADDRESS: solana_address::Address = + solana_address::address!("675kPX9MHTjS2zt1qfr1NYHuzeLXfQM9H24wFSUt1Mp8"); pub fn create_amm_authority_pda( bump: u8, ) -> Result { solana_address::Address::create_program_address( &[AMM_AUTHORITY_SEED, &[bump]], - &RAYDIUM_LAUNCHPAD_ID, + &AMM_AUTHORITY_PROGRAM_ADDRESS, ) } pub fn find_amm_authority_pda() -> (solana_address::Address, u8) { - solana_address::Address::find_program_address(&[AMM_AUTHORITY_SEED], &RAYDIUM_LAUNCHPAD_ID) + solana_address::Address::find_program_address( + &[AMM_AUTHORITY_SEED], + &AMM_AUTHORITY_PROGRAM_ADDRESS, + ) } diff --git a/e2e/raydium-launchpad/src/generated/pdas/amm_base_vault.rs b/e2e/raydium-launchpad/src/generated/pdas/amm_base_vault.rs index 72ae854..310f395 100644 --- a/e2e/raydium-launchpad/src/generated/pdas/amm_base_vault.rs +++ b/e2e/raydium-launchpad/src/generated/pdas/amm_base_vault.rs @@ -7,33 +7,38 @@ use solana_address::Address; -use crate::RAYDIUM_LAUNCHPAD_ID; - -pub const AMM_BASE_VAULT_SEED: &'static [u8] = &[ +pub const AMM_BASE_VAULT_SEED_0: &'static [u8] = &[ + 75, 217, 73, 196, 54, 2, 195, 63, 32, 119, 144, 237, 22, 163, 82, 76, 161, 185, 151, 92, 241, + 33, 162, 169, 12, 255, 236, 125, 248, 182, 138, 205, +]; +pub const AMM_BASE_VAULT_SEED_1: &'static [u8] = &[ 99, 111, 105, 110, 95, 118, 97, 117, 108, 116, 95, 97, 115, 115, 111, 99, 105, 97, 116, 101, 100, 95, 115, 101, 101, 100, ]; + +pub const AMM_BASE_VAULT_PROGRAM_ADDRESS: solana_address::Address = + solana_address::address!("675kPX9MHTjS2zt1qfr1NYHuzeLXfQM9H24wFSUt1Mp8"); pub fn create_amm_base_vault_pda( - amm_program: Address, market: Address, bump: u8, ) -> Result { solana_address::Address::create_program_address( &[ - amm_program.as_ref(), + AMM_BASE_VAULT_SEED_0, market.as_ref(), - AMM_BASE_VAULT_SEED, + AMM_BASE_VAULT_SEED_1, &[bump], ], - &RAYDIUM_LAUNCHPAD_ID, + &AMM_BASE_VAULT_PROGRAM_ADDRESS, ) } -pub fn find_amm_base_vault_pda( - amm_program: &Address, - market: &Address, -) -> (solana_address::Address, u8) { +pub fn find_amm_base_vault_pda(market: &Address) -> (solana_address::Address, u8) { solana_address::Address::find_program_address( - &[amm_program.as_ref(), market.as_ref(), AMM_BASE_VAULT_SEED], - &RAYDIUM_LAUNCHPAD_ID, + &[ + AMM_BASE_VAULT_SEED_0, + market.as_ref(), + AMM_BASE_VAULT_SEED_1, + ], + &AMM_BASE_VAULT_PROGRAM_ADDRESS, ) } diff --git a/e2e/raydium-launchpad/src/generated/pdas/amm_config.rs b/e2e/raydium-launchpad/src/generated/pdas/amm_config.rs index 7b45598..afbf832 100644 --- a/e2e/raydium-launchpad/src/generated/pdas/amm_config.rs +++ b/e2e/raydium-launchpad/src/generated/pdas/amm_config.rs @@ -5,23 +5,24 @@ //! //! -use crate::RAYDIUM_LAUNCHPAD_ID; - pub const AMM_CONFIG_SEED: &'static [u8] = &[ 97, 109, 109, 95, 99, 111, 110, 102, 105, 103, 95, 97, 99, 99, 111, 117, 110, 116, 95, 115, 101, 101, 100, ]; pub const AMM_CONFIG_ADDRESS: solana_address::Address = - solana_address::address!("NKeKVhNv6BayHHcFzpt8DTZ9vw8c3CuGcHDmULVoQr8"); + solana_address::address!("9DCxsMizn3H1hprZ7xWe6LDzeUeZBksYFpBWBtSf1PQX"); + +pub const AMM_CONFIG_PROGRAM_ADDRESS: solana_address::Address = + solana_address::address!("675kPX9MHTjS2zt1qfr1NYHuzeLXfQM9H24wFSUt1Mp8"); pub fn create_amm_config_pda( bump: u8, ) -> Result { solana_address::Address::create_program_address( &[AMM_CONFIG_SEED, &[bump]], - &RAYDIUM_LAUNCHPAD_ID, + &AMM_CONFIG_PROGRAM_ADDRESS, ) } pub fn find_amm_config_pda() -> (solana_address::Address, u8) { - solana_address::Address::find_program_address(&[AMM_CONFIG_SEED], &RAYDIUM_LAUNCHPAD_ID) + solana_address::Address::find_program_address(&[AMM_CONFIG_SEED], &AMM_CONFIG_PROGRAM_ADDRESS) } diff --git a/e2e/raydium-launchpad/src/generated/pdas/amm_lp_mint.rs b/e2e/raydium-launchpad/src/generated/pdas/amm_lp_mint.rs index c52daab..d1a039a 100644 --- a/e2e/raydium-launchpad/src/generated/pdas/amm_lp_mint.rs +++ b/e2e/raydium-launchpad/src/generated/pdas/amm_lp_mint.rs @@ -7,33 +7,34 @@ use solana_address::Address; -use crate::RAYDIUM_LAUNCHPAD_ID; - -pub const AMM_LP_MINT_SEED: &'static [u8] = &[ +pub const AMM_LP_MINT_SEED_0: &'static [u8] = &[ + 75, 217, 73, 196, 54, 2, 195, 63, 32, 119, 144, 237, 22, 163, 82, 76, 161, 185, 151, 92, 241, + 33, 162, 169, 12, 255, 236, 125, 248, 182, 138, 205, +]; +pub const AMM_LP_MINT_SEED_1: &'static [u8] = &[ 108, 112, 95, 109, 105, 110, 116, 95, 97, 115, 115, 111, 99, 105, 97, 116, 101, 100, 95, 115, 101, 101, 100, ]; + +pub const AMM_LP_MINT_PROGRAM_ADDRESS: solana_address::Address = + solana_address::address!("675kPX9MHTjS2zt1qfr1NYHuzeLXfQM9H24wFSUt1Mp8"); pub fn create_amm_lp_mint_pda( - amm_program: Address, market: Address, bump: u8, ) -> Result { solana_address::Address::create_program_address( &[ - amm_program.as_ref(), + AMM_LP_MINT_SEED_0, market.as_ref(), - AMM_LP_MINT_SEED, + AMM_LP_MINT_SEED_1, &[bump], ], - &RAYDIUM_LAUNCHPAD_ID, + &AMM_LP_MINT_PROGRAM_ADDRESS, ) } -pub fn find_amm_lp_mint_pda( - amm_program: &Address, - market: &Address, -) -> (solana_address::Address, u8) { +pub fn find_amm_lp_mint_pda(market: &Address) -> (solana_address::Address, u8) { solana_address::Address::find_program_address( - &[amm_program.as_ref(), market.as_ref(), AMM_LP_MINT_SEED], - &RAYDIUM_LAUNCHPAD_ID, + &[AMM_LP_MINT_SEED_0, market.as_ref(), AMM_LP_MINT_SEED_1], + &AMM_LP_MINT_PROGRAM_ADDRESS, ) } diff --git a/e2e/raydium-launchpad/src/generated/pdas/amm_open_orders.rs b/e2e/raydium-launchpad/src/generated/pdas/amm_open_orders.rs index 3fa37d3..22e4b86 100644 --- a/e2e/raydium-launchpad/src/generated/pdas/amm_open_orders.rs +++ b/e2e/raydium-launchpad/src/generated/pdas/amm_open_orders.rs @@ -7,33 +7,38 @@ use solana_address::Address; -use crate::RAYDIUM_LAUNCHPAD_ID; - -pub const AMM_OPEN_ORDERS_SEED: &'static [u8] = &[ +pub const AMM_OPEN_ORDERS_SEED_0: &'static [u8] = &[ + 75, 217, 73, 196, 54, 2, 195, 63, 32, 119, 144, 237, 22, 163, 82, 76, 161, 185, 151, 92, 241, + 33, 162, 169, 12, 255, 236, 125, 248, 182, 138, 205, +]; +pub const AMM_OPEN_ORDERS_SEED_1: &'static [u8] = &[ 111, 112, 101, 110, 95, 111, 114, 100, 101, 114, 95, 97, 115, 115, 111, 99, 105, 97, 116, 101, 100, 95, 115, 101, 101, 100, ]; + +pub const AMM_OPEN_ORDERS_PROGRAM_ADDRESS: solana_address::Address = + solana_address::address!("675kPX9MHTjS2zt1qfr1NYHuzeLXfQM9H24wFSUt1Mp8"); pub fn create_amm_open_orders_pda( - amm_program: Address, market: Address, bump: u8, ) -> Result { solana_address::Address::create_program_address( &[ - amm_program.as_ref(), + AMM_OPEN_ORDERS_SEED_0, market.as_ref(), - AMM_OPEN_ORDERS_SEED, + AMM_OPEN_ORDERS_SEED_1, &[bump], ], - &RAYDIUM_LAUNCHPAD_ID, + &AMM_OPEN_ORDERS_PROGRAM_ADDRESS, ) } -pub fn find_amm_open_orders_pda( - amm_program: &Address, - market: &Address, -) -> (solana_address::Address, u8) { +pub fn find_amm_open_orders_pda(market: &Address) -> (solana_address::Address, u8) { solana_address::Address::find_program_address( - &[amm_program.as_ref(), market.as_ref(), AMM_OPEN_ORDERS_SEED], - &RAYDIUM_LAUNCHPAD_ID, + &[ + AMM_OPEN_ORDERS_SEED_0, + market.as_ref(), + AMM_OPEN_ORDERS_SEED_1, + ], + &AMM_OPEN_ORDERS_PROGRAM_ADDRESS, ) } diff --git a/e2e/raydium-launchpad/src/generated/pdas/amm_pool.rs b/e2e/raydium-launchpad/src/generated/pdas/amm_pool.rs index 05cea0b..7e3dad7 100644 --- a/e2e/raydium-launchpad/src/generated/pdas/amm_pool.rs +++ b/e2e/raydium-launchpad/src/generated/pdas/amm_pool.rs @@ -7,29 +7,28 @@ use solana_address::Address; -use crate::RAYDIUM_LAUNCHPAD_ID; - -pub const AMM_POOL_SEED: &'static [u8] = &[ +pub const AMM_POOL_SEED_0: &'static [u8] = &[ + 75, 217, 73, 196, 54, 2, 195, 63, 32, 119, 144, 237, 22, 163, 82, 76, 161, 185, 151, 92, 241, + 33, 162, 169, 12, 255, 236, 125, 248, 182, 138, 205, +]; +pub const AMM_POOL_SEED_1: &'static [u8] = &[ 97, 109, 109, 95, 97, 115, 115, 111, 99, 105, 97, 116, 101, 100, 95, 115, 101, 101, 100, ]; + +pub const AMM_POOL_PROGRAM_ADDRESS: solana_address::Address = + solana_address::address!("675kPX9MHTjS2zt1qfr1NYHuzeLXfQM9H24wFSUt1Mp8"); pub fn create_amm_pool_pda( - amm_program: Address, market: Address, bump: u8, ) -> Result { solana_address::Address::create_program_address( - &[ - amm_program.as_ref(), - market.as_ref(), - AMM_POOL_SEED, - &[bump], - ], - &RAYDIUM_LAUNCHPAD_ID, + &[AMM_POOL_SEED_0, market.as_ref(), AMM_POOL_SEED_1, &[bump]], + &AMM_POOL_PROGRAM_ADDRESS, ) } -pub fn find_amm_pool_pda(amm_program: &Address, market: &Address) -> (solana_address::Address, u8) { +pub fn find_amm_pool_pda(market: &Address) -> (solana_address::Address, u8) { solana_address::Address::find_program_address( - &[amm_program.as_ref(), market.as_ref(), AMM_POOL_SEED], - &RAYDIUM_LAUNCHPAD_ID, + &[AMM_POOL_SEED_0, market.as_ref(), AMM_POOL_SEED_1], + &AMM_POOL_PROGRAM_ADDRESS, ) } diff --git a/e2e/raydium-launchpad/src/generated/pdas/amm_quote_vault.rs b/e2e/raydium-launchpad/src/generated/pdas/amm_quote_vault.rs index 765426c..d7e3e92 100644 --- a/e2e/raydium-launchpad/src/generated/pdas/amm_quote_vault.rs +++ b/e2e/raydium-launchpad/src/generated/pdas/amm_quote_vault.rs @@ -7,33 +7,38 @@ use solana_address::Address; -use crate::RAYDIUM_LAUNCHPAD_ID; - -pub const AMM_QUOTE_VAULT_SEED: &'static [u8] = &[ +pub const AMM_QUOTE_VAULT_SEED_0: &'static [u8] = &[ + 75, 217, 73, 196, 54, 2, 195, 63, 32, 119, 144, 237, 22, 163, 82, 76, 161, 185, 151, 92, 241, + 33, 162, 169, 12, 255, 236, 125, 248, 182, 138, 205, +]; +pub const AMM_QUOTE_VAULT_SEED_1: &'static [u8] = &[ 112, 99, 95, 118, 97, 117, 108, 116, 95, 97, 115, 115, 111, 99, 105, 97, 116, 101, 100, 95, 115, 101, 101, 100, ]; + +pub const AMM_QUOTE_VAULT_PROGRAM_ADDRESS: solana_address::Address = + solana_address::address!("675kPX9MHTjS2zt1qfr1NYHuzeLXfQM9H24wFSUt1Mp8"); pub fn create_amm_quote_vault_pda( - amm_program: Address, market: Address, bump: u8, ) -> Result { solana_address::Address::create_program_address( &[ - amm_program.as_ref(), + AMM_QUOTE_VAULT_SEED_0, market.as_ref(), - AMM_QUOTE_VAULT_SEED, + AMM_QUOTE_VAULT_SEED_1, &[bump], ], - &RAYDIUM_LAUNCHPAD_ID, + &AMM_QUOTE_VAULT_PROGRAM_ADDRESS, ) } -pub fn find_amm_quote_vault_pda( - amm_program: &Address, - market: &Address, -) -> (solana_address::Address, u8) { +pub fn find_amm_quote_vault_pda(market: &Address) -> (solana_address::Address, u8) { solana_address::Address::find_program_address( - &[amm_program.as_ref(), market.as_ref(), AMM_QUOTE_VAULT_SEED], - &RAYDIUM_LAUNCHPAD_ID, + &[ + AMM_QUOTE_VAULT_SEED_0, + market.as_ref(), + AMM_QUOTE_VAULT_SEED_1, + ], + &AMM_QUOTE_VAULT_PROGRAM_ADDRESS, ) } diff --git a/e2e/raydium-launchpad/src/generated/pdas/amm_target_orders.rs b/e2e/raydium-launchpad/src/generated/pdas/amm_target_orders.rs index 3ab85e7..951b70b 100644 --- a/e2e/raydium-launchpad/src/generated/pdas/amm_target_orders.rs +++ b/e2e/raydium-launchpad/src/generated/pdas/amm_target_orders.rs @@ -7,37 +7,38 @@ use solana_address::Address; -use crate::RAYDIUM_LAUNCHPAD_ID; - -pub const AMM_TARGET_ORDERS_SEED: &'static [u8] = &[ +pub const AMM_TARGET_ORDERS_SEED_0: &'static [u8] = &[ + 75, 217, 73, 196, 54, 2, 195, 63, 32, 119, 144, 237, 22, 163, 82, 76, 161, 185, 151, 92, 241, + 33, 162, 169, 12, 255, 236, 125, 248, 182, 138, 205, +]; +pub const AMM_TARGET_ORDERS_SEED_1: &'static [u8] = &[ 116, 97, 114, 103, 101, 116, 95, 97, 115, 115, 111, 99, 105, 97, 116, 101, 100, 95, 115, 101, 101, 100, ]; + +pub const AMM_TARGET_ORDERS_PROGRAM_ADDRESS: solana_address::Address = + solana_address::address!("675kPX9MHTjS2zt1qfr1NYHuzeLXfQM9H24wFSUt1Mp8"); pub fn create_amm_target_orders_pda( - amm_program: Address, market: Address, bump: u8, ) -> Result { solana_address::Address::create_program_address( &[ - amm_program.as_ref(), + AMM_TARGET_ORDERS_SEED_0, market.as_ref(), - AMM_TARGET_ORDERS_SEED, + AMM_TARGET_ORDERS_SEED_1, &[bump], ], - &RAYDIUM_LAUNCHPAD_ID, + &AMM_TARGET_ORDERS_PROGRAM_ADDRESS, ) } -pub fn find_amm_target_orders_pda( - amm_program: &Address, - market: &Address, -) -> (solana_address::Address, u8) { +pub fn find_amm_target_orders_pda(market: &Address) -> (solana_address::Address, u8) { solana_address::Address::find_program_address( &[ - amm_program.as_ref(), + AMM_TARGET_ORDERS_SEED_0, market.as_ref(), - AMM_TARGET_ORDERS_SEED, + AMM_TARGET_ORDERS_SEED_1, ], - &RAYDIUM_LAUNCHPAD_ID, + &AMM_TARGET_ORDERS_PROGRAM_ADDRESS, ) } diff --git a/e2e/raydium-launchpad/src/generated/pdas/cpswap_authority.rs b/e2e/raydium-launchpad/src/generated/pdas/cpswap_authority.rs index 891cfb5..f069ea6 100644 --- a/e2e/raydium-launchpad/src/generated/pdas/cpswap_authority.rs +++ b/e2e/raydium-launchpad/src/generated/pdas/cpswap_authority.rs @@ -5,23 +5,27 @@ //! //! -use crate::RAYDIUM_LAUNCHPAD_ID; - pub const CPSWAP_AUTHORITY_SEED: &'static [u8] = &[ 118, 97, 117, 108, 116, 95, 97, 110, 100, 95, 108, 112, 95, 109, 105, 110, 116, 95, 97, 117, 116, 104, 95, 115, 101, 101, 100, ]; pub const CPSWAP_AUTHORITY_ADDRESS: solana_address::Address = - solana_address::address!("GE8yD1URMMFUh4LBN9kHw1iTPvmPZdCnExEY1kVa4P1C"); + solana_address::address!("GpMZbSM2GgvTKHJirzeGfMFoaZ8UR2X7F4v8vHTvxFbL"); + +pub const CPSWAP_AUTHORITY_PROGRAM_ADDRESS: solana_address::Address = + solana_address::address!("CPMMoo8L3F4NbTegBCKVNunggL7H1ZpdTHKxQB5qKP1C"); pub fn create_cpswap_authority_pda( bump: u8, ) -> Result { solana_address::Address::create_program_address( &[CPSWAP_AUTHORITY_SEED, &[bump]], - &RAYDIUM_LAUNCHPAD_ID, + &CPSWAP_AUTHORITY_PROGRAM_ADDRESS, ) } pub fn find_cpswap_authority_pda() -> (solana_address::Address, u8) { - solana_address::Address::find_program_address(&[CPSWAP_AUTHORITY_SEED], &RAYDIUM_LAUNCHPAD_ID) + solana_address::Address::find_program_address( + &[CPSWAP_AUTHORITY_SEED], + &CPSWAP_AUTHORITY_PROGRAM_ADDRESS, + ) } diff --git a/e2e/raydium-launchpad/src/generated/pdas/cpswap_base_vault.rs b/e2e/raydium-launchpad/src/generated/pdas/cpswap_base_vault.rs index aab8e4f..b2fef25 100644 --- a/e2e/raydium-launchpad/src/generated/pdas/cpswap_base_vault.rs +++ b/e2e/raydium-launchpad/src/generated/pdas/cpswap_base_vault.rs @@ -7,9 +7,10 @@ use solana_address::Address; -use crate::RAYDIUM_LAUNCHPAD_ID; - pub const CPSWAP_BASE_VAULT_SEED: &'static [u8] = &[112, 111, 111, 108, 95, 118, 97, 117, 108, 116]; + +pub const CPSWAP_BASE_VAULT_PROGRAM_ADDRESS: solana_address::Address = + solana_address::address!("CPMMoo8L3F4NbTegBCKVNunggL7H1ZpdTHKxQB5qKP1C"); pub fn create_cpswap_base_vault_pda( cpswap_pool: Address, base_mint: Address, @@ -22,7 +23,7 @@ pub fn create_cpswap_base_vault_pda( base_mint.as_ref(), &[bump], ], - &RAYDIUM_LAUNCHPAD_ID, + &CPSWAP_BASE_VAULT_PROGRAM_ADDRESS, ) } pub fn find_cpswap_base_vault_pda( @@ -35,6 +36,6 @@ pub fn find_cpswap_base_vault_pda( cpswap_pool.as_ref(), base_mint.as_ref(), ], - &RAYDIUM_LAUNCHPAD_ID, + &CPSWAP_BASE_VAULT_PROGRAM_ADDRESS, ) } diff --git a/e2e/raydium-launchpad/src/generated/pdas/cpswap_lp_mint.rs b/e2e/raydium-launchpad/src/generated/pdas/cpswap_lp_mint.rs index 664ed11..d95a256 100644 --- a/e2e/raydium-launchpad/src/generated/pdas/cpswap_lp_mint.rs +++ b/e2e/raydium-launchpad/src/generated/pdas/cpswap_lp_mint.rs @@ -7,22 +7,23 @@ use solana_address::Address; -use crate::RAYDIUM_LAUNCHPAD_ID; - pub const CPSWAP_LP_MINT_SEED: &'static [u8] = &[112, 111, 111, 108, 95, 108, 112, 95, 109, 105, 110, 116]; + +pub const CPSWAP_LP_MINT_PROGRAM_ADDRESS: solana_address::Address = + solana_address::address!("CPMMoo8L3F4NbTegBCKVNunggL7H1ZpdTHKxQB5qKP1C"); pub fn create_cpswap_lp_mint_pda( cpswap_pool: Address, bump: u8, ) -> Result { solana_address::Address::create_program_address( &[CPSWAP_LP_MINT_SEED, cpswap_pool.as_ref(), &[bump]], - &RAYDIUM_LAUNCHPAD_ID, + &CPSWAP_LP_MINT_PROGRAM_ADDRESS, ) } pub fn find_cpswap_lp_mint_pda(cpswap_pool: &Address) -> (solana_address::Address, u8) { solana_address::Address::find_program_address( &[CPSWAP_LP_MINT_SEED, cpswap_pool.as_ref()], - &RAYDIUM_LAUNCHPAD_ID, + &CPSWAP_LP_MINT_PROGRAM_ADDRESS, ) } diff --git a/e2e/raydium-launchpad/src/generated/pdas/cpswap_observation.rs b/e2e/raydium-launchpad/src/generated/pdas/cpswap_observation.rs index a129030..5393446 100644 --- a/e2e/raydium-launchpad/src/generated/pdas/cpswap_observation.rs +++ b/e2e/raydium-launchpad/src/generated/pdas/cpswap_observation.rs @@ -7,22 +7,23 @@ use solana_address::Address; -use crate::RAYDIUM_LAUNCHPAD_ID; - pub const CPSWAP_OBSERVATION_SEED: &'static [u8] = &[111, 98, 115, 101, 114, 118, 97, 116, 105, 111, 110]; + +pub const CPSWAP_OBSERVATION_PROGRAM_ADDRESS: solana_address::Address = + solana_address::address!("CPMMoo8L3F4NbTegBCKVNunggL7H1ZpdTHKxQB5qKP1C"); pub fn create_cpswap_observation_pda( cpswap_pool: Address, bump: u8, ) -> Result { solana_address::Address::create_program_address( &[CPSWAP_OBSERVATION_SEED, cpswap_pool.as_ref(), &[bump]], - &RAYDIUM_LAUNCHPAD_ID, + &CPSWAP_OBSERVATION_PROGRAM_ADDRESS, ) } pub fn find_cpswap_observation_pda(cpswap_pool: &Address) -> (solana_address::Address, u8) { solana_address::Address::find_program_address( &[CPSWAP_OBSERVATION_SEED, cpswap_pool.as_ref()], - &RAYDIUM_LAUNCHPAD_ID, + &CPSWAP_OBSERVATION_PROGRAM_ADDRESS, ) } diff --git a/e2e/raydium-launchpad/src/generated/pdas/cpswap_quote_vault.rs b/e2e/raydium-launchpad/src/generated/pdas/cpswap_quote_vault.rs index 23c80fc..d6977d1 100644 --- a/e2e/raydium-launchpad/src/generated/pdas/cpswap_quote_vault.rs +++ b/e2e/raydium-launchpad/src/generated/pdas/cpswap_quote_vault.rs @@ -7,10 +7,11 @@ use solana_address::Address; -use crate::RAYDIUM_LAUNCHPAD_ID; - pub const CPSWAP_QUOTE_VAULT_SEED: &'static [u8] = &[112, 111, 111, 108, 95, 118, 97, 117, 108, 116]; + +pub const CPSWAP_QUOTE_VAULT_PROGRAM_ADDRESS: solana_address::Address = + solana_address::address!("CPMMoo8L3F4NbTegBCKVNunggL7H1ZpdTHKxQB5qKP1C"); pub fn create_cpswap_quote_vault_pda( cpswap_pool: Address, quote_mint: Address, @@ -23,7 +24,7 @@ pub fn create_cpswap_quote_vault_pda( quote_mint.as_ref(), &[bump], ], - &RAYDIUM_LAUNCHPAD_ID, + &CPSWAP_QUOTE_VAULT_PROGRAM_ADDRESS, ) } pub fn find_cpswap_quote_vault_pda( @@ -36,6 +37,6 @@ pub fn find_cpswap_quote_vault_pda( cpswap_pool.as_ref(), quote_mint.as_ref(), ], - &RAYDIUM_LAUNCHPAD_ID, + &CPSWAP_QUOTE_VAULT_PROGRAM_ADDRESS, ) } diff --git a/e2e/raydium-launchpad/src/generated/pdas/lock_authority.rs b/e2e/raydium-launchpad/src/generated/pdas/lock_authority.rs index 002197e..9800531 100644 --- a/e2e/raydium-launchpad/src/generated/pdas/lock_authority.rs +++ b/e2e/raydium-launchpad/src/generated/pdas/lock_authority.rs @@ -5,23 +5,27 @@ //! //! -use crate::RAYDIUM_LAUNCHPAD_ID; - pub const LOCK_AUTHORITY_SEED: &'static [u8] = &[ 108, 111, 99, 107, 95, 99, 112, 95, 97, 117, 116, 104, 111, 114, 105, 116, 121, 95, 115, 101, 101, 100, ]; pub const LOCK_AUTHORITY_ADDRESS: solana_address::Address = - solana_address::address!("J119hBxyfY1jnqgajS5p3GLXm7mG9KP5r7P9bmrKk9SE"); + solana_address::address!("3f7GcQFG397GAaEnv51zR6tsTVihYRydnydDD1cXekxH"); + +pub const LOCK_AUTHORITY_PROGRAM_ADDRESS: solana_address::Address = + solana_address::address!("LockrWmn6K5twhz3y9w1dQERbmgSaRkfnTeTKbpofwE"); pub fn create_lock_authority_pda( bump: u8, ) -> Result { solana_address::Address::create_program_address( &[LOCK_AUTHORITY_SEED, &[bump]], - &RAYDIUM_LAUNCHPAD_ID, + &LOCK_AUTHORITY_PROGRAM_ADDRESS, ) } pub fn find_lock_authority_pda() -> (solana_address::Address, u8) { - solana_address::Address::find_program_address(&[LOCK_AUTHORITY_SEED], &RAYDIUM_LAUNCHPAD_ID) + solana_address::Address::find_program_address( + &[LOCK_AUTHORITY_SEED], + &LOCK_AUTHORITY_PROGRAM_ADDRESS, + ) } diff --git a/e2e/raydium-launchpad/src/lib.rs b/e2e/raydium-launchpad/src/lib.rs index 847ba65..6040d68 100644 --- a/e2e/raydium-launchpad/src/lib.rs +++ b/e2e/raydium-launchpad/src/lib.rs @@ -2,3 +2,105 @@ mod generated; pub use generated::programs::RAYDIUM_LAUNCHPAD_ID as ID; pub use generated::*; + +#[cfg(test)] +mod tests { + use solana_address::{address, Address}; + + fn filler(byte: u8) -> Address { + Address::new_from_array([byte; 32]) + } + + /// PDAs with a dynamic `programId` (a runtime account reference) must derive + /// under that program, not the local launchpad program. Expected addresses are + /// computed independently with codama's `dynamic-address-resolution` package + /// (the runtime source of truth), using + /// `market = So11111111111111111111111111111111111111112` and the default + /// (canonical) amm program `675kPX9MHTjS2zt1qfr1NYHuzeLXfQM9H24wFSUt1Mp8`. + #[test] + fn migrate_to_amm_derives_pdas_under_dynamic_amm_program() { + let market = address!("So11111111111111111111111111111111111111112"); + let ix = crate::instructions::MigrateToAmmBuilder::new( + filler(1), // payer + filler(2), // base_mint + filler(3), // quote_mint + market, // market + filler(5), // request_queue + filler(6), // event_queue + filler(7), // bids + filler(8), // asks + filler(9), // market_vault_signer + filler(10), // market_base_vault + filler(11), // market_quote_vault + filler(12), // amm_create_fee_destination + filler(13), // global_config + filler(14), // base_vault + filler(15), // quote_vault + filler(16), // pool_lp_token + 1, // base_lot_size + 1, // quote_lot_size + 0, // market_vault_signer_nonce + ) + .instruction(); + + assert_eq!( + ix.accounts[13].pubkey, + address!("2ooeaoRtTBK2EgKFLUKeZVz7SJZo3etuVhHagwPxBegj"), + "amm_pool" + ); + assert_eq!( + ix.accounts[14].pubkey, + address!("5Q544fKrFoe6tsEbD7S8EmxGTJYAKtTVhAW5Q5pge4j1"), + "amm_authority" + ); + assert_eq!( + ix.accounts[15].pubkey, + address!("HUGGGKtDNCKVTWPRVcTXyEJxNchMhhyZjhvUpfqPbka"), + "amm_open_orders" + ); + assert_eq!( + ix.accounts[20].pubkey, + address!("9DCxsMizn3H1hprZ7xWe6LDzeUeZBksYFpBWBtSf1PQX"), + "amm_config" + ); + } + + /// Same as above for the cpswap/lock programs, with + /// `cpswap_pool = base_mint = quote_mint = So11111111111111111111111111111111111111112` + /// and the default cpswap/lock programs. + #[test] + fn migrate_to_cpswap_derives_pdas_under_dynamic_programs() { + let shared = address!("So11111111111111111111111111111111111111112"); + let ix = crate::instructions::MigrateToCpswapBuilder::new( + filler(1), // payer + shared, // base_mint + shared, // quote_mint + filler(4), // platform_config + shared, // cpswap_pool + filler(6), // cpswap_config + filler(7), // cpswap_create_pool_fee + filler(8), // lock_lp_vault + filler(9), // global_config + filler(10), // base_vault + filler(11), // quote_vault + filler(12), // pool_lp_token + ) + .instruction(); + + assert_eq!( + ix.accounts[6].pubkey, + address!("GpMZbSM2GgvTKHJirzeGfMFoaZ8UR2X7F4v8vHTvxFbL"), + "cpswap_authority" + ); + assert_eq!( + ix.accounts[7].pubkey, + address!("CnXtmAN29yi5xNoc47HhtfEER7Ei3F3BBDM9KL6jen6d"), + "cpswap_lp_mint" + ); + assert_eq!( + ix.accounts[14].pubkey, + address!("3f7GcQFG397GAaEnv51zR6tsTVihYRydnydDD1cXekxH"), + "lock_authority" + ); + } +} diff --git a/public/templates/instructionsPageBuilder.njk b/public/templates/instructionsPageBuilder.njk index 46fe008..835fb27 100644 --- a/public/templates/instructionsPageBuilder.njk +++ b/public/templates/instructionsPageBuilder.njk @@ -44,6 +44,9 @@ pub struct {{ instruction.name | pascalCase }}Builder { {% endif %} {% endif %} {% endfor %} + {% for arg in extraArgs %} + {{ arg.name | snakeCase }}: {{ arg.type }}, + {% endfor %} __remaining_accounts: Vec, } @@ -61,6 +64,9 @@ impl {{ instruction.name | pascalCase }}Builder { {{ arg.name | snakeCase }}: {{ arg.type }}, {% endif %} {% endfor %} + {% for arg in extraArgs %} + {{ arg.name | snakeCase }}: {{ arg.type }}, + {% endfor %} ) -> Self { Self { {% for account in instruction.accounts %} @@ -80,6 +86,9 @@ impl {{ instruction.name | pascalCase }}Builder { {% endif %} {% endif %} {% endfor %} + {% for arg in extraArgs %} + {{ arg.name | snakeCase }}, + {% endfor %} __remaining_accounts: Vec::new(), } } @@ -149,7 +158,7 @@ impl {{ instruction.name | pascalCase }}Builder { pub fn instruction(&self) -> solana_instruction::Instruction { {% for account in resolvedAccounts %} {% if account.pdaDefault %} - {% if account.pdaDefault.isLinked and not account.pdaDefault.hasVariableSeeds %} + {% if account.pdaDefault.isLinked and not account.pdaDefault.hasVariableSeeds and not account.pdaDefault.hasDynamicProgram %} {% if account.isSigner === 'either' %} let {{ account.name | snakeCase }} = self.{{ account.name | snakeCase }}.map(|(k, _)| k).unwrap_or( {% else %} @@ -168,6 +177,9 @@ impl {{ instruction.name | pascalCase }}Builder { {% for seed in account.pdaDefault.renderedSeeds %} {{ seed.render }}, {% endfor %} + {% if account.pdaDefault.hasDynamicProgram %} + &{{ account.pdaDefault.programAddressExpr }}, + {% endif %} ).0 {% else %} solana_address::Address::find_program_address( diff --git a/public/templates/pdasPage.njk b/public/templates/pdasPage.njk index e385634..5cf8278 100644 --- a/public/templates/pdasPage.njk +++ b/public/templates/pdasPage.njk @@ -5,7 +5,7 @@ {{ imports }} -{% if program %} +{% if program and not dynamicProgramOnly %} use crate::{{ program.name | snakeCase | upper }}_ID; {% endif %} @@ -22,7 +22,82 @@ pub const {{ pda.name | snakeCase | upper }}_SEED{% if constantSeeds.length > 1 pub const {{ pda.name | snakeCase | upper }}_ADDRESS: solana_address::Address = solana_address::address!("{{ precomputedAddress }}"); {% endif %} +{% if dynamicProgramOnly and canonicalProgramAddress %} +{# The IDL pins the owning program's address (Anchor address constraint), so bake it in. #} +pub const {{ pda.name | snakeCase | upper }}_PROGRAM_ADDRESS: solana_address::Address = + solana_address::address!("{{ canonicalProgramAddress }}"); + +{{- macros.docblock(pda.docs) -}} +pub fn create_{{ pda.name | snakeCase }}_pda( + {% if hasVariableSeeds %} + {% for seed in seeds %} + {% if seed.kind === 'variablePdaSeedNode' %} + {{ seed.name | snakeCase }}: {{ seed.typeManifest.type }}, + {% endif %} + {% endfor %} + {% endif %} + bump: u8, +) -> Result { + solana_address::Address::create_program_address( + &[ + {% set constantUsageIndexP = 0 %} + {% for seed in seeds %} + {% if seed.kind === 'constantPdaSeedNode' and seed.value.kind === 'programIdValueNode' %} + {{ pda.name | snakeCase | upper }}_PROGRAM_ADDRESS.as_ref(), + {% elif seed.kind === 'constantPdaSeedNode' %} + {{ pda.name | snakeCase | upper }}_SEED{% if constantSeeds.length > 1 %}_{{ constantUsageIndexP }}{% endif %}, + {% set constantUsageIndexP = constantUsageIndexP + 1 %} + {% elif seed.kind == 'variablePdaSeedNode' and seed.resolvedType.kind == 'publicKeyTypeNode' %} + {{ seed.name | snakeCase }}.as_ref(), + {% elif seed.kind == 'variablePdaSeedNode' and seed.resolvedType.kind == 'bytesTypeNode' %} + &{{ seed.name | snakeCase }}, + {% else %} + {{ seed.name | snakeCase }}.to_string().as_ref(), + {% endif %} + {% endfor %} + &[bump], + ], + &{{ pda.name | snakeCase | upper }}_PROGRAM_ADDRESS, + ) +} + +{{- macros.docblock(pda.docs) -}} +pub fn find_{{ pda.name | snakeCase }}_pda( +{% if hasVariableSeeds %} + {% for seed in seeds %} + {% if seed.kind == 'variablePdaSeedNode' and seed.resolvedType.kind == 'publicKeyTypeNode' %} + {{ seed.name | snakeCase }}: &{{ seed.typeManifest.type }}, + {% elif seed.kind === 'variablePdaSeedNode' %} + {{ seed.name | snakeCase }}: {{ seed.typeManifest.type }}, + {% endif %} + {% endfor %} +{% endif %} +) -> (solana_address::Address, u8) { + solana_address::Address::find_program_address( + &[ + {% set constantUsageIndexP2 = 0 %} + {% for seed in seeds %} + {% if seed.kind === 'constantPdaSeedNode' and seed.value.kind === 'programIdValueNode' %} + {{ pda.name | snakeCase | upper }}_PROGRAM_ADDRESS.as_ref(), + {% elif seed.kind === 'constantPdaSeedNode' %} + {{ pda.name | snakeCase | upper }}_SEED{% if constantSeeds.length > 1 %}_{{ constantUsageIndexP2 }}{% endif %}, + {% set constantUsageIndexP2 = constantUsageIndexP2 + 1 %} + {% elif seed.kind == 'variablePdaSeedNode' and seed.resolvedType.kind == 'publicKeyTypeNode' %} + {{ seed.name | snakeCase }}.as_ref(), + {% elif seed.kind == 'variablePdaSeedNode' and seed.resolvedType.kind == 'bytesTypeNode' %} + &{{ seed.name | snakeCase }}, + {% else %} + {{ seed.name | snakeCase }}.to_string().as_ref(), + {% endif %} + {% endfor %} + ], + &{{ pda.name | snakeCase | upper }}_PROGRAM_ADDRESS, + ) +} +{% elif dynamicProgramOnly %} + +{# The deriving program is unpinned and only known at runtime, so callers pass it in. #} {{- macros.docblock(pda.docs) -}} pub fn create_{{ pda.name | snakeCase }}_pda( {% if hasVariableSeeds %} @@ -33,18 +108,89 @@ pub fn create_{{ pda.name | snakeCase }}_pda( {% endfor %} {% endif %} bump: u8, + program_address: &solana_address::Address, ) -> Result { solana_address::Address::create_program_address( &[ {% set constantUsageIndex = 0 %} + {% for seed in seeds %} + {% if seed.kind === 'constantPdaSeedNode' and seed.value.kind === 'programIdValueNode' %} + program_address.as_ref(), + {% elif seed.kind === 'constantPdaSeedNode' %} + {{ pda.name | snakeCase | upper }}_SEED{% if constantSeeds.length > 1 %}_{{ constantUsageIndex }}{% endif %}, + {% set constantUsageIndex = constantUsageIndex + 1 %} + {% elif seed.kind == 'variablePdaSeedNode' and seed.resolvedType.kind == 'publicKeyTypeNode' %} + {{ seed.name | snakeCase }}.as_ref(), + {% elif seed.kind == 'variablePdaSeedNode' and seed.resolvedType.kind == 'bytesTypeNode' %} + &{{ seed.name | snakeCase }}, + {% else %} + {{ seed.name | snakeCase }}.to_string().as_ref(), + {% endif %} + {% endfor %} + &[bump], + ], + program_address, + ) +} + +{{- macros.docblock(pda.docs) -}} +pub fn find_{{ pda.name | snakeCase }}_pda( +{% if hasVariableSeeds %} + {% for seed in seeds %} + {% if seed.kind == 'variablePdaSeedNode' and seed.resolvedType.kind == 'publicKeyTypeNode' %} + {{ seed.name | snakeCase }}: &{{ seed.typeManifest.type }}, + {% elif seed.kind === 'variablePdaSeedNode' %} + {{ seed.name | snakeCase }}: {{ seed.typeManifest.type }}, + {% endif %} + {% endfor %} +{% endif %} + program_address: &solana_address::Address, +) -> (solana_address::Address, u8) { + solana_address::Address::find_program_address( + &[ + {% set constantUsageIndex2 = 0 %} + {% for seed in seeds %} + {% if seed.kind === 'constantPdaSeedNode' and seed.value.kind === 'programIdValueNode' %} + program_address.as_ref(), + {% elif seed.kind === 'constantPdaSeedNode' %} + {{ pda.name | snakeCase | upper }}_SEED{% if constantSeeds.length > 1 %}_{{ constantUsageIndex2 }}{% endif %}, + {% set constantUsageIndex2 = constantUsageIndex2 + 1 %} + {% elif seed.kind == 'variablePdaSeedNode' and seed.resolvedType.kind == 'publicKeyTypeNode' %} + {{ seed.name | snakeCase }}.as_ref(), + {% elif seed.kind == 'variablePdaSeedNode' and seed.resolvedType.kind == 'bytesTypeNode' %} + &{{ seed.name | snakeCase }}, + {% else %} + {{ seed.name | snakeCase }}.to_string().as_ref(), + {% endif %} + {% endfor %} + ], + program_address, + ) +} +{% else %} + +{{- macros.docblock(pda.docs) -}} +pub fn create_{{ pda.name | snakeCase }}_pda( + {% if hasVariableSeeds %} + {% for seed in seeds %} + {% if seed.kind === 'variablePdaSeedNode' %} + {{ seed.name | snakeCase }}: {{ seed.typeManifest.type }}, + {% endif %} + {% endfor %} + {% endif %} + bump: u8, +) -> Result { + solana_address::Address::create_program_address( + &[ + {% set constantUsageIndex3 = 0 %} {% for seed in seeds %} {% if seed.kind === 'constantPdaSeedNode' and seed.value.kind === 'programIdValueNode' %} {% if program %} crate::{{ program.name | snakeCase | upper }}_ID.as_ref(), {% endif %} {% elif seed.kind === 'constantPdaSeedNode' %} - {{ pda.name | snakeCase | upper }}_SEED{% if constantSeeds.length > 1 %}_{{ constantUsageIndex }}{% endif %}, - {% set constantUsageIndex = constantUsageIndex + 1 %} + {{ pda.name | snakeCase | upper }}_SEED{% if constantSeeds.length > 1 %}_{{ constantUsageIndex3 }}{% endif %}, + {% set constantUsageIndex3 = constantUsageIndex3 + 1 %} {% elif seed.kind == 'variablePdaSeedNode' and seed.resolvedType.kind == 'publicKeyTypeNode' %} {{ seed.name | snakeCase }}.as_ref(), {% elif seed.kind == 'variablePdaSeedNode' and seed.resolvedType.kind == 'bytesTypeNode' %} @@ -77,15 +223,15 @@ pub fn find_{{ pda.name | snakeCase }}_pda( ) -> (solana_address::Address, u8) { solana_address::Address::find_program_address( &[ - {% set constantUsageIndex2 = 0 %} + {% set constantUsageIndex4 = 0 %} {% for seed in seeds %} {% if seed.kind === 'constantPdaSeedNode' and seed.value.kind === 'programIdValueNode' %} {% if program %} crate::{{ program.name | snakeCase | upper }}_ID.as_ref(), {% endif %} {% elif seed.kind === 'constantPdaSeedNode' %} - {{ pda.name | snakeCase | upper }}_SEED{% if constantSeeds.length > 1 %}_{{ constantUsageIndex2 }}{% endif %}, - {% set constantUsageIndex2 = constantUsageIndex2 + 1 %} + {{ pda.name | snakeCase | upper }}_SEED{% if constantSeeds.length > 1 %}_{{ constantUsageIndex4 }}{% endif %}, + {% set constantUsageIndex4 = constantUsageIndex4 + 1 %} {% elif seed.kind == 'variablePdaSeedNode' and seed.resolvedType.kind == 'publicKeyTypeNode' %} {{ seed.name | snakeCase }}.as_ref(), {% elif seed.kind == 'variablePdaSeedNode' and seed.resolvedType.kind == 'bytesTypeNode' %} @@ -102,5 +248,6 @@ pub fn find_{{ pda.name | snakeCase }}_pda( {% endif %} ) } +{% endif %} {% endblock %} diff --git a/src/getRenderMapVisitor.ts b/src/getRenderMapVisitor.ts index 8ce41bc..2a52f88 100644 --- a/src/getRenderMapVisitor.ts +++ b/src/getRenderMapVisitor.ts @@ -1,5 +1,6 @@ import { logWarn } from '@codama/errors'; import { + type ConstantPdaSeedNode, ConstantValueNode, constantValueNode, definedTypeNode, @@ -8,16 +9,17 @@ import { getAllAccounts, getAllDefinedTypes, getAllEvents, + getAllInstructionArguments, getAllInstructionsWithSubs, getAllPdas, getAllPrograms, type InstructionAccountNode, - type InstructionArgumentNode, InstructionNode, isNode, isNodeFilter, pascalCase, type PdaNode, + type PdaValueNode, type ProgramNode, resolveNestedTypeNode, snakeCase, @@ -28,6 +30,7 @@ import { addToRenderMap, createRenderMap, mergeRenderMaps } from '@codama/render import { extendVisitor, findProgramNodeFromPath, + getResolvedInstructionInputsVisitor, LinkableDictionary, NodeStack, pipe, @@ -36,6 +39,7 @@ import { staticVisitor, visit, } from '@codama/visitors-core'; +import { getBase58Encoder } from '@solana/codecs-strings'; import { getTypeManifestVisitor } from './getTypeManifestVisitor'; import { ImportMap } from './ImportMap'; @@ -81,6 +85,11 @@ export function getRenderMapVisitor(options: GetRenderMapOptions = {}) { getTraitsFromNode, traitOptions: options.traitOptions, }); + // Optional accounts are safe as PDA seeds: builders hold accounts as + // Option and only expect() them on the derive path. + const resolvedInstructionInputVisitor = getResolvedInstructionInputsVisitor({ + allowOptionalAccountsAsPdaSeeds: true, + }); const anchorTraits = options.anchorTraits ?? true; return pipe( @@ -137,21 +146,9 @@ export function getRenderMapVisitor(options: GetRenderMapOptions = {}) { } const seedManifest = visit(seed.type, typeManifestVisitor); const resolvedType = resolveNestedTypeNode(seed.type); - let seedBytesExpr: string; - if (isNode(seed.value, 'stringValueNode')) { - const m = renderValueNode(seed.value, getImportFrom, true); - seedsImports.mergeWith(m.imports); - seedBytesExpr = `b${m.render}`; - } else if (isNode(seed.value, 'bytesValueNode')) { - const m = renderValueNode(seed.value, getImportFrom, true); - seedsImports.mergeWith(m.imports); - seedBytesExpr = `&${m.render}`; - } else { - const m = renderValueNode(constantValueNode(seed.type, seed.value), getImportFrom, true); - seedsImports.mergeWith(m.imports); - seedBytesExpr = `&${m.render}`; - } - return { ...seed, resolvedType, seedBytesExpr, typeManifest: seedManifest }; + const seedBytes = renderConstantSeedBytes(seed, getImportFrom); + seedsImports.mergeWith(seedBytes.imports); + return { ...seed, resolvedType, seedBytesExpr: seedBytes.render, typeManifest: seedManifest }; }); const hasVariableSeeds = pdaSeeds.filter(isNodeFilter('variablePdaSeedNode')).length > 0; const constantSeeds = seeds @@ -354,6 +351,18 @@ export function getRenderMapVisitor(options: GetRenderMapOptions = {}) { }); }); + // Extra arguments: required, non-serialized caller inputs (e.g. Anchor + // account-data seeds lowered to argumentValueNodes). They become builder + // fields read by PDA derivations but never enter InstructionData/Args. + const extraArgs = (node.extraArguments ?? []).map(argument => { + const manifest = visit(argument.type, typeManifestVisitor); + imports.mergeWith(manifest.imports); + const name = accountsAndArgsConflicts.includes(argument.name) + ? `${argument.name}_arg` + : argument.name; + return { name, type: manifest.type }; + }); + const struct = structTypeNodeFromInstructionArgumentNodes(node.arguments); const structVisitor = getTypeManifestVisitor({ getImportFrom, @@ -391,41 +400,37 @@ export function getRenderMapVisitor(options: GetRenderMapOptions = {}) { ) .map(a => a.name), ); - const hasRequiredArgs = instructionArgs.some( - arg => !arg.default && !arg.optional && !arg.innerOptionType, - ); - const requiredArgNames = instructionArgs - .filter(arg => !arg.default && !arg.optional && !arg.innerOptionType) - .map(arg => snakeCase(arg.name)); - - // Resolve PDA defaults and topologically sort accounts by dependency. + // Extra args are always required builder inputs. + const hasRequiredArgs = + instructionArgs.some(arg => !arg.default && !arg.optional && !arg.innerOptionType) || + extraArgs.length > 0; + const requiredArgNames = [ + ...instructionArgs + .filter(arg => !arg.default && !arg.optional && !arg.innerOptionType) + .map(arg => snakeCase(arg.name)), + ...extraArgs.map(arg => snakeCase(arg.name)), + ]; + + // Resolve PDA defaults; builder `let` bindings follow the visitor's + // dependency-first order so derived PDAs can feed later derivations. + // Strip `isOptional` for the ordering visit: codama rejects optional + // accounts as seed sources, but the builder unwraps them at runtime. + const orderingNode = { ...node, accounts: node.accounts.map(a => ({ ...a, isOptional: false })) }; + const orderedAccountNames = visit(orderingNode, resolvedInstructionInputVisitor) + .filter(isNodeFilter('instructionAccountNode')) + .map(input => input.name as string); const resolvedAccounts = resolveInstructionPdaDefaults({ - accounts: node.accounts, accountsAndArgsConflicts, builderOptionalAccounts, getImportFrom, imports, - instructionArguments: node.arguments, - instructionName: node.name, + instruction: node, linkables, + orderedAccountNames, program, requiredArgNames, stack, }); - - // An account with a PDA default that could not be resolved has no usable - // default, so it falls back to a required builder input. Drop it from the - // optional sets so its field type and accounts struct stay consistent. - for (const account of resolvedAccounts) { - if ( - account.pdaDefault == null && - !account.isOptional && - account.defaultValue?.kind === 'pdaValueNode' - ) { - builderOptionalAccounts.delete(account.name); - cpiBuilderOptionalAccounts.delete(account.name); - } - } const hasRequiredAccounts = node.accounts.some(a => !builderOptionalAccounts.has(a.name)); return createRenderMap(`instructions/${snakeCase(node.name)}.rs`, { @@ -435,6 +440,7 @@ export function getRenderMapVisitor(options: GetRenderMapOptions = {}) { cpiBuilderOptionalAccounts: [...cpiBuilderOptionalAccounts], dataTraits: dataTraits.render, discriminatorConstants: discriminatorConstants.render, + extraArgs, hasArgs, hasOptional, hasRequiredAccounts, @@ -472,21 +478,9 @@ export function getRenderMapVisitor(options: GetRenderMapOptions = {}) { } const seedManifest = visit(seed.type, typeManifestVisitor); const resolvedType = resolveNestedTypeNode(seed.type); - let seedBytesExpr: string; - if (isNode(seed.value, 'stringValueNode')) { - const m = renderValueNode(seed.value, getImportFrom, true); - imports.mergeWith(m.imports); - seedBytesExpr = `b${m.render}`; - } else if (isNode(seed.value, 'bytesValueNode')) { - const m = renderValueNode(seed.value, getImportFrom, true); - imports.mergeWith(m.imports); - seedBytesExpr = `&${m.render}`; - } else { - const m = renderValueNode(constantValueNode(seed.type, seed.value), getImportFrom, true); - imports.mergeWith(m.imports); - seedBytesExpr = `&${m.render}`; - } - return { ...seed, resolvedType, seedBytesExpr, typeManifest: seedManifest }; + const seedBytes = renderConstantSeedBytes(seed, getImportFrom); + imports.mergeWith(seedBytes.imports); + return { ...seed, resolvedType, seedBytesExpr: seedBytes.render, typeManifest: seedManifest }; }); const hasVariableSeeds = node.seeds.filter(isNodeFilter('variablePdaSeedNode')).length > 0; @@ -496,9 +490,20 @@ export function getRenderMapVisitor(options: GetRenderMapOptions = {}) { const programAddress = node.programId ?? program?.publicKey; + // Dynamic-only PDAs: helpers take the deriving program as a parameter, + // and _ADDRESS folds under the canonical program, not this program's ID. + const dynamicProgramOnly = getDynamicProgramOnlyPdas(program).has(node.name as string); + // Codama pins foreign programs (IDL address constraint) on + // pdaNode.programId; bake that address into the helpers. + const canonicalProgramAddress = + node.programId && node.programId !== program.publicKey ? node.programId : undefined; + let precomputedAddress: string | undefined; - if (!hasVariableSeeds && programAddress) { - precomputedAddress = computePdaAddress(node.seeds, programAddress) ?? undefined; + if (!hasVariableSeeds) { + const foldProgram = dynamicProgramOnly ? canonicalProgramAddress : programAddress; + if (foldProgram) { + precomputedAddress = computePdaAddress(node.seeds, foldProgram) ?? undefined; + } } // Template uses fully-qualified paths for return types and static methods, @@ -510,7 +515,9 @@ export function getRenderMapVisitor(options: GetRenderMapOptions = {}) { return createRenderMap(`pdas/${snakeCase(node.name)}.rs`, { content: render('pdasPage.njk', { + canonicalProgramAddress, constantSeeds, + dynamicProgramOnly, hasVariableSeeds, imports: imports.toString(dependencyMap), pda: node, @@ -829,10 +836,60 @@ function buildProgramEventsRender( }; } +/** + * Linked PDAs whose every use-site passes a dynamic programId. Their helpers + * take the deriving program as a parameter (unless pinned to a foreign address). + */ +function getDynamicProgramOnlyPdas(program: ProgramNode): Set { + const allUsagesDynamic = new Map(); + for (const instruction of getAllInstructionsWithSubs(program, { leavesOnly: false })) { + for (const account of instruction.accounts) { + const defaultValue = account.defaultValue; + if (!defaultValue || !isNode(defaultValue, 'pdaValueNode')) continue; + if (!isNode(defaultValue.pda, 'pdaLinkNode')) continue; + const name = defaultValue.pda.name as string; + allUsagesDynamic.set(name, (allUsagesDynamic.get(name) ?? true) && defaultValue.programId != null); + } + } + return new Set([...allUsagesDynamic.entries()].filter(([, allDynamic]) => allDynamic).map(([name]) => name)); +} + +/** + * Renders a constant PDA seed as a raw byte-slice expression suitable for + * `find_program_address(&[...])`: `b"…"` for strings, `&[…]` for bytes, and + * `&N.to_le_bytes()`-style for typed values. Shared by the PDA-helper pages + * and the inline instruction-builder derivations. + */ +function renderConstantSeedBytes( + seed: ConstantPdaSeedNode, + getImportFrom: GetImportFromFunction, +): { imports: ImportMap; render: string } { + if (isNode(seed.value, 'programIdValueNode')) { + // The program reference is context-dependent; callers render it themselves. + throw new Error('programIdValueNode seeds must be rendered by the caller.'); + } + if (isNode(seed.value, 'stringValueNode')) { + const m = renderValueNode(seed.value, getImportFrom, true); + return { imports: m.imports, render: `b${m.render}` }; + } + if (isNode(seed.value, 'bytesValueNode')) { + const m = renderValueNode(seed.value, getImportFrom, true); + return { imports: m.imports, render: `&${m.render}` }; + } + if (isNode(seed.value, 'publicKeyValueNode')) { + // Codama folds address-pinned program accounts used as seeds into + // constant publicKey seeds; emit the decoded 32 bytes. + const bytes = getBase58Encoder().encode(seed.value.publicKey); + return { imports: new ImportMap(), render: `&[${Array.from(bytes).join(', ')}]` }; + } + const m = renderValueNode(constantValueNode(seed.type, seed.value), getImportFrom, true); + return { imports: m.imports, render: `&${m.render}` }; +} + function getConflictsForInstructionAccountsAndArgs(instruction: InstructionNode): string[] { const allNames = [ ...instruction.accounts.map(account => account.name), - ...instruction.arguments.map(argument => argument.name), + ...getAllInstructionArguments(instruction).map(argument => argument.name), ]; const duplicates = allNames.filter((e, i, a) => a.indexOf(e) !== i); return [...new Set(duplicates)]; @@ -845,11 +902,15 @@ type RenderedSeed = { }; type ResolvedPdaDefault = { - accountDeps: string[]; + /** + * True when the helper call needs a runtime program argument, i.e. the + * deriving program is dynamic and not address-pinned (pinned ones are baked in). + */ + hasDynamicProgram: boolean; hasVariableSeeds: boolean; isLinked: boolean; linkedPdaName?: string; - programAddressExpr?: string; + programAddressExpr: string; renderedSeeds: RenderedSeed[]; }; @@ -858,37 +919,87 @@ type ResolvedAccount = InstructionAccountNode & { }; function resolveInstructionPdaDefaults(ctx: { - accounts: readonly InstructionAccountNode[]; accountsAndArgsConflicts: string[]; builderOptionalAccounts: Set; getImportFrom: GetImportFromFunction; imports: ImportMap; - instructionArguments: readonly InstructionArgumentNode[]; - instructionName: string; + instruction: InstructionNode; linkables: LinkableDictionary; + orderedAccountNames: string[]; program: ProgramNode; requiredArgNames: string[]; stack: NodeStack; }): ResolvedAccount[] { const { - accounts, accountsAndArgsConflicts, builderOptionalAccounts, getImportFrom, imports, - instructionArguments, - instructionName, + instruction, linkables, + orderedAccountNames, program, requiredArgNames, stack, } = ctx; + const accounts = instruction.accounts; + // Includes extraArguments — Anchor lowers account-data seeds (e.g. `guard.mint`) + // to caller-supplied extra arguments. + const instructionArguments = getAllInstructionArguments(instruction); + const instructionName = instruction.name; + const localProgramIdExpr = `crate::${snakeCase(program.name).toUpperCase()}_ID`; + // PDAs whose helpers require the deriving program as a parameter. + const dynamicOnlyPdas = getDynamicProgramOnlyPdas(program); + // Cast to string to avoid branded CamelCaseString type. const pdaDefaultedNames = new Set( accounts.filter(a => a.defaultValue?.kind === 'pdaValueNode').map(a => a.name as string), ); + // Nested argument paths (e.g. `guard.mint`) have no builder field to read from. + const assertNoArgumentPath = (ref: { name: string; path?: readonly string[] }, accountName: string) => { + if (ref.path && ref.path.length > 0) { + throw new Error( + `[Rust] Account [${accountName}] of instruction [${instructionName}] references nested ` + + `argument path [${ref.name}.${ref.path.join('.')}], which the Rust renderer does not support.`, + ); + } + }; + + // Renders the builder expression for the account/argument reference used as a + // PDA's dynamic deriving program. + const renderProgramRefExpr = (ref: NonNullable, accountName: string): string => { + if (isNode(ref, 'accountValueNode')) { + const refName = snakeCase(ref.name); + if (pdaDefaultedNames.has(ref.name)) { + // Previously derived in the builder; visitor ordering guarantees it. + return refName; + } + const refAccount = accounts.find(a => a.name === ref.name); + const isEither = refAccount?.isSigner === 'either'; + const isOptional = builderOptionalAccounts.has(ref.name); + const eitherExtract = isEither ? (isOptional ? '.map(|(k, _)| k)' : '.0') : ''; + if (!isOptional) { + return `self.${refName}${eitherExtract}`; + } + if (refAccount?.defaultValue && isNode(refAccount.defaultValue, 'publicKeyValueNode')) { + return `self.${refName}${eitherExtract}.unwrap_or(solana_address::address!("${refAccount.defaultValue.publicKey}"))`; + } + if (refAccount?.defaultValue && isNode(refAccount.defaultValue, 'programIdValueNode')) { + return `self.${refName}${eitherExtract}.unwrap_or(${localProgramIdExpr})`; + } + return `self.${refName}${eitherExtract}.expect("${refName} is needed for ${snakeCase(accountName)} PDA")`; + } + assertNoArgumentPath(ref, accountName); + const argFieldName = accountsAndArgsConflicts.includes(ref.name) ? `${ref.name}_arg` : ref.name; + const fieldName = snakeCase(argFieldName); + if (requiredArgNames.includes(fieldName)) { + return `self.${fieldName}`; + } + return `self.${fieldName}.clone().expect("${fieldName} is needed for ${snakeCase(accountName)} PDA")`; + }; + const resolvedPdas: Record = {}; for (const account of accounts) { @@ -907,19 +1018,23 @@ function resolveInstructionPdaDefaults(ctx: { pdaNode = defaultValue.pda; } - // Linked PDAs can work without pdaNode (iterate defaultValue.seeds directly). - if (!isLinked && !pdaNode) { - logWarn( - `[Rust] Could not resolve PDA node for account [${account.name}] ` + - `in instruction [${instructionName}]. The account will be treated as required.`, - ); - continue; + // Dynamic programId: render as linked only when the PDA's helper takes a + // program parameter (dynamic-only); mixed-use PDAs fall back to inline. + const dynamicProgramRef = defaultValue.programId; + const renderAsLinked = + isLinked && (!dynamicProgramRef || (linkedPdaName !== undefined && dynamicOnlyPdas.has(linkedPdaName))); + + // Program priority mirrors codama resolve-pda-address.ts: + // dynamic runtime ref > pdaNode constant > local program ID. + let programAddressExpr: string; + if (dynamicProgramRef) { + programAddressExpr = renderProgramRefExpr(dynamicProgramRef, account.name); + } else if (pdaNode?.programId) { + programAddressExpr = `solana_address::address!("${pdaNode.programId}")`; + } else { + programAddressExpr = localProgramIdExpr; } - const programAddressExpr = pdaNode?.programId - ? `solana_address::address!("${pdaNode.programId}")` - : `crate::${snakeCase(program.name).toUpperCase()}_ID`; - // Upstream account defaults for seed resolution. const accountDefaults: Record = {}; const eitherSignerAccounts = new Set(); @@ -930,7 +1045,7 @@ function resolveInstructionPdaDefaults(ctx: { if (refAccount?.defaultValue && isNode(refAccount.defaultValue, 'publicKeyValueNode')) { accountDefaults[refName] = `solana_address::address!("${refAccount.defaultValue.publicKey}")`; } else if (refAccount?.defaultValue && isNode(refAccount.defaultValue, 'programIdValueNode')) { - accountDefaults[refName] = `crate::${snakeCase(program.name).toUpperCase()}_ID`; + accountDefaults[refName] = localProgramIdExpr; } if (refAccount?.isSigner === 'either') { eitherSignerAccounts.add(refName); @@ -939,16 +1054,15 @@ function resolveInstructionPdaDefaults(ctx: { } const renderedSeeds: RenderedSeed[] = []; - const accountDeps: string[] = []; - let seedsComplete = true; // Two rendering paths because extractPdasVisitor only extracts same-program // PDAs — cross-program derivations (e.g. ATAs via the associated-token-program) // stay inline as pdaNode since they can't live in this program's pdas module. // - // Linked (pdaLinkNode): call the standalone find_*_pda() with typed args. + // Linked (pdaLinkNode): call find_*_pda() with typed args (and the program + // when the helper takes one). // Inline (pdaNode): emit find_program_address() with raw byte-slice seeds. - if (isLinked) { + if (renderAsLinked) { for (const seedBinding of defaultValue.seeds) { const seedValue = seedBinding.value; @@ -959,7 +1073,6 @@ function resolveInstructionPdaDefaults(ctx: { const eitherExtract = isEither ? (isOptional ? '.map(|(k, _)| k)' : '.0') : ''; if (pdaDefaultedNames.has(seedValue.name)) { - accountDeps.push(seedValue.name); renderedSeeds.push({ kind: 'accountRef', rawName: refName, render: `&${refName}` }); } else if (!isOptional) { // Required account — direct field access, no Option unwrap. @@ -979,6 +1092,7 @@ function resolveInstructionPdaDefaults(ctx: { renderedSeeds.push({ kind: 'accountRef', rawName: refName, render }); } } else if (isNode(seedValue, 'argumentValueNode')) { + assertNoArgumentPath(seedValue, account.name); const argFieldName = accountsAndArgsConflicts.includes(seedValue.name) ? `${seedValue.name}_arg` : seedValue.name; @@ -986,26 +1100,20 @@ function resolveInstructionPdaDefaults(ctx: { const isRequiredArg = requiredArgNames.includes(fieldName); const arg = instructionArguments.find(a => a.name === seedValue.name); + if (!arg) { + // The native visitor validates seed dependencies upfront, so this is + // unreachable for well-formed IDLs. + throw new Error( + `[Rust] Seed argument [${seedValue.name}] for account [${account.name}] in ` + + `instruction [${instructionName}] does not match any instruction argument.`, + ); + } let argDefault: { isOmitted: boolean; value: string } | null = null; - if (arg?.defaultValue && isNode(arg.defaultValue, VALUE_NODES)) { + if (arg.defaultValue && isNode(arg.defaultValue, VALUE_NODES)) { const { render: value } = renderValueNode(arg.defaultValue, getImportFrom); argDefault = { isOmitted: arg.defaultValueStrategy === 'omitted', value }; } - // A seed may reference an argument that does not exist on the instruction - // (e.g. an account-data path like `guard.mint` that cannot be resolved at - // build time). Without a matching argument there is no builder field to read, - // so treat the PDA as unresolvable and fall back to a required account. - if (!arg) { - logWarn( - `[Rust] Seed argument [${seedValue.name}] for account [${account.name}] ` + - `in instruction [${instructionName}] does not match any instruction ` + - `argument. Falling back to required account.`, - ); - seedsComplete = false; - break; - } - // Pubkey seeds need by-ref for the typed find_*_pda() signature. let isByRef = false; if (pdaNode) { @@ -1037,17 +1145,25 @@ function resolveInstructionPdaDefaults(ctx: { } } } else { - for (const seed of pdaNode!.seeds) { + if (!pdaNode) { + throw new Error( + `[Rust] Could not resolve PDA node for account [${account.name}] ` + + `in instruction [${instructionName}].`, + ); + } + for (const seed of pdaNode.seeds) { if (isNode(seed, 'constantPdaSeedNode')) { if (isNode(seed.value, 'programIdValueNode')) { + // The deriving program doubles as a seed; honor the runtime ref. + const programSeedExpr = dynamicProgramRef ? programAddressExpr : localProgramIdExpr; renderedSeeds.push({ kind: 'programId', - render: `crate::${snakeCase(program.name).toUpperCase()}_ID.as_ref()`, + render: `${programSeedExpr}.as_ref()`, }); } else { - const valueManifest = renderValueNode(seed.value, getImportFrom); - imports.mergeWith(valueManifest.imports); - renderedSeeds.push({ kind: 'constant', render: `&${valueManifest.render}` }); + const seedBytes = renderConstantSeedBytes(seed, getImportFrom); + imports.mergeWith(seedBytes.imports); + renderedSeeds.push({ kind: 'constant', render: seedBytes.render }); } continue; } @@ -1056,13 +1172,10 @@ function resolveInstructionPdaDefaults(ctx: { const binding = defaultValue.seeds.find(s => s.name === seed.name); if (!binding) { - logWarn( - `[Rust] Missing seed value for variable seed [${seed.name}] ` + - `in PDA default for account [${account.name}] ` + - `of instruction [${instructionName}]. Skipping PDA resolution.`, + throw new Error( + `[Rust] Missing seed value for variable seed [${seed.name}] in PDA default ` + + `for account [${account.name}] of instruction [${instructionName}].`, ); - seedsComplete = false; - break; } const resolvedType = resolveNestedTypeNode(seed.type); @@ -1075,10 +1188,6 @@ function resolveInstructionPdaDefaults(ctx: { const eitherExtract = isEither ? (isOptional ? '.map(|(k, _)| k)' : '.0') : ''; const defaultExpr = accountDefaults[seedValue.name]; - if (pdaDefaultedNames.has(seedValue.name)) { - accountDeps.push(seedValue.name); - } - let valueExpr: string; if (pdaDefaultedNames.has(seedValue.name)) { valueExpr = refName; @@ -1103,6 +1212,7 @@ function resolveInstructionPdaDefaults(ctx: { }); } } else if (isNode(seedValue, 'argumentValueNode')) { + assertNoArgumentPath(seedValue, account.name); const argFieldName = accountsAndArgsConflicts.includes(seedValue.name) ? `${seedValue.name}_arg` : seedValue.name; @@ -1110,25 +1220,20 @@ function resolveInstructionPdaDefaults(ctx: { const isRequiredArg = requiredArgNames.includes(fieldName); const arg = instructionArguments.find(a => a.name === seedValue.name); + if (!arg) { + // The native visitor validates seed dependencies upfront, so this is + // unreachable for well-formed IDLs. + throw new Error( + `[Rust] Seed argument [${seedValue.name}] for account [${account.name}] in ` + + `instruction [${instructionName}] does not match any instruction argument.`, + ); + } let argDefault: { isOmitted: boolean; value: string } | null = null; - if (arg?.defaultValue && isNode(arg.defaultValue, VALUE_NODES)) { + if (arg.defaultValue && isNode(arg.defaultValue, VALUE_NODES)) { const { render: value } = renderValueNode(arg.defaultValue, getImportFrom); argDefault = { isOmitted: arg.defaultValueStrategy === 'omitted', value }; } - // See note in the linked-PDA branch above: a seed referencing a - // non-existent argument (e.g. an account-data path) cannot be resolved - // from a builder field, so fall back to a required account. - if (!arg) { - logWarn( - `[Rust] Seed argument [${seedValue.name}] for account [${account.name}] ` + - `in instruction [${instructionName}] does not match any instruction ` + - `argument. Falling back to required account.`, - ); - seedsComplete = false; - break; - } - if (argDefault && argDefault.isOmitted) { if (resolvedType.kind === 'publicKeyTypeNode') { renderedSeeds.push({ kind: 'argumentRef', render: `${argDefault.value}.as_ref()` }); @@ -1178,66 +1283,30 @@ function resolveInstructionPdaDefaults(ctx: { } } - if (!seedsComplete) continue; - const pdaHasVariableSeeds = pdaNode ? pdaNode.seeds.some(s => isNode(s, 'variablePdaSeedNode')) : true; + // Pinned programs (pdaNode.programId) are baked into the generated + // helpers and _ADDRESS constant, so the builder passes no program arg. + const pinnedProgram = + renderAsLinked && pdaNode?.programId && pdaNode.programId !== program.publicKey + ? pdaNode.programId + : undefined; + resolvedPdas[account.name] = { - accountDeps, + hasDynamicProgram: !!dynamicProgramRef && !pinnedProgram, hasVariableSeeds: pdaHasVariableSeeds, - isLinked, + isLinked: renderAsLinked, linkedPdaName, programAddressExpr, renderedSeeds, }; } - // DFS topological sort with cycle detection and propagation. - const accountDeps = new Map>(); - for (const account of accounts) { - const name = account.name; - accountDeps.set(name, new Set()); - const pdaInfo = resolvedPdas[name]; - if (pdaInfo) { - for (const dep of pdaInfo.accountDeps) { - accountDeps.get(name)!.add(dep); - } - } - } - - const sortedNames: string[] = []; - const visited = new Set(); - const visiting = new Set(); - - const topoVisit = (name: string): boolean => { - if (visited.has(name)) return resolvedPdas[name] !== undefined || !pdaDefaultedNames.has(name); - if (visiting.has(name)) { - logWarn( - `[Rust] Circular PDA dependency detected for account [${name}] ` + - `in instruction [${instructionName}]. Falling back to required account.`, - ); - delete resolvedPdas[name]; - return false; - } - visiting.add(name); - for (const dep of accountDeps.get(name) ?? []) { - if (accountDeps.has(dep) && !topoVisit(dep)) { - // Dependency lost its PDA resolution — remove ours too. - delete resolvedPdas[name]; - } - } - visiting.delete(name); - visited.add(name); - sortedNames.push(name); - return resolvedPdas[name] !== undefined || !pdaDefaultedNames.has(name); - }; - - for (const account of accounts) { - topoVisit(account.name); - } - - return sortedNames.map(name => { - const account = accounts.find(a => a.name === name)!; + // Inputs are already validated and dependency-ordered; emit builder `let` + // bindings in that order so derived PDAs can feed later derivations. + const accountsByName = new Map(accounts.map(a => [a.name as string, a])); + return orderedAccountNames.map(name => { + const account = accountsByName.get(name)!; return { ...account, pdaDefault: resolvedPdas[name] ?? null }; }); } diff --git a/test/instructionsPage.test.ts b/test/instructionsPage.test.ts index 5d1e93a..311ce5e 100644 --- a/test/instructionsPage.test.ts +++ b/test/instructionsPage.test.ts @@ -1020,7 +1020,7 @@ test('it handles omitted-default argument seeds in inline pdaNode', () => { expect(content).not.toContain('self.kind'); }); -test('it falls back to .expect() for both accounts in a circular PDA dependency', () => { +test('it throws on a circular PDA dependency', () => { // Given two accounts with circular PDA dependencies (A depends on B, B depends on A). const node = programNode({ instructions: [ @@ -1060,17 +1060,11 @@ test('it falls back to .expect() for both accounts in a circular PDA dependency' publicKey: '11111111111111111111111111111111', }); - const renderMap = visit(node, getRenderMapVisitor()); - const content = getFromRenderMap(renderMap, 'instructions/circular.rs').content; - - // Then BOTH accounts lose PDA resolution and become required constructor params. - // They resolve via let-bindings with direct field access. - codeContains(content, ['let account_a = self.account_a', 'let account_b = self.account_b']); - // No PDA derivation code should be emitted for either. - codeDoesNotContains(content, ['find_program_address', 'unwrap_or_else']); + // Then the native input resolution hard-throws instead of degrading. + expect(() => visit(node, getRenderMapVisitor())).toThrow(/[Cc]ircular dependency/); }); -test('it bails entire PDA resolution when a variable seed has no binding', () => { +test('it throws when a variable seed has no binding', () => { // Given an inline PDA with a variable seed that has no matching binding. const node = programNode({ instructions: [ @@ -1102,13 +1096,8 @@ test('it bails entire PDA resolution when a variable seed has no binding', () => publicKey: '11111111111111111111111111111111', }); - const renderMap = visit(node, getRenderMapVisitor()); - const content = getFromRenderMap(renderMap, 'instructions/deposit.rs').content; - - // PDA resolution fails — vault becomes a required constructor param. - // Resolved via let-binding with direct field access. - codeContains(content, ['let vault = self.vault']); - codeDoesNotContains(content, ['find_program_address', 'unwrap_or_else', '.expect(']); + // An unbound variable seed cannot be derived at runtime — hard-throw. + expect(() => visit(node, getRenderMapVisitor())).toThrow(/Missing seed value for variable seed \[owner\]/); }); test('it renders required args as constructor params', () => { @@ -1630,3 +1619,345 @@ test('it uses unwrap_or with precomputed address for zero-variable-seed linked P codeContains(content, ['unwrap_or(', 'crate::pdas::CONFIG_ADDRESS']); codeDoesNotContains(content, ['unwrap_or_else', 'find_config_pda']); }); + +test('it derives linked PDAs with a dynamic programId by passing the program to the helper', () => { + // Given linked PDAs whose deriving program is a runtime account reference. + const node = programNode({ + instructions: [ + instructionNode({ + accounts: [ + instructionAccountNode({ + isOptional: false, + isSigner: false, + isWritable: false, + name: 'ammProgram', + }), + instructionAccountNode({ isOptional: false, isSigner: false, isWritable: false, name: 'market' }), + instructionAccountNode({ + defaultValue: pdaValueNode( + pdaLinkNode('pool'), + [pdaSeedValueNode('market', accountValueNode('market'))], + accountValueNode('ammProgram'), + ), + isOptional: false, + isSigner: false, + isWritable: true, + name: 'pool', + }), + instructionAccountNode({ + defaultValue: pdaValueNode(pdaLinkNode('authority'), [], accountValueNode('ammProgram')), + isOptional: false, + isSigner: false, + isWritable: false, + name: 'authority', + }), + ], + name: 'migrate', + }), + ], + name: 'testProgram', + pdas: [ + pdaNode({ name: 'pool', seeds: [variablePdaSeedNode('market', publicKeyTypeNode())] }), + pdaNode({ name: 'authority', seeds: [constantPdaSeedNodeFromString('utf8', 'authority')] }), + ], + publicKey: '11111111111111111111111111111111', + }); + + // When we render it. + const renderMap = visit(node, getRenderMapVisitor()); + const content = getFromRenderMap(renderMap, 'instructions/migrate.rs').content; + + // Then the builder calls the helpers with the referenced account as the + // deriving program. + codeContains(content, [ + `crate::pdas::find_pool_pda(`, + `&self.market,`, + `&self.amm_program,`, + `crate::pdas::find_authority_pda(`, + ]); + // And never through a local-program constant. + codeDoesNotContains(content, [`AUTHORITY_ADDRESS`, `_with_program`]); + + // And the dynamic-only PDA helpers take the deriving program as a required + // parameter; the local-program _ADDRESS constant is not emitted. + const authorityPda = getFromRenderMap(renderMap, 'pdas/authority.rs').content; + codeContains(authorityPda, [ + /pub fn find_authority_pda\(\s*program_address: &solana_address::Address,/, + `pub const AUTHORITY_SEED`, + ]); + codeDoesNotContains(authorityPda, [`AUTHORITY_ADDRESS`, `_with_program`, `use crate::TEST_PROGRAM_ID`]); +}); + +test('it derives linked PDAs with a dynamic programId from an argument reference', () => { + // Given a PDA whose deriving program comes from a required instruction argument. + const node = programNode({ + instructions: [ + instructionNode({ + accounts: [ + instructionAccountNode({ isOptional: false, isSigner: false, isWritable: false, name: 'market' }), + instructionAccountNode({ + defaultValue: pdaValueNode( + pdaLinkNode('pool'), + [pdaSeedValueNode('market', accountValueNode('market'))], + argumentValueNode('poolProgram'), + ), + isOptional: false, + isSigner: false, + isWritable: true, + name: 'pool', + }), + ], + arguments: [instructionArgumentNode({ name: 'poolProgram', type: publicKeyTypeNode() })], + name: 'migrate', + }), + ], + name: 'testProgram', + pdas: [pdaNode({ name: 'pool', seeds: [variablePdaSeedNode('market', publicKeyTypeNode())] })], + publicKey: '11111111111111111111111111111111', + }); + + const renderMap = visit(node, getRenderMapVisitor()); + const content = getFromRenderMap(renderMap, 'instructions/migrate.rs').content; + + // Required arg — direct field access as the deriving program. + codeContains(content, [`crate::pdas::find_pool_pda(`, `&self.market,`, `&self.pool_program,`]); +}); + +test('it throws on a nested argument path in a PDA seed', () => { + // Given a PDA seed bound to a nested argument path (e.g. account-data field). + const node = programNode({ + instructions: [ + instructionNode({ + accounts: [ + instructionAccountNode({ + defaultValue: pdaValueNode(pdaLinkNode('guard'), [ + pdaSeedValueNode('mint', argumentValueNode('guardData', ['mint'])), + ]), + isOptional: false, + isSigner: false, + isWritable: false, + name: 'guard', + }), + ], + arguments: [instructionArgumentNode({ name: 'guardData', type: publicKeyTypeNode() })], + name: 'execute', + }), + ], + name: 'testProgram', + pdas: [pdaNode({ name: 'guard', seeds: [variablePdaSeedNode('mint', publicKeyTypeNode())] })], + publicKey: '11111111111111111111111111111111', + }); + + // Nested paths have no builder field to read from — hard-throw. + expect(() => visit(node, getRenderMapVisitor())).toThrow(/nested argument path \[guardData\.mint\]/); +}); + +test('it renders inline constant string seeds with byte semantics', () => { + // Given an inline (non-linked) PDA default with a constant string seed. + const node = programNode({ + instructions: [ + instructionNode({ + accounts: [ + instructionAccountNode({ isOptional: false, isSigner: false, isWritable: false, name: 'owner' }), + instructionAccountNode({ + defaultValue: pdaValueNode( + pdaNode({ + name: 'ata', + programId: 'ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL', + seeds: [ + constantPdaSeedNodeFromString('utf8', 'prefix'), + variablePdaSeedNode('owner', publicKeyTypeNode()), + ], + }), + [pdaSeedValueNode('owner', accountValueNode('owner'))], + ), + isOptional: false, + isSigner: false, + isWritable: true, + name: 'ata', + }), + ], + name: 'init', + }), + ], + name: 'testProgram', + publicKey: '11111111111111111111111111111111', + }); + + const renderMap = visit(node, getRenderMapVisitor()); + const content = getFromRenderMap(renderMap, 'instructions/init.rs').content; + + // The string seed must be a byte-string literal, not a Rust String. + codeContains(content, [ + `find_program_address`, + `b"prefix"`, + `solana_address::address!("ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL")`, + ]); + codeDoesNotContains(content, [`String::from`]); +}); + +test('it renders extra arguments as required builder inputs', () => { + // Given an instruction whose PDA seed reads a caller-supplied extra argument. + const node = programNode({ + instructions: [ + instructionNode({ + accounts: [ + instructionAccountNode({ + defaultValue: pdaValueNode(pdaLinkNode('guard'), [ + pdaSeedValueNode('mint', argumentValueNode('guardMint')), + ]), + isOptional: false, + isSigner: false, + isWritable: false, + name: 'guard', + }), + ], + arguments: [instructionArgumentNode({ name: 'amount', type: numberTypeNode('u64') })], + extraArguments: [instructionArgumentNode({ name: 'guardMint', type: publicKeyTypeNode() })], + name: 'execute', + }), + ], + name: 'testProgram', + pdas: [pdaNode({ name: 'guard', seeds: [variablePdaSeedNode('mint', publicKeyTypeNode())] })], + publicKey: '11111111111111111111111111111111', + }); + + const renderMap = visit(node, getRenderMapVisitor()); + const content = getFromRenderMap(renderMap, 'instructions/execute.rs').content; + + codeContains(content, [ + // Builder field + constructor param appended after required args. + /pub fn new\([\s\S]*amount: u64,[\s\S]*guard_mint: Address,[\s\S]*\) -> Self/, + `guard_mint: Address,`, + // Read by the PDA derivation. + `crate::pdas::find_guard_pda(`, + `&self.guard_mint.clone(),`, + ]); + // Never serialized into the instruction data/args structs. + codeDoesNotContains(content, [`pub guard_mint`]); +}); + +test('it suffixes extra arguments conflicting with account names', () => { + // Given an extra argument whose name collides with an account. + const node = programNode({ + instructions: [ + instructionNode({ + accounts: [ + instructionAccountNode({ isOptional: false, isSigner: false, isWritable: false, name: 'mint' }), + instructionAccountNode({ + defaultValue: pdaValueNode(pdaLinkNode('guard'), [ + pdaSeedValueNode('mint', argumentValueNode('mint')), + ]), + isOptional: false, + isSigner: false, + isWritable: false, + name: 'guard', + }), + ], + extraArguments: [instructionArgumentNode({ name: 'mint', type: publicKeyTypeNode() })], + name: 'execute', + }), + ], + name: 'testProgram', + pdas: [pdaNode({ name: 'guard', seeds: [variablePdaSeedNode('mint', publicKeyTypeNode())] })], + publicKey: '11111111111111111111111111111111', + }); + + const renderMap = visit(node, getRenderMapVisitor()); + const content = getFromRenderMap(renderMap, 'instructions/execute.rs').content; + + // The extra-arg field and its seed usage both carry the _arg suffix. + codeContains(content, [`mint_arg: Address,`, `&self.mint_arg.clone(),`]); +}); + +// Relies on allowOptionalAccountsAsPdaSeeds; derivation runs inside unwrap_or_else, +// so the expect() only fires when the PDA actually needs deriving. +test('it derives a PDA from an optional account seed via expect', () => { + // Given a PDA-defaulted account whose seed reads an optional account. + const node = programNode({ + instructions: [ + instructionNode({ + accounts: [ + instructionAccountNode({ isOptional: true, isSigner: false, isWritable: false, name: 'owner' }), + instructionAccountNode({ + defaultValue: pdaValueNode(pdaLinkNode('record'), [ + pdaSeedValueNode('owner', accountValueNode('owner')), + ]), + isOptional: false, + isSigner: false, + isWritable: true, + name: 'record', + }), + ], + name: 'createRecord', + }), + ], + name: 'testProgram', + pdas: [pdaNode({ name: 'record', seeds: [variablePdaSeedNode('owner', publicKeyTypeNode())] })], + publicKey: '11111111111111111111111111111111', + }); + + // When we render it. + const renderMap = visit(node, getRenderMapVisitor()); + const content = getFromRenderMap(renderMap, 'instructions/create_record.rs').content; + + codeContains(content, [`crate::pdas::find_record_pda(`, `&self.owner.expect("owner is needed for record PDA")`]); +}); + +test('it folds constant-seed dynamic PDAs under the canonical program default', () => { + // Given a constant-seed PDA pinned to a foreign program via pdaNode.programId, + // while the use-site still passes a runtime program reference. + const node = programNode({ + instructions: [ + instructionNode({ + accounts: [ + instructionAccountNode({ + defaultValue: publicKeyValueNode('CPMMoo8L3F4NbTegBCKVNunggL7H1ZpdTHKxQB5qKP1C'), + isOptional: false, + isSigner: false, + isWritable: false, + name: 'cpswapProgram', + }), + instructionAccountNode({ + defaultValue: pdaValueNode( + pdaLinkNode('vaultAuthority'), + [], + accountValueNode('cpswapProgram'), + ), + isOptional: false, + isSigner: false, + isWritable: false, + name: 'vaultAuthority', + }), + ], + name: 'migrate', + }), + ], + name: 'testProgram', + pdas: [ + pdaNode({ + name: 'vaultAuthority', + programId: 'CPMMoo8L3F4NbTegBCKVNunggL7H1ZpdTHKxQB5qKP1C', + seeds: [constantPdaSeedNodeFromString('utf8', 'vault_auth')], + }), + ], + publicKey: '11111111111111111111111111111111', + }); + + const renderMap = visit(node, getRenderMapVisitor()); + + // The pdas page folds the address at codegen time under the pinned program, + // and the helpers bake that program in — no program parameter. + const pdaContent = getFromRenderMap(renderMap, 'pdas/vault_authority.rs').content; + codeContains(pdaContent, [ + `pub const VAULT_AUTHORITY_PROGRAM_ADDRESS: solana_address::Address`, + `CPMMoo8L3F4NbTegBCKVNunggL7H1ZpdTHKxQB5qKP1C`, + `pub const VAULT_AUTHORITY_ADDRESS: solana_address::Address`, + ]); + codeDoesNotContains(pdaContent, [`program_address:`]); + + // The builder uses the folded constant directly. + const ixContent = getFromRenderMap(renderMap, 'instructions/migrate.rs').content; + codeContains(ixContent, [`unwrap_or(`, `crate::pdas::VAULT_AUTHORITY_ADDRESS`]); + codeDoesNotContains(ixContent, [`find_vault_authority_pda`]); +}); diff --git a/test/pdasPage.test.ts b/test/pdasPage.test.ts index 673d86d..78715c1 100644 --- a/test/pdasPage.test.ts +++ b/test/pdasPage.test.ts @@ -9,6 +9,7 @@ import { pdaNode, programNode, publicKeyTypeNode, + publicKeyValueNode, rootNode, variablePdaSeedNode, } from '@codama/nodes'; @@ -209,3 +210,63 @@ test('it renders a PDA with byte array constant seeds', () => { 'mint: &Address,', ]); }); + +test('it renders constant publicKey seeds as byte-array seed constants', () => { + // Given a PDA with a constant publicKey seed, as codama emits when an + // address-pinned program account is used as a seed (e.g. raydium's ammPool). + const node = programNode({ + name: 'myProgram', + pdas: [ + pdaNode({ + name: 'ammPool', + programId: '675kPX9MHTjS2zt1qfr1NYHuzeLXfQM9H24wFSUt1Mp8', + seeds: [ + constantPdaSeedNode( + publicKeyTypeNode(), + publicKeyValueNode('675kPX9MHTjS2zt1qfr1NYHuzeLXfQM9H24wFSUt1Mp8'), + ), + variablePdaSeedNode('market', publicKeyTypeNode()), + constantPdaSeedNodeFromString('utf8', 'amm_associated_seed'), + ], + }), + ], + publicKey: 'TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA', + }); + + // When we render it. + const renderMap = visit(node, getRenderMapVisitor()); + + // Then the publicKey seed renders as its base58-decoded byte slice. + codeContains(getFromRenderMap(renderMap, 'pdas/amm_pool.rs').content, [ + "pub const AMM_POOL_SEED_0: &'static [u8] = " + + '&[75, 217, 73, 196, 54, 2, 195, 63, 32, 119, 144, 237, 22, 163, 82, 76, ' + + '161, 185, 151, 92, 241, 33, 162, 169, 12, 255, 236, 125, 248, 182, 138, 205];', + 'pub const AMM_POOL_SEED_1: &\'static [u8] = b"amm_associated_seed";', + 'pub fn find_amm_pool_pda(', + ]); +}); + +test('it bakes the local program into helpers of same-program PDAs', () => { + // Given a standalone PDA with no dynamic-programId usages. + const node = programNode({ + name: 'myProgram', + pdas: [ + pdaNode({ + name: 'myPda', + seeds: [ + constantPdaSeedNodeFromString('utf8', 'prefix'), + variablePdaSeedNode('owner', publicKeyTypeNode()), + ], + }), + ], + publicKey: '1111', + }); + + // When we render it. + const renderMap = visit(node, getRenderMapVisitor()); + const content = getFromRenderMap(renderMap, 'pdas/my_pda.rs').content; + + // Then the helpers derive under this crate's program — no program parameter. + codeContains(content, [`pub fn find_my_pda_pda(`, `pub fn create_my_pda_pda(`, `&MY_PROGRAM_ID,`]); + codeDoesNotContains(content, [`program_address:`, `_with_program`]); +}); From 5eb8ad7572ae81d0799e2a20944b544f7bb4a38c Mon Sep 17 00:00:00 2001 From: ioxde <228087182+ioxde@users.noreply.github.com> Date: Fri, 5 Jun 2026 10:32:18 -0700 Subject: [PATCH 24/24] Render literal byte ranges in event discriminator checks and skips Replace offset + CONST.len() arithmetic in generated event code with ranges and skips precomputed at generation time, keeping clippy::arithmetic_side_effects out of generated crates: - Fold discriminator checks to literal ranges (data.get(8..16)) when the byte size is statically known, falling back to a starts_with tail probe for link-typed constants of unknown size. - Compare scalar number constants via to_le/be_bytes instead of emitting non-compiling slice operations on them. - Fold CPI-framed skips to a single literal (&data[16..]) with a provenance comment, chaining [CONST.len()..] slices only for unknown-size discriminators. - Unify all condition rendering in renderByteCheck, shared by the events template, identify conditions, and field discriminators. --- .../src/generated/events/lp_change_event.rs | 2 +- .../events/raydium_cp_swap_events.rs | 4 +- .../src/generated/events/swap_event.rs | 2 +- .../generated/events/claim_vested_event.rs | 8 +- .../generated/events/create_vesting_event.rs | 8 +- .../src/generated/events/pool_create_event.rs | 8 +- .../events/raydium_launchpad_events.rs | 27 +- .../src/generated/events/trade_event.rs | 7 +- public/templates/eventsPage.njk | 11 +- public/templates/programEventsPage.njk | 13 +- src/getRenderMapVisitor.ts | 89 +++- src/utils/discriminatorConstant.ts | 71 ++- test/eventsPage.test.ts | 444 +++++++++++++++++- 13 files changed, 581 insertions(+), 113 deletions(-) diff --git a/e2e/raydium-cpmm/src/generated/events/lp_change_event.rs b/e2e/raydium-cpmm/src/generated/events/lp_change_event.rs index 15dbf98..f67d272 100644 --- a/e2e/raydium-cpmm/src/generated/events/lp_change_event.rs +++ b/e2e/raydium-cpmm/src/generated/events/lp_change_event.rs @@ -39,7 +39,7 @@ impl LpChangeEvent { "invalid event discriminator", )); } - let mut data = &data[LP_CHANGE_EVENT_DISCRIMINATOR.len()..]; + let mut data = &data[8..]; Self::deserialize(&mut data) } } diff --git a/e2e/raydium-cpmm/src/generated/events/raydium_cp_swap_events.rs b/e2e/raydium-cpmm/src/generated/events/raydium_cp_swap_events.rs index affde9d..209e1e4 100644 --- a/e2e/raydium-cpmm/src/generated/events/raydium_cp_swap_events.rs +++ b/e2e/raydium-cpmm/src/generated/events/raydium_cp_swap_events.rs @@ -43,11 +43,11 @@ pub fn try_parse_raydium_cp_swap_event( let event_kind = identify_raydium_cp_swap_event(data)?; Some(match event_kind { RaydiumCpSwapEventKind::LpChangeEvent => { - let mut data = &data[LP_CHANGE_EVENT_DISCRIMINATOR.len()..]; + let mut data = &data[8..]; LpChangeEvent::deserialize(&mut data).map(RaydiumCpSwapEvent::LpChangeEvent) } RaydiumCpSwapEventKind::SwapEvent => { - let mut data = &data[SWAP_EVENT_DISCRIMINATOR.len()..]; + let mut data = &data[8..]; SwapEvent::deserialize(&mut data).map(RaydiumCpSwapEvent::SwapEvent) } }) diff --git a/e2e/raydium-cpmm/src/generated/events/swap_event.rs b/e2e/raydium-cpmm/src/generated/events/swap_event.rs index d3f68cf..de94e5d 100644 --- a/e2e/raydium-cpmm/src/generated/events/swap_event.rs +++ b/e2e/raydium-cpmm/src/generated/events/swap_event.rs @@ -36,7 +36,7 @@ impl SwapEvent { "invalid event discriminator", )); } - let mut data = &data[SWAP_EVENT_DISCRIMINATOR.len()..]; + let mut data = &data[8..]; Self::deserialize(&mut data) } } diff --git a/e2e/raydium-launchpad/src/generated/events/claim_vested_event.rs b/e2e/raydium-launchpad/src/generated/events/claim_vested_event.rs index f20b280..2fc1577 100644 --- a/e2e/raydium-launchpad/src/generated/events/claim_vested_event.rs +++ b/e2e/raydium-launchpad/src/generated/events/claim_vested_event.rs @@ -30,16 +30,14 @@ impl ClaimVestedEvent { "invalid event discriminator", )); } - if data.get(8..8 + CLAIM_VESTED_EVENT_DISCRIMINATOR.len()) - != Some(&CLAIM_VESTED_EVENT_DISCRIMINATOR[..]) - { + if data.get(8..16) != Some(&CLAIM_VESTED_EVENT_DISCRIMINATOR[..]) { return Err(std::io::Error::new( std::io::ErrorKind::InvalidData, "invalid event discriminator", )); } - let mut data = - &data[ANCHOR_EVENT_CPI_DISCRIMINATOR.len() + CLAIM_VESTED_EVENT_DISCRIMINATOR.len()..]; + // ANCHOR_EVENT_CPI_DISCRIMINATOR (8) + CLAIM_VESTED_EVENT_DISCRIMINATOR (8) + let mut data = &data[16..]; Self::deserialize(&mut data) } } diff --git a/e2e/raydium-launchpad/src/generated/events/create_vesting_event.rs b/e2e/raydium-launchpad/src/generated/events/create_vesting_event.rs index 3336aca..f38edfe 100644 --- a/e2e/raydium-launchpad/src/generated/events/create_vesting_event.rs +++ b/e2e/raydium-launchpad/src/generated/events/create_vesting_event.rs @@ -30,16 +30,14 @@ impl CreateVestingEvent { "invalid event discriminator", )); } - if data.get(8..8 + CREATE_VESTING_EVENT_DISCRIMINATOR.len()) - != Some(&CREATE_VESTING_EVENT_DISCRIMINATOR[..]) - { + if data.get(8..16) != Some(&CREATE_VESTING_EVENT_DISCRIMINATOR[..]) { return Err(std::io::Error::new( std::io::ErrorKind::InvalidData, "invalid event discriminator", )); } - let mut data = &data - [ANCHOR_EVENT_CPI_DISCRIMINATOR.len() + CREATE_VESTING_EVENT_DISCRIMINATOR.len()..]; + // ANCHOR_EVENT_CPI_DISCRIMINATOR (8) + CREATE_VESTING_EVENT_DISCRIMINATOR (8) + let mut data = &data[16..]; Self::deserialize(&mut data) } } diff --git a/e2e/raydium-launchpad/src/generated/events/pool_create_event.rs b/e2e/raydium-launchpad/src/generated/events/pool_create_event.rs index b967e61..e0cd74f 100644 --- a/e2e/raydium-launchpad/src/generated/events/pool_create_event.rs +++ b/e2e/raydium-launchpad/src/generated/events/pool_create_event.rs @@ -36,16 +36,14 @@ impl PoolCreateEvent { "invalid event discriminator", )); } - if data.get(8..8 + POOL_CREATE_EVENT_DISCRIMINATOR.len()) - != Some(&POOL_CREATE_EVENT_DISCRIMINATOR[..]) - { + if data.get(8..16) != Some(&POOL_CREATE_EVENT_DISCRIMINATOR[..]) { return Err(std::io::Error::new( std::io::ErrorKind::InvalidData, "invalid event discriminator", )); } - let mut data = - &data[ANCHOR_EVENT_CPI_DISCRIMINATOR.len() + POOL_CREATE_EVENT_DISCRIMINATOR.len()..]; + // ANCHOR_EVENT_CPI_DISCRIMINATOR (8) + POOL_CREATE_EVENT_DISCRIMINATOR (8) + let mut data = &data[16..]; Self::deserialize(&mut data) } } diff --git a/e2e/raydium-launchpad/src/generated/events/raydium_launchpad_events.rs b/e2e/raydium-launchpad/src/generated/events/raydium_launchpad_events.rs index 9368b5c..c88b64f 100644 --- a/e2e/raydium-launchpad/src/generated/events/raydium_launchpad_events.rs +++ b/e2e/raydium-launchpad/src/generated/events/raydium_launchpad_events.rs @@ -31,25 +31,22 @@ pub enum RaydiumLaunchpadEventKind { /// Identifies a `raydium_launchpad` event from the provided data. pub fn identify_raydium_launchpad_event(data: &[u8]) -> Option { if data.get(..ANCHOR_EVENT_CPI_DISCRIMINATOR.len()) == Some(&ANCHOR_EVENT_CPI_DISCRIMINATOR[..]) - && data.get(8..8 + CLAIM_VESTED_EVENT_DISCRIMINATOR.len()) - == Some(&CLAIM_VESTED_EVENT_DISCRIMINATOR[..]) + && data.get(8..16) == Some(&CLAIM_VESTED_EVENT_DISCRIMINATOR[..]) { return Some(RaydiumLaunchpadEventKind::ClaimVestedEvent); } if data.get(..ANCHOR_EVENT_CPI_DISCRIMINATOR.len()) == Some(&ANCHOR_EVENT_CPI_DISCRIMINATOR[..]) - && data.get(8..8 + CREATE_VESTING_EVENT_DISCRIMINATOR.len()) - == Some(&CREATE_VESTING_EVENT_DISCRIMINATOR[..]) + && data.get(8..16) == Some(&CREATE_VESTING_EVENT_DISCRIMINATOR[..]) { return Some(RaydiumLaunchpadEventKind::CreateVestingEvent); } if data.get(..ANCHOR_EVENT_CPI_DISCRIMINATOR.len()) == Some(&ANCHOR_EVENT_CPI_DISCRIMINATOR[..]) - && data.get(8..8 + POOL_CREATE_EVENT_DISCRIMINATOR.len()) - == Some(&POOL_CREATE_EVENT_DISCRIMINATOR[..]) + && data.get(8..16) == Some(&POOL_CREATE_EVENT_DISCRIMINATOR[..]) { return Some(RaydiumLaunchpadEventKind::PoolCreateEvent); } if data.get(..ANCHOR_EVENT_CPI_DISCRIMINATOR.len()) == Some(&ANCHOR_EVENT_CPI_DISCRIMINATOR[..]) - && data.get(8..8 + TRADE_EVENT_DISCRIMINATOR.len()) == Some(&TRADE_EVENT_DISCRIMINATOR[..]) + && data.get(8..16) == Some(&TRADE_EVENT_DISCRIMINATOR[..]) { return Some(RaydiumLaunchpadEventKind::TradeEvent); } @@ -72,24 +69,24 @@ pub fn try_parse_raydium_launchpad_event( let event_kind = identify_raydium_launchpad_event(data)?; Some(match event_kind { RaydiumLaunchpadEventKind::ClaimVestedEvent => { - let mut data = &data - [ANCHOR_EVENT_CPI_DISCRIMINATOR.len() + CLAIM_VESTED_EVENT_DISCRIMINATOR.len()..]; + // ANCHOR_EVENT_CPI_DISCRIMINATOR (8) + CLAIM_VESTED_EVENT_DISCRIMINATOR (8) + let mut data = &data[16..]; ClaimVestedEvent::deserialize(&mut data).map(RaydiumLaunchpadEvent::ClaimVestedEvent) } RaydiumLaunchpadEventKind::CreateVestingEvent => { - let mut data = &data - [ANCHOR_EVENT_CPI_DISCRIMINATOR.len() + CREATE_VESTING_EVENT_DISCRIMINATOR.len()..]; + // ANCHOR_EVENT_CPI_DISCRIMINATOR (8) + CREATE_VESTING_EVENT_DISCRIMINATOR (8) + let mut data = &data[16..]; CreateVestingEvent::deserialize(&mut data) .map(RaydiumLaunchpadEvent::CreateVestingEvent) } RaydiumLaunchpadEventKind::PoolCreateEvent => { - let mut data = &data - [ANCHOR_EVENT_CPI_DISCRIMINATOR.len() + POOL_CREATE_EVENT_DISCRIMINATOR.len()..]; + // ANCHOR_EVENT_CPI_DISCRIMINATOR (8) + POOL_CREATE_EVENT_DISCRIMINATOR (8) + let mut data = &data[16..]; PoolCreateEvent::deserialize(&mut data).map(RaydiumLaunchpadEvent::PoolCreateEvent) } RaydiumLaunchpadEventKind::TradeEvent => { - let mut data = - &data[ANCHOR_EVENT_CPI_DISCRIMINATOR.len() + TRADE_EVENT_DISCRIMINATOR.len()..]; + // ANCHOR_EVENT_CPI_DISCRIMINATOR (8) + TRADE_EVENT_DISCRIMINATOR (8) + let mut data = &data[16..]; TradeEvent::deserialize(&mut data).map(RaydiumLaunchpadEvent::TradeEvent) } }) diff --git a/e2e/raydium-launchpad/src/generated/events/trade_event.rs b/e2e/raydium-launchpad/src/generated/events/trade_event.rs index 2865ee4..a0f57f6 100644 --- a/e2e/raydium-launchpad/src/generated/events/trade_event.rs +++ b/e2e/raydium-launchpad/src/generated/events/trade_event.rs @@ -44,15 +44,14 @@ impl TradeEvent { "invalid event discriminator", )); } - if data.get(8..8 + TRADE_EVENT_DISCRIMINATOR.len()) != Some(&TRADE_EVENT_DISCRIMINATOR[..]) - { + if data.get(8..16) != Some(&TRADE_EVENT_DISCRIMINATOR[..]) { return Err(std::io::Error::new( std::io::ErrorKind::InvalidData, "invalid event discriminator", )); } - let mut data = - &data[ANCHOR_EVENT_CPI_DISCRIMINATOR.len() + TRADE_EVENT_DISCRIMINATOR.len()..]; + // ANCHOR_EVENT_CPI_DISCRIMINATOR (8) + TRADE_EVENT_DISCRIMINATOR (8) + let mut data = &data[16..]; Self::deserialize(&mut data) } } diff --git a/public/templates/eventsPage.njk b/public/templates/eventsPage.njk index 05b176a..d3b5319 100644 --- a/public/templates/eventsPage.njk +++ b/public/templates/eventsPage.njk @@ -19,18 +19,17 @@ impl {{ event.name | pascalCase }} { #[inline(always)] pub fn from_bytes(data: &[u8]) -> Result { {% for disc in constantDiscriminators %} -{% if disc.offset === 0 %} - if data.get(..{{ disc.name }}.len()) != Some(&{{ disc.name }}[..]) { -{% else %} - if data.get({{ disc.offset }}..{{ disc.offset }} + {{ disc.name }}.len()) != Some(&{{ disc.name }}[..]) { -{% endif %} + if {{ disc.condition }} { return Err(std::io::Error::new( std::io::ErrorKind::InvalidData, "invalid event discriminator", )); } {% endfor %} - let mut data = &data[{{ hiddenPrefixSkip }}..]; +{% if hiddenPrefixSkip.comment %} + // {{ hiddenPrefixSkip.comment }} +{% endif %} + let mut data = {{ hiddenPrefixSkip.expr }}; Self::deserialize(&mut data) } } diff --git a/public/templates/programEventsPage.njk b/public/templates/programEventsPage.njk index 99d8bc6..6bfc8aa 100644 --- a/public/templates/programEventsPage.njk +++ b/public/templates/programEventsPage.njk @@ -41,19 +41,14 @@ pub fn try_parse_{{ program.name | snakeCase }}_event(data: &[u8]) -> Option { - let mut data = &data[{{ event.hiddenPrefixSkip }}..]; - {{ event.name | pascalCase }}::deserialize(&mut data) - .map({{ program.name | pascalCase }}Event::{{ event.name | pascalCase }}) - } -{% else %} - {{ program.name | pascalCase }}EventKind::{{ event.name | pascalCase }} => { - let mut data = data; +{% if event.hiddenPrefixSkip.comment %} + // {{ event.hiddenPrefixSkip.comment }} +{% endif %} + let mut data = {{ event.hiddenPrefixSkip.expr }}; {{ event.name | pascalCase }}::deserialize(&mut data) .map({{ program.name | pascalCase }}Event::{{ event.name | pascalCase }}) } -{% endif %} {% endfor %} }) } diff --git a/src/getRenderMapVisitor.ts b/src/getRenderMapVisitor.ts index 2a52f88..eac6d4c 100644 --- a/src/getRenderMapVisitor.ts +++ b/src/getRenderMapVisitor.ts @@ -48,6 +48,7 @@ import { CargoDependencies, computePdaAddress, constantDiscriminatorName, + constantDiscriminatorSize, Fragment, getByteArrayDiscriminatorConstantName, getDiscriminatorConditions, @@ -57,6 +58,7 @@ import { getTraitsFromNodeFactory, LinkOverrides, render, + renderByteCheck, TraitOptions, } from './utils'; @@ -225,27 +227,45 @@ export function getRenderMapVisitor(options: GetRenderMapOptions = {}) { const perEventConstantDiscriminators = hasFromBytes ? discriminators .filter(isNodeFilter('constantDiscriminatorNode')) - .map(d => ({ - name: snakeCase( + .map(d => { + const name = snakeCase( constantDiscriminatorName(node.name, d, discriminators), - ).toUpperCase(), - offset: d.offset, - })) + ).toUpperCase(); + return { + condition: renderByteCheck(name, d.constant.type, d.offset, true), + name, + offset: d.offset, + size: constantDiscriminatorSize(d), + }; + }) .sort((a, b) => a.offset - b.offset) : []; const allConstantDiscriminators = isCpiFramed && framingConstantName - ? [{ name: framingConstantName, offset: 0 }, ...perEventConstantDiscriminators] + ? [ + { + condition: renderByteCheck( + framingConstantName, + programEventFraming!.constant.type, + 0, + true, + ), + name: framingConstantName, + offset: 0, + size: renderConstantBytesArray(programEventFraming!.constant)?.len ?? null, + }, + ...perEventConstantDiscriminators, + ] : perEventConstantDiscriminators; const hiddenPrefixSkipResult = hasFromBytes ? isCpiFramed ? getCpiFramedSkip(allConstantDiscriminators) - : getHiddenPrefixSkip(node, allConstantDiscriminators) + : getHiddenPrefixSkip(node) : null; const generateFromBytes = hasFromBytes && hiddenPrefixSkipResult !== null; - const hiddenPrefixSkip = hiddenPrefixSkipResult ?? '0'; + const hiddenPrefixSkip = hiddenPrefixSkipResult ?? NO_SKIP; const constantDiscriminators = generateFromBytes ? allConstantDiscriminators : []; const imports = new ImportMap() @@ -659,12 +679,14 @@ function eventHasFromBytes(event: EventNode): boolean { return hasConstantDiscriminator && dataHasHiddenPrefix; } -function getHiddenPrefixSkip( - event: EventNode, - constantDiscriminators: { name: string; offset: number }[], -): string | null { +/** A rendered `&data[..]` skip expression; `comment` lists the constants folded into a literal offset. */ +type SkipExpr = { comment: string | null; expr: string }; + +const NO_SKIP: SkipExpr = { comment: null, expr: 'data' }; + +function getHiddenPrefixSkip(event: EventNode): SkipExpr | null { if (!isNode(event.data, 'hiddenPrefixTypeNode')) { - return '0'; + return NO_SKIP; } let hasNonFixedSize = false; const prefixSize = event.data.prefix.reduce((sum, p) => { @@ -681,11 +703,8 @@ function getHiddenPrefixSkip( if (hasNonFixedSize) { return null; } - const firstDisc = constantDiscriminators.find(d => d.offset === 0); - if (event.data.prefix.length === 1 && firstDisc) { - return `${firstDisc.name}.len()`; - } - return String(prefixSize); + // Literal byte count: keeps arithmetic out of generated code (clippy::arithmetic_side_effects). + return { comment: null, expr: `&data[${prefixSize}..]` }; } /** Resolved program-level framing: the hoisted prefix constant + its source EventFraming. */ @@ -722,9 +741,19 @@ function isEventCpiFramed(event: EventNode, programEventFraming: ResolvedProgram return event.data.prefix.length > 0; } -function getCpiFramedSkip(constantDiscriminators: { name: string; offset: number }[]): string { - // Sorted by offset; skip past every leading constant discriminator. - return constantDiscriminators.map(d => `${d.name}.len()`).join(' + '); +function getCpiFramedSkip(constantDiscriminators: { name: string; offset: number; size: number | null }[]): SkipExpr { + // Fold known sizes into one leading literal range and chain `[X.len()..]` for the rest, + // so generated code never emits `+` (clippy::arithmetic_side_effects). + const knownSize = constantDiscriminators.reduce((sum, d) => sum + (d.size ?? 0), 0); + const ranges = constantDiscriminators.filter(d => d.size === null).map(d => `[${d.name}.len()..]`); + if (knownSize > 0 || ranges.length === 0) { + ranges.unshift(`[${knownSize}..]`); + } + const comment = + constantDiscriminators.length > 1 + ? constantDiscriminators.map(d => (d.size === null ? d.name : `${d.name} (${d.size})`)).join(' + ') + : null; + return { comment, expr: `&data${ranges.join('')}` }; } /** Renders a fixed-size bytes ConstantValueNode as a Rust `[u8; N] = [b0, b1, ...]` array literal. */ @@ -783,22 +812,30 @@ function buildProgramEventsRender( .map(d => ({ name: snakeCase(constantDiscriminatorName(event.name, d, perEventDiscriminators)).toUpperCase(), offset: d.offset, + size: constantDiscriminatorSize(d), })); let conditions: string[]; - let hiddenPrefixSkipResult: string | null; + let hiddenPrefixSkipResult: SkipExpr | null; if (isCpiFramed && framingConstantName) { conditions = [ - `data.get(..${framingConstantName}.len()) == Some(&${framingConstantName}[..])`, + renderByteCheck(framingConstantName, programEventFraming!.constant.type, 0), ...perEventConditions, ]; - const allConstantDiscs = [{ name: framingConstantName, offset: 0 }, ...perEventConstantDiscs]; + const allConstantDiscs = [ + { + name: framingConstantName, + offset: 0, + size: renderConstantBytesArray(programEventFraming!.constant)?.len ?? null, + }, + ...perEventConstantDiscs, + ]; hiddenPrefixSkipResult = getCpiFramedSkip(allConstantDiscs); } else { conditions = perEventConditions; hiddenPrefixSkipResult = isNode(event.data, 'hiddenPrefixTypeNode') - ? getHiddenPrefixSkip(event, perEventConstantDiscs) - : '0'; + ? getHiddenPrefixSkip(event) + : NO_SKIP; } if (hiddenPrefixSkipResult === null || conditions.length === 0) { diff --git a/src/utils/discriminatorConstant.ts b/src/utils/discriminatorConstant.ts index e4e1aa9..8164a68 100644 --- a/src/utils/discriminatorConstant.ts +++ b/src/utils/discriminatorConstant.ts @@ -6,9 +6,11 @@ import { InstructionArgumentNode, isNode, isNodeFilter, + NumberTypeNode, SizeDiscriminatorNode, snakeCase, StructFieldTypeNode, + TypeNode, VALUE_NODES, } from '@codama/nodes'; import { visit } from '@codama/visitors-core'; @@ -201,11 +203,60 @@ function getConstantCondition( const constName = snakeCase(constantDiscriminatorName(prefix, discriminatorNode, discriminatorNodes)).toUpperCase(); imports.add(`${importPrefix}::${constName}`); - const offset = discriminatorNode.offset; + return renderByteCheck(constName, discriminatorNode.constant.type, discriminatorNode.offset); +} + +/** + * Renders a `data` vs discriminator constant check; `negate` inverts it for guards. Scalar number + * consts compare via `to_le/be_bytes`; ranges are precomputed literals (clippy::arithmetic_side_effects). + */ +export function renderByteCheck(name: string, type: TypeNode, offset: number, negate = false): string { + const eq = negate ? '!=' : '=='; + if (isNode(type, 'numberTypeNode')) { + const byteSize = getNumberByteSize(type.format); + const range = offset === 0 ? `..${byteSize}` : `${offset}..${offset + byteSize}`; + return `data.get(${range}) ${eq} Some(&${name}.${numberBytesFn(type)}())`; + } if (offset === 0) { - return `data.get(..${constName}.len()) == Some(&${constName}[..])`; + return `data.get(..${name}.len()) ${eq} Some(&${name}[..])`; + } + const size = staticByteSize(type); + if (size !== null) { + return `data.get(${offset}..${offset + size}) ${eq} Some(&${name}[..])`; } - return `data.get(${offset}..${offset} + ${constName}.len()) == Some(&${constName}[..])`; + return `${negate ? '!' : ''}data.get(${offset}..).is_some_and(|tail| tail.starts_with(&${name}[..]))`; +} + +/** Byte size of a constant discriminator, when statically known. */ +export function constantDiscriminatorSize(discriminatorNode: ConstantDiscriminatorNode): number | null { + const type = discriminatorNode.constant.type; + if (isNode(type, 'numberTypeNode')) { + return NUMBER_BYTE_SIZES[type.format] ?? null; + } + return staticByteSize(type); +} + +function numberBytesFn(type: NumberTypeNode): string { + return type.endian === 'be' ? 'to_be_bytes' : 'to_le_bytes'; +} + +/** + * Statically known byte size of a type rendered as `[u8; N]`. u8 arrays only: + * other element types wouldn't compile against `&[u8]` data anyway. + */ +function staticByteSize(type: TypeNode): number | null { + if (isNode(type, 'fixedSizeTypeNode')) { + return type.size; + } + if ( + isNode(type, 'arrayTypeNode') && + isNode(type.item, 'numberTypeNode') && + type.item.format === 'u8' && + isNode(type.count, 'fixedCountNode') + ) { + return type.count.value; + } + return null; } function getFieldCondition( @@ -225,19 +276,7 @@ function getFieldCondition( const constName = snakeCase(fieldDiscriminatorName(prefix, discriminatorNode.name)).toUpperCase(); imports.add(`${importPrefix}::${constName}`); - const offset = discriminatorNode.offset; - - if (isNode(field.type, 'numberTypeNode')) { - const byteSize = getNumberByteSize(field.type.format); - const bytesFn = field.type.endian === 'le' ? 'to_le_bytes' : 'to_be_bytes'; - const range = offset === 0 ? `..${byteSize}` : `${offset}..${offset + byteSize}`; - return `data.get(${range}) == Some(&${constName}.${bytesFn}())`; - } - - if (offset === 0) { - return `data.get(..${constName}.len()) == Some(&${constName}[..])`; - } - return `data.get(${offset}..${offset} + ${constName}.len()) == Some(&${constName}[..])`; + return renderByteCheck(constName, field.type, discriminatorNode.offset); } const NUMBER_BYTE_SIZES: Record = { diff --git a/test/eventsPage.test.ts b/test/eventsPage.test.ts index 6dc916d..a41289c 100644 --- a/test/eventsPage.test.ts +++ b/test/eventsPage.test.ts @@ -6,6 +6,8 @@ import { CamelCaseString, constantDiscriminatorNode, constantValueNode, + definedTypeLinkNode, + definedTypeNode, eventNode, fieldDiscriminatorNode, fixedCountNode, @@ -268,11 +270,142 @@ test('it validates all constant discriminators in from_bytes for multi-disc even codeContains(code, [ 'pub fn from_bytes', 'MULTI_DISC_EVENT_DISCRIMINATOR.len()) != Some(&MULTI_DISC_EVENT_DISCRIMINATOR[..])', - 'data.get(12..12 + MULTI_DISC_EVENT_DISCRIMINATOR2.len()) != Some(&MULTI_DISC_EVENT_DISCRIMINATOR2[..])', + 'data.get(12..16) != Some(&MULTI_DISC_EVENT_DISCRIMINATOR2[..])', 'Self::deserialize(&mut data)', ]); }); +test('it uses a literal range in from_bytes for u8-array constant discriminators at non-zero offset', () => { + const prefix = constantValueNode( + fixedSizeTypeNode(bytesTypeNode(), 8), + bytesValueNode('base16', 'aabbccdd11223344'), + ); + // u8-array constant: no fixedSizeTypeNode, but the fixed count gives a static size of 3. + const arrayDisc = constantValueNode( + arrayTypeNode(numberTypeNode('u8'), fixedCountNode(3)), + arrayValueNode([numberValueNode(1), numberValueNode(2), numberValueNode(3)]), + ); + const node = programNode({ + events: [ + eventNode({ + data: hiddenPrefixTypeNode( + structTypeNode([structFieldTypeNode({ name: 'value', type: numberTypeNode('u64') })]), + [prefix], + ), + discriminators: [constantDiscriminatorNode(prefix, 0), constantDiscriminatorNode(arrayDisc, 8)], + name: 'tailEvent', + }), + ], + name: 'myProgram', + publicKey: '11111111111111111111111111111111', + }); + + const renderMap = visit(node, getRenderMapVisitor()); + const code = getFromRenderMap(renderMap, 'events/tail_event.rs').content; + + codeContains(code, [ + 'pub const TAIL_EVENT_DISCRIMINATOR2: [u8; 3] = [1, 2, 3];', + 'if data.get(8..11) != Some(&TAIL_EVENT_DISCRIMINATOR2[..])', + 'let mut data = &data[8..];', + ]); +}); + +test('it falls back to starts_with in from_bytes when a non-zero-offset discriminator size is unknown', () => { + const prefix = constantValueNode( + fixedSizeTypeNode(bytesTypeNode(), 8), + bytesValueNode('base16', 'aabbccdd11223344'), + ); + // Link-typed constant: byte size not resolvable at the discriminator site. + const linkDisc = constantValueNode( + definedTypeLinkNode('discAlias'), + arrayValueNode([numberValueNode(1), numberValueNode(2), numberValueNode(3)]), + ); + const node = programNode({ + definedTypes: [definedTypeNode({ name: 'discAlias', type: fixedSizeTypeNode(bytesTypeNode(), 3) })], + events: [ + eventNode({ + data: hiddenPrefixTypeNode( + structTypeNode([structFieldTypeNode({ name: 'value', type: numberTypeNode('u64') })]), + [prefix], + ), + discriminators: [constantDiscriminatorNode(prefix, 0), constantDiscriminatorNode(linkDisc, 8)], + name: 'tailEvent', + }), + ], + name: 'myProgram', + publicKey: '11111111111111111111111111111111', + }); + + const renderMap = visit(node, getRenderMapVisitor()); + const code = getFromRenderMap(renderMap, 'events/tail_event.rs').content; + + codeContains(code, [ + 'pub const TAIL_EVENT_DISCRIMINATOR2: DiscAlias = [1, 2, 3];', + 'if !data.get(8..).is_some_and(|tail| tail.starts_with(&TAIL_EVENT_DISCRIMINATOR2[..]))', + 'let mut data = &data[8..];', + ]); +}); + +test('it compares number constant discriminators via to_le_bytes in from_bytes', () => { + // Number constants render as scalar Rust constants (`pub const X: u32`), + // so from_bytes must compare their byte encoding, not slice the constant. + const numDisc = constantValueNode(numberTypeNode('u32'), numberValueNode(42)); + const node = programNode({ + events: [ + // Number discriminator at offset 0. + eventNode({ + data: hiddenPrefixTypeNode( + structTypeNode([structFieldTypeNode({ name: 'value', type: numberTypeNode('u64') })]), + [constantValueNode(fixedSizeTypeNode(bytesTypeNode(), 4), bytesValueNode('base16', '2a000000'))], + ), + discriminators: [constantDiscriminatorNode(numDisc, 0)], + name: 'numHeadEvent', + }), + // Number discriminator at non-zero offset. + eventNode({ + data: hiddenPrefixTypeNode( + structTypeNode([structFieldTypeNode({ name: 'value', type: numberTypeNode('u64') })]), + [ + constantValueNode( + fixedSizeTypeNode(bytesTypeNode(), 8), + bytesValueNode('base16', 'aabbccdd11223344'), + ), + ], + ), + discriminators: [ + constantDiscriminatorNode( + constantValueNode( + fixedSizeTypeNode(bytesTypeNode(), 8), + bytesValueNode('base16', 'aabbccdd11223344'), + ), + 0, + ), + constantDiscriminatorNode(numDisc, 8), + ], + name: 'numTailEvent', + }), + ], + name: 'myProgram', + publicKey: '11111111111111111111111111111111', + }); + + const renderMap = visit(node, getRenderMapVisitor()); + + const headCode = getFromRenderMap(renderMap, 'events/num_head_event.rs').content; + codeContains(headCode, [ + 'pub const NUM_HEAD_EVENT_DISCRIMINATOR: u32 = 42;', + 'if data.get(..4) != Some(&NUM_HEAD_EVENT_DISCRIMINATOR.to_le_bytes())', + 'let mut data = &data[4..];', + ]); + + const tailCode = getFromRenderMap(renderMap, 'events/num_tail_event.rs').content; + codeContains(tailCode, [ + 'pub const NUM_TAIL_EVENT_DISCRIMINATOR2: u32 = 42;', + 'if data.get(8..12) != Some(&NUM_TAIL_EVENT_DISCRIMINATOR2.to_le_bytes())', + 'let mut data = &data[8..];', + ]); +}); + test('it uses literal byte count in from_bytes for multi-prefix hidden prefix', () => { const prefix1 = constantValueNode( fixedSizeTypeNode(bytesTypeNode(), 8), @@ -438,12 +571,9 @@ test('it renders identify and try_parse for events with constant discriminators' 'return Some(MyProgramEventKind::TradeEvent)', 'pub fn try_parse_my_program_event(data: &[u8]) -> Option>', 'identify_my_program_event(data)?', - 'MyProgramEventKind::SettleEvent =>', - 'let mut data = &data[SETTLE_EVENT_DISCRIMINATOR.len()..]', - 'SettleEvent::deserialize(&mut data)', - 'MyProgramEventKind::TradeEvent =>', - 'let mut data = &data[TRADE_EVENT_DISCRIMINATOR.len()..]', - 'TradeEvent::deserialize(&mut data)', + // Skips are numeric literals (8-byte prefix), so match each arm to keep them distinct. + /MyProgramEventKind::SettleEvent => \{\s*let mut data = &data\[8\.\.\];\s*SettleEvent::deserialize\(&mut data\)/, + /MyProgramEventKind::TradeEvent => \{\s*let mut data = &data\[8\.\.\];\s*TradeEvent::deserialize\(&mut data\)/, ]); codeDoesNotContains(code, ['from_bytes', 'Err(std::io::Error::new']); }); @@ -492,8 +622,7 @@ test('it uses BorshDeserialize for events without from_bytes in try_parse', () = const code = getFromRenderMap(renderMap, 'events/my_program_events.rs').content; codeContains(code, [ - 'let mut data = &data[TRADE_EVENT_DISCRIMINATOR.len()..]', - 'TradeEvent::deserialize(&mut data)', + /MyProgramEventKind::TradeEvent => \{\s*let mut data = &data\[8\.\.\];\s*TradeEvent::deserialize\(&mut data\)/, ]); codeContains(code, ['SimpleEvent::deserialize(&mut data)']); codeDoesNotContains(code, ['from_bytes']); @@ -758,13 +887,163 @@ test('it handles non-zero offset in constant discriminator conditions', () => { codeContains(code, [ 'pub fn identify_my_program_event', - 'data.get(8..8 + OFFSET_EVENT_DISCRIMINATOR.len()) == Some(&OFFSET_EVENT_DISCRIMINATOR[..])', + 'data.get(8..12) == Some(&OFFSET_EVENT_DISCRIMINATOR[..])', 'return Some(MyProgramEventKind::OffsetEvent)', 'pub fn try_parse_my_program_event', 'OffsetEvent::deserialize(&mut data)', ]); }); +test('it uses a literal range in identify for u8-array constant discriminators at non-zero offset', () => { + // u8-array constant: no fixedSizeTypeNode, but the fixed count gives a static size of 3. + const arrayDisc = constantValueNode( + arrayTypeNode(numberTypeNode('u8'), fixedCountNode(3)), + arrayValueNode([numberValueNode(1), numberValueNode(2), numberValueNode(3)]), + ); + const node = programNode({ + events: [ + eventNode({ + data: structTypeNode([structFieldTypeNode({ name: 'value', type: numberTypeNode('u64') })]), + discriminators: [constantDiscriminatorNode(arrayDisc, 4)], + name: 'tailDiscEvent', + }), + ], + name: 'myProgram', + publicKey: '11111111111111111111111111111111', + }); + + const renderMap = visit(node, getRenderMapVisitor()); + const code = getFromRenderMap(renderMap, 'events/my_program_events.rs').content; + + codeContains(code, [ + 'data.get(4..7) == Some(&TAIL_DISC_EVENT_DISCRIMINATOR[..])', + 'return Some(MyProgramEventKind::TailDiscEvent)', + ]); +}); + +test('it falls back to starts_with in identify when a non-zero-offset discriminator size is unknown', () => { + // Link-typed constant: byte size not resolvable at the discriminator site. + const linkDisc = constantValueNode( + definedTypeLinkNode('discAlias'), + arrayValueNode([numberValueNode(1), numberValueNode(2), numberValueNode(3)]), + ); + const node = programNode({ + definedTypes: [definedTypeNode({ name: 'discAlias', type: fixedSizeTypeNode(bytesTypeNode(), 3) })], + events: [ + eventNode({ + data: structTypeNode([structFieldTypeNode({ name: 'value', type: numberTypeNode('u64') })]), + discriminators: [constantDiscriminatorNode(linkDisc, 4)], + name: 'tailDiscEvent', + }), + ], + name: 'myProgram', + publicKey: '11111111111111111111111111111111', + }); + + const renderMap = visit(node, getRenderMapVisitor()); + const code = getFromRenderMap(renderMap, 'events/my_program_events.rs').content; + + codeContains(code, [ + 'data.get(4..).is_some_and(|tail| tail.starts_with(&TAIL_DISC_EVENT_DISCRIMINATOR[..]))', + 'return Some(MyProgramEventKind::TailDiscEvent)', + ]); +}); + +test('it compares number constant discriminators via to_le_bytes in identify', () => { + // Scalar number constants can't be sliced, so identify compares their byte encoding. + // Only LE is reachable: the type manifest visitor rejects big-endian numbers for Borsh. + const numDisc = constantValueNode(numberTypeNode('u32'), numberValueNode(42)); + const shortDisc = constantValueNode(numberTypeNode('u16'), numberValueNode(7)); + const node = programNode({ + events: [ + eventNode({ + data: structTypeNode([structFieldTypeNode({ name: 'value', type: numberTypeNode('u64') })]), + discriminators: [constantDiscriminatorNode(numDisc, 0), constantDiscriminatorNode(shortDisc, 8)], + name: 'numDiscEvent', + }), + ], + name: 'myProgram', + publicKey: '11111111111111111111111111111111', + }); + + const renderMap = visit(node, getRenderMapVisitor()); + + const eventCode = getFromRenderMap(renderMap, 'events/num_disc_event.rs').content; + codeContains(eventCode, [ + 'pub const NUM_DISC_EVENT_DISCRIMINATOR: u32 = 42;', + 'pub const NUM_DISC_EVENT_DISCRIMINATOR2: u16 = 7;', + ]); + + const code = getFromRenderMap(renderMap, 'events/my_program_events.rs').content; + codeContains(code, [ + 'data.get(..4) == Some(&NUM_DISC_EVENT_DISCRIMINATOR.to_le_bytes())', + 'data.get(8..10) == Some(&NUM_DISC_EVENT_DISCRIMINATOR2.to_le_bytes())', + 'return Some(MyProgramEventKind::NumDiscEvent)', + ]); +}); + +test('it uses a literal range for fixed-size field discriminators at non-zero offset', () => { + const node = programNode({ + events: [ + eventNode({ + data: structTypeNode([ + structFieldTypeNode({ name: 'header', type: numberTypeNode('u32') }), + structFieldTypeNode({ + defaultValue: arrayValueNode([numberValueNode(1), numberValueNode(2), numberValueNode(3)]), + name: 'disc', + type: arrayTypeNode(numberTypeNode('u8'), fixedCountNode(3)), + }), + structFieldTypeNode({ name: 'value', type: numberTypeNode('u64') }), + ]), + discriminators: [fieldDiscriminatorNode('disc', 4)], + name: 'offsetFieldEvent', + }), + ], + name: 'myProgram', + publicKey: '11111111111111111111111111111111', + }); + + const renderMap = visit(node, getRenderMapVisitor()); + const code = getFromRenderMap(renderMap, 'events/my_program_events.rs').content; + + codeContains(code, [ + 'data.get(4..7) == Some(&OFFSET_FIELD_EVENT_DISC[..])', + 'return Some(MyProgramEventKind::OffsetFieldEvent)', + ]); +}); + +test('it falls back to starts_with for field discriminators with unknown size at non-zero offset', () => { + const node = programNode({ + definedTypes: [definedTypeNode({ name: 'discAlias', type: fixedSizeTypeNode(bytesTypeNode(), 3) })], + events: [ + eventNode({ + data: structTypeNode([ + structFieldTypeNode({ name: 'header', type: numberTypeNode('u32') }), + structFieldTypeNode({ + defaultValue: arrayValueNode([numberValueNode(1), numberValueNode(2), numberValueNode(3)]), + name: 'disc', + // Link-typed field: byte size not resolvable at the discriminator site. + type: definedTypeLinkNode('discAlias'), + }), + structFieldTypeNode({ name: 'value', type: numberTypeNode('u64') }), + ]), + discriminators: [fieldDiscriminatorNode('disc', 4)], + name: 'offsetFieldEvent', + }), + ], + name: 'myProgram', + publicKey: '11111111111111111111111111111111', + }); + + const renderMap = visit(node, getRenderMapVisitor()); + const code = getFromRenderMap(renderMap, 'events/my_program_events.rs').content; + + codeContains(code, [ + 'data.get(4..).is_some_and(|tail| tail.starts_with(&OFFSET_FIELD_EVENT_DISC[..]))', + 'return Some(MyProgramEventKind::OffsetFieldEvent)', + ]); +}); + test('it handles multiple constant discriminators and excludes events with unresolvable field discriminators', () => { const disc1 = constantValueNode(fixedSizeTypeNode(bytesTypeNode(), 4), bytesValueNode('base16', 'aabbccdd')); const disc2 = constantValueNode(fixedSizeTypeNode(bytesTypeNode(), 2), bytesValueNode('base16', 'eeff')); @@ -795,7 +1074,7 @@ test('it handles multiple constant discriminators and excludes events with unres codeContains(code, [ 'MULTI_DISC_EVENT_DISCRIMINATOR.len()) == Some(&MULTI_DISC_EVENT_DISCRIMINATOR[..])', - 'MULTI_DISC_EVENT_DISCRIMINATOR2.len()) == Some(&MULTI_DISC_EVENT_DISCRIMINATOR2[..])', + 'data.get(4..6) == Some(&MULTI_DISC_EVENT_DISCRIMINATOR2[..])', 'return Some(MyProgramEventKind::MultiDiscEvent)', ]); codeContains(code, ['pub enum MyProgramEventKind']); @@ -876,10 +1155,138 @@ test('it generates from_bytes that validates both the framing prefix and the eve codeContains(tradeEventCode, [ 'pub fn from_bytes', 'data.get(..EVENT_CPI_PREFIX.len()) != Some(&EVENT_CPI_PREFIX[..])', - 'data.get(8..8 + TRADE_EVENT_DISCRIMINATOR.len()) != Some(&TRADE_EVENT_DISCRIMINATOR[..])', - 'let mut data = &data[EVENT_CPI_PREFIX.len() + TRADE_EVENT_DISCRIMINATOR.len()..];', - 'Self::deserialize(&mut data)', + 'data.get(8..16) != Some(&TRADE_EVENT_DISCRIMINATOR[..])', + // Both discriminator sizes are known, so the skip folds to a literal + // with an explanatory comment on the line above. + /\/\/ EVENT_CPI_PREFIX \(8\) \+ TRADE_EVENT_DISCRIMINATOR \(8\)\n\s*let mut data = &data\[16\.\.\];\n\s*Self::deserialize\(&mut data\)/, + ]); +}); + +test('it folds the framed skip to a literal for u8-array discriminators', () => { + // u8-array discriminator: the fixed count gives a static size of 8, so the skip folds to 16. + const arrayEventDisc = constantValueNode( + arrayTypeNode(numberTypeNode('u8'), fixedCountNode(8)), + arrayValueNode([ + numberValueNode(1), + numberValueNode(2), + numberValueNode(3), + numberValueNode(4), + numberValueNode(5), + numberValueNode(6), + numberValueNode(7), + numberValueNode(8), + ]), + ); + const node = programNode({ + events: [ + eventNode({ + data: hiddenPrefixTypeNode( + structTypeNode([structFieldTypeNode({ name: 'amount', type: numberTypeNode('u64') })]), + [framingPrefix, arrayEventDisc], + ), + discriminators: [ + constantDiscriminatorNode(framingPrefix, 0), + constantDiscriminatorNode(arrayEventDisc, 8), + ], + framing: cpiFraming, + name: 'mixedEvent', + }), + ], + name: 'myProgram', + publicKey: '11111111111111111111111111111111', + }); + + const renderMap = visit(node, getRenderMapVisitor()); + const eventCode = getFromRenderMap(renderMap, 'events/mixed_event.rs').content; + const programEventsCode = getFromRenderMap(renderMap, 'events/my_program_events.rs').content; + + codeContains(eventCode, [ + 'data.get(..EVENT_CPI_PREFIX.len()) != Some(&EVENT_CPI_PREFIX[..])', + 'data.get(8..16) != Some(&MIXED_EVENT_DISCRIMINATOR[..])', + 'let mut data = &data[16..];', + ]); + codeContains(programEventsCode, [ + /MyProgramEventKind::MixedEvent => \{\s*\/\/ EVENT_CPI_PREFIX \(8\) \+ MIXED_EVENT_DISCRIMINATOR \(8\)\n\s*let mut data = &data\[16\.\.\];\n\s*MixedEvent::deserialize\(&mut data\)/, + ]); +}); + +test('it compares number constant discriminators via to_le_bytes in framed from_bytes', () => { + const numEventDisc = constantValueNode(numberTypeNode('u32'), numberValueNode(42)); + const node = programNode({ + events: [ + eventNode({ + data: hiddenPrefixTypeNode( + structTypeNode([structFieldTypeNode({ name: 'amount', type: numberTypeNode('u64') })]), + [framingPrefix, numEventDisc], + ), + discriminators: [ + constantDiscriminatorNode(framingPrefix, 0), + constantDiscriminatorNode(numEventDisc, 8), + ], + framing: cpiFraming, + name: 'numFramedEvent', + }), + ], + name: 'myProgram', + publicKey: '11111111111111111111111111111111', + }); + + const renderMap = visit(node, getRenderMapVisitor()); + const eventCode = getFromRenderMap(renderMap, 'events/num_framed_event.rs').content; + const programEventsCode = getFromRenderMap(renderMap, 'events/my_program_events.rs').content; + + codeContains(eventCode, [ + 'pub const NUM_FRAMED_EVENT_DISCRIMINATOR: u32 = 42;', + 'data.get(..EVENT_CPI_PREFIX.len()) != Some(&EVENT_CPI_PREFIX[..])', + 'if data.get(8..12) != Some(&NUM_FRAMED_EVENT_DISCRIMINATOR.to_le_bytes())', + // Both sizes are known (8 framing + 4 number), so the skip folds to a literal. + 'let mut data = &data[12..];', + ]); + codeContains(programEventsCode, [ + 'data.get(8..12) == Some(&NUM_FRAMED_EVENT_DISCRIMINATOR.to_le_bytes())', + /MyProgramEventKind::NumFramedEvent => \{\s*\/\/ EVENT_CPI_PREFIX \(8\) \+ NUM_FRAMED_EVENT_DISCRIMINATOR \(4\)\n\s*let mut data = &data\[12\.\.\];\n\s*NumFramedEvent::deserialize\(&mut data\)/, + ]); +}); + +test('it falls back to a chained .len() slice skip when a framed discriminator size is unknown', () => { + // Link-typed discriminator: the aliased type's byte size is not resolvable + // at the discriminator site, so the framed skip can't fold to a literal. + const linkEventDisc = constantValueNode( + definedTypeLinkNode('discAlias'), + arrayValueNode([numberValueNode(1), numberValueNode(2), numberValueNode(3)]), + ); + const node = programNode({ + definedTypes: [definedTypeNode({ name: 'discAlias', type: fixedSizeTypeNode(bytesTypeNode(), 3) })], + events: [ + eventNode({ + data: hiddenPrefixTypeNode( + structTypeNode([structFieldTypeNode({ name: 'amount', type: numberTypeNode('u64') })]), + [framingPrefix, linkEventDisc], + ), + discriminators: [ + constantDiscriminatorNode(framingPrefix, 0), + constantDiscriminatorNode(linkEventDisc, 8), + ], + framing: cpiFraming, + name: 'mixedEvent', + }), + ], + name: 'myProgram', + publicKey: '11111111111111111111111111111111', + }); + + const renderMap = visit(node, getRenderMapVisitor()); + const eventCode = getFromRenderMap(renderMap, 'events/mixed_event.rs').content; + const programEventsCode = getFromRenderMap(renderMap, 'events/my_program_events.rs').content; + + codeContains(eventCode, [ + 'data.get(..EVENT_CPI_PREFIX.len()) != Some(&EVENT_CPI_PREFIX[..])', + 'if !data.get(8..).is_some_and(|tail| tail.starts_with(&MIXED_EVENT_DISCRIMINATOR[..]))', + // The framing size (8) is known and folds to a literal; the unknown-size + // discriminator chains a `[.len()..]` slice so no `+` arithmetic is emitted. + /\/\/ EVENT_CPI_PREFIX \(8\) \+ MIXED_EVENT_DISCRIMINATOR\n\s*let mut data = &data\[8\.\.\]\[MIXED_EVENT_DISCRIMINATOR\.len\(\)\.\.\];/, ]); + codeContains(programEventsCode, ['let mut data = &data[8..][MIXED_EVENT_DISCRIMINATOR.len()..];']); }); test('it references the hoisted framing constant in identify and try_parse', () => { @@ -895,11 +1302,12 @@ test('it references the hoisted framing constant in identify and try_parse', () codeContains(programEventsCode, [ 'pub fn identify_my_program_event', 'data.get(..EVENT_CPI_PREFIX.len()) == Some(&EVENT_CPI_PREFIX[..])', - '&& data.get(8..8 + TRADE_EVENT_DISCRIMINATOR.len()) == Some(&TRADE_EVENT_DISCRIMINATOR[..])', - '&& data.get(8..8 + SETTLE_EVENT_DISCRIMINATOR.len()) == Some(&SETTLE_EVENT_DISCRIMINATOR[..])', + '&& data.get(8..16) == Some(&TRADE_EVENT_DISCRIMINATOR[..])', + '&& data.get(8..16) == Some(&SETTLE_EVENT_DISCRIMINATOR[..])', 'pub fn try_parse_my_program_event', - 'let mut data = &data[EVENT_CPI_PREFIX.len() + TRADE_EVENT_DISCRIMINATOR.len()..]', - 'let mut data = &data[EVENT_CPI_PREFIX.len() + SETTLE_EVENT_DISCRIMINATOR.len()..]', + // Skips are numeric literals (8 framing + 8 event disc), so match each arm to keep them distinct. + /MyProgramEventKind::TradeEvent => \{\s*\/\/ EVENT_CPI_PREFIX \(8\) \+ TRADE_EVENT_DISCRIMINATOR \(8\)\n\s*let mut data = &data\[16\.\.\];\n\s*TradeEvent::deserialize\(&mut data\)/, + /MyProgramEventKind::SettleEvent => \{\s*\/\/ EVENT_CPI_PREFIX \(8\) \+ SETTLE_EVENT_DISCRIMINATOR \(8\)\n\s*let mut data = &data\[16\.\.\];\n\s*SettleEvent::deserialize\(&mut data\)/, ]); });