diff --git a/.changeset/good-readers-flash.md b/.changeset/good-readers-flash.md new file mode 100644 index 000000000..32b167dea --- /dev/null +++ b/.changeset/good-readers-flash.md @@ -0,0 +1,5 @@ +--- +'@codama/renderers-rust': patch +--- + +Add anchorTraits option to Rust renderer diff --git a/packages/renderers-rust/README.md b/packages/renderers-rust/README.md index af05de381..e1ebb8ba2 100644 --- a/packages/renderers-rust/README.md +++ b/packages/renderers-rust/README.md @@ -47,6 +47,7 @@ The `renderVisitor` accepts the following options. | `dependencyMap` | `Record` | `{}` | A mapping between import aliases and their actual crate name or path in Rust. | | `renderParentInstructions` | `boolean` | `false` | When using nested instructions, whether the parent instructions should also be rendered. When set to `false` (default), only the instruction leaves are being rendered. | | `traitOptions` | [`TraitOptions`](#trait-options) | `DEFAULT_TRAIT_OPTIONS` | A set of options that can be used to configure how traits are rendered for every Rust types. See [documentation below](#trait-options) for more information. | +| `anchorTraits` | `boolean` | `true` | Whether to generate Anchor traits `impl` for account types. | ## Trait Options diff --git a/packages/renderers-rust/public/templates/accountsPage.njk b/packages/renderers-rust/public/templates/accountsPage.njk index 006ec8a8c..aa0d46402 100644 --- a/packages/renderers-rust/public/templates/accountsPage.njk +++ b/packages/renderers-rust/public/templates/accountsPage.njk @@ -128,33 +128,35 @@ impl<'a> TryFrom<&solana_program::account_info::AccountInfo<'a>> for {{ account. } } -#[cfg(feature = "anchor")] -impl anchor_lang::AccountDeserialize for {{ account.name | pascalCase }} { - fn try_deserialize_unchecked(buf: &mut &[u8]) -> anchor_lang::Result { - Ok(Self::deserialize(buf)?) - } -} +{% if anchorTraits %} + #[cfg(feature = "anchor")] + impl anchor_lang::AccountDeserialize for {{ account.name | pascalCase }} { + fn try_deserialize_unchecked(buf: &mut &[u8]) -> anchor_lang::Result { + Ok(Self::deserialize(buf)?) + } + } -#[cfg(feature = "anchor")] -impl anchor_lang::AccountSerialize for {{ account.name | pascalCase }} {} + #[cfg(feature = "anchor")] + impl anchor_lang::AccountSerialize for {{ account.name | pascalCase }} {} -#[cfg(feature = "anchor")] -impl anchor_lang::Owner for {{ account.name | pascalCase }} { - fn owner() -> Pubkey { - crate::{{ program.name | snakeCase | upper }}_ID - } -} + #[cfg(feature = "anchor")] + impl anchor_lang::Owner for {{ account.name | pascalCase }} { + fn owner() -> Pubkey { + crate::{{ program.name | snakeCase | upper }}_ID + } + } -#[cfg(feature = "anchor-idl-build")] -impl anchor_lang::IdlBuild for {{ account.name | pascalCase }} {} + #[cfg(feature = "anchor-idl-build")] + impl anchor_lang::IdlBuild for {{ account.name | pascalCase }} {} -{# - This is not used for the IDL generation since default `IdlBuild` impl doesn't include - the type in the IDL but it stil needs to be added in order to make compilation work. -#} -#[cfg(feature = "anchor-idl-build")] -impl anchor_lang::Discriminator for {{ account.name | pascalCase }} { - const DISCRIMINATOR: [u8; 8] = [0; 8]; -} + {# + This is not used for the IDL generation since default `IdlBuild` impl doesn't include + the type in the IDL but it stil needs to be added in order to make compilation work. + #} + #[cfg(feature = "anchor-idl-build")] + impl anchor_lang::Discriminator for {{ account.name | pascalCase }} { + const DISCRIMINATOR: [u8; 8] = [0; 8]; + } +{% endif %} {% endblock %} diff --git a/packages/renderers-rust/src/getRenderMapVisitor.ts b/packages/renderers-rust/src/getRenderMapVisitor.ts index 27835fde8..9c66734c5 100644 --- a/packages/renderers-rust/src/getRenderMapVisitor.ts +++ b/packages/renderers-rust/src/getRenderMapVisitor.ts @@ -30,6 +30,7 @@ import { renderValueNode } from './renderValueNodeVisitor'; import { getImportFromFactory, getTraitsFromNodeFactory, LinkOverrides, render, TraitOptions } from './utils'; export type GetRenderMapOptions = { + anchorTraits?: boolean; defaultTraitOverrides?: string[]; dependencyMap?: Record; linkOverrides?: LinkOverrides; @@ -46,6 +47,7 @@ export function getRenderMapVisitor(options: GetRenderMapOptions = {}) { const getImportFrom = getImportFromFactory(options.linkOverrides ?? {}); const getTraitsFromNode = getTraitsFromNodeFactory(options.traitOptions); const typeManifestVisitor = getTypeManifestVisitor({ getImportFrom, getTraitsFromNode }); + const anchorTraits = options.anchorTraits ?? true; return pipe( staticVisitor( @@ -92,6 +94,7 @@ export function getRenderMapVisitor(options: GetRenderMapOptions = {}) { `accounts/${snakeCase(node.name)}.rs`, render('accountsPage.njk', { account: node, + anchorTraits, constantSeeds, hasVariableSeeds, imports: imports diff --git a/packages/renderers-rust/test/accountsPage.test.ts b/packages/renderers-rust/test/accountsPage.test.ts index 72c820061..a3292b74b 100644 --- a/packages/renderers-rust/test/accountsPage.test.ts +++ b/packages/renderers-rust/test/accountsPage.test.ts @@ -17,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 byte array seed used on an account', () => { // Given the following program with 1 account and 1 pda with a byte array as seeds. @@ -134,3 +134,33 @@ test('it renders anchor traits impl', () => { 'impl anchor_lang::Owner for TestAccount', ]); }); + +test('it renders account without anchor traits', () => { + // Given the following account. + const node = programNode({ + accounts: [ + accountNode({ + discriminators: [ + { + kind: 'fieldDiscriminatorNode', + name: camelCase('discriminator'), + offset: 0, + }, + ], + name: 'testAccount', + pda: pdaLinkNode('testPda'), + }), + ], + name: 'myProgram', + publicKey: '1111', + }); + + // When we render it with anchor traits disabled. + const renderMap = visit(node, getRenderMapVisitor({ anchorTraits: false })); + + // Then we do not expect Anchor traits. + codeDoesNotContains(renderMap.get('accounts/test_account.rs'), [ + '#[cfg(feature = "anchor")]', + '#[cfg(feature = "anchor-idl-build")]', + ]); +});