@layerzerolabs/framework-solana-anchor-trait 0.2.62 → 0.2.63

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (51) hide show
  1. package/Cargo.toml +3 -0
  2. package/README.md +5 -0
  3. package/SPEC.md +318 -0
  4. package/examples/shapes/Cargo.lock +4126 -0
  5. package/examples/shapes/Cargo.toml +16 -0
  6. package/examples/shapes/macros/src/audit.rs +15 -0
  7. package/examples/shapes/macros/src/instructions/clear.rs +19 -0
  8. package/examples/shapes/macros/src/instructions/compute_area.rs +18 -20
  9. package/examples/shapes/macros/src/instructions/compute_perimeter.rs +18 -20
  10. package/examples/shapes/macros/src/instructions/get_dimension.rs +19 -0
  11. package/examples/shapes/macros/src/instructions/get_dimension_count.rs +19 -17
  12. package/examples/shapes/macros/src/instructions/mod.rs +8 -0
  13. package/examples/shapes/macros/src/instructions/reset.rs +50 -0
  14. package/examples/shapes/macros/src/instructions/scale.rs +52 -0
  15. package/examples/shapes/macros/src/lib.rs +14 -11
  16. package/examples/shapes/macros/src/shapes.rs +21 -26
  17. package/examples/shapes/macros/src/state_types.rs +14 -0
  18. package/examples/shapes/programs/ellipse/Cargo.toml +7 -0
  19. package/examples/shapes/programs/ellipse/src/lib.rs +69 -17
  20. package/examples/shapes/programs/ellipse/tests/ellipse/helpers.rs +110 -0
  21. package/examples/shapes/programs/ellipse/tests/ellipse/negative.rs +49 -0
  22. package/examples/shapes/programs/ellipse/tests/ellipse/positive.rs +231 -0
  23. package/examples/shapes/programs/ellipse/tests/ellipse.rs +23 -0
  24. package/examples/shapes/programs/triangle/Cargo.toml +7 -0
  25. package/examples/shapes/programs/triangle/src/lib.rs +69 -16
  26. package/examples/shapes/programs/triangle/tests/triangle/helpers.rs +123 -0
  27. package/examples/shapes/programs/triangle/tests/triangle/negative.rs +49 -0
  28. package/examples/shapes/programs/triangle/tests/triangle/positive.rs +225 -0
  29. package/examples/shapes/programs/triangle/tests/triangle.rs +23 -0
  30. package/examples/shapes/target/deploy/shapes_ellipse-keypair.json +1 -0
  31. package/examples/shapes/target/deploy/shapes_ellipse.so +0 -0
  32. package/examples/shapes/target/deploy/shapes_triangle-keypair.json +1 -0
  33. package/examples/shapes/target/deploy/shapes_triangle.so +0 -0
  34. package/package.json +14 -7
  35. package/src/assembly.rs +41 -6
  36. package/src/generation.rs +108 -131
  37. package/src/lib.rs +6 -4
  38. package/src/overrides.rs +56 -81
  39. package/tests/assembly.rs +154 -23
  40. package/tests/common/mod.rs +68 -14
  41. package/tests/generation.rs +137 -65
  42. package/tests/override.rs +93 -55
  43. package/tests/snapshots/snapshots__tests__snapshot_all_defaults.snap +32 -5
  44. package/tests/snapshots/snapshots__tests__snapshot_full_override.snap +35 -7
  45. package/tests/snapshots/snapshots__tests__snapshot_handler_override.snap +37 -7
  46. package/tests/snapshots/snapshots__tests__snapshot_mixed_overrides.snap +40 -9
  47. package/tests/snapshots/snapshots__tests__snapshot_with_extend_macro.snap +82 -0
  48. package/tests/snapshots.rs +51 -18
  49. package/examples/shapes/Anchor.toml +0 -19
  50. package/examples/shapes/programs/ellipse/src/state.rs +0 -9
  51. package/examples/shapes/programs/triangle/src/state.rs +0 -9
@@ -0,0 +1,16 @@
1
+ [workspace]
2
+ members = ["programs/ellipse", "programs/triangle", "macros"]
3
+ resolver = "2"
4
+
5
+ [workspace.dependencies]
6
+ anchor-lang = "0.32.1"
7
+ anchor-trait = { path = "../.." }
8
+ shapes-macros = { path = "macros" }
9
+ mollusk-svm = { version = "0.8", features = ["inner-instructions"] }
10
+ solana-account = "3.4"
11
+ solana-instruction = "3.2"
12
+ solana-pubkey = "4.1"
13
+ solana-program-error = "3.0"
14
+
15
+ [profile.release]
16
+ overflow-checks = true
@@ -0,0 +1,15 @@
1
+ use proc_macro2::TokenStream;
2
+ use quote::quote;
3
+ use syn::ItemMod;
4
+
5
+ pub fn expand(_attr: TokenStream, item: TokenStream) -> syn::Result<TokenStream> {
6
+ let mut module = syn::parse2::<ItemMod>(item)?;
7
+
8
+ if let Some((_, ref mut items)) = module.content {
9
+ items.push(syn::parse_quote! {
10
+ pub const SHAPES_AUDIT_ENABLED: bool = true;
11
+ });
12
+ }
13
+
14
+ Ok(quote! { #module })
15
+ }
@@ -0,0 +1,19 @@
1
+ //! Code generator for the `clear` instruction.
2
+ //!
3
+ //! Required instruction with no params. Zeros all mutable state.
4
+ //! Demonstrates a **required + mutable + no-params** instruction — every shape
5
+ //! must implement this since each shape's zero-state may differ.
6
+
7
+ use anchor_trait::InstructionSpec;
8
+ use quote::quote;
9
+
10
+ use super::CodegenContext;
11
+
12
+ pub(super) fn spec() -> InstructionSpec<CodegenContext> {
13
+ InstructionSpec {
14
+ params_type: None,
15
+ return_type: quote!(()),
16
+ is_view: false,
17
+ default_impl: None, // Required — implementor MUST provide
18
+ }
19
+ }
@@ -2,9 +2,9 @@
2
2
  //!
3
3
  //! Provided instruction with default handler: width * height (rectangle area).
4
4
 
5
- use anchor_trait::{DefaultImpl, InstructionSpec};
6
- use proc_macro2::TokenStream;
5
+ use anchor_trait::{DefaultAccounts, DefaultImpl, InstructionSpec};
7
6
  use quote::{format_ident, quote};
7
+ use syn::parse_quote;
8
8
 
9
9
  use super::CodegenContext;
10
10
 
@@ -14,7 +14,6 @@ pub(super) fn spec(_ctx: &CodegenContext) -> InstructionSpec<CodegenContext> {
14
14
  return_type: quote!(u64),
15
15
  is_view: true,
16
16
  default_impl: Some(DefaultImpl {
17
- accounts_ident: format_ident!("StdComputeArea"),
18
17
  handler_ident: format_ident!("apply"),
19
18
  generator: generate_default_context,
20
19
  }),
@@ -24,27 +23,26 @@ pub(super) fn spec(_ctx: &CodegenContext) -> InstructionSpec<CodegenContext> {
24
23
  fn generate_default_context(
25
24
  ctx: &CodegenContext,
26
25
  spec: &InstructionSpec<CodegenContext>,
27
- ) -> TokenStream {
26
+ ) -> DefaultAccounts {
28
27
  let state_type = &ctx.state_type;
29
-
30
28
  let params_type = spec.params_type.as_ref().unwrap();
31
29
  let return_type = &spec.return_type;
32
- let default_impl = spec.default_impl.as_ref().unwrap();
33
-
34
- let default_accounts_ident = &default_impl.accounts_ident;
35
- let handler_ident = &default_impl.handler_ident;
30
+ let handler_ident = &spec.default_impl.as_ref().unwrap().handler_ident;
36
31
 
37
- quote! {
38
- #[derive(Accounts)]
39
- pub struct #default_accounts_ident<'info> {
40
- pub shape: Account<'info, #state_type>,
41
- }
42
-
43
- impl #default_accounts_ident<'_> {
44
- pub fn #handler_ident(ctx: &Context<Self>, _params: &#params_type) -> Result<#return_type> {
45
- let s = &ctx.accounts.shape;
46
- Ok(s.width * s.height)
32
+ DefaultAccounts {
33
+ struct_type: parse_quote! {
34
+ #[derive(Accounts)]
35
+ pub struct StdComputeArea<'info> {
36
+ pub shape: Account<'info, #state_type>,
37
+ }
38
+ },
39
+ impl_block: parse_quote! {
40
+ impl StdComputeArea<'_> {
41
+ pub fn #handler_ident(ctx: &Context<Self>, _params: &#params_type) -> Result<#return_type> {
42
+ let s = &ctx.accounts.shape;
43
+ Ok(s.width * s.height)
44
+ }
47
45
  }
48
- }
46
+ },
49
47
  }
50
48
  }
@@ -2,9 +2,9 @@
2
2
  //!
3
3
  //! Provided instruction with default handler: 2 * (width + height) (rectangle perimeter).
4
4
 
5
- use anchor_trait::{DefaultImpl, InstructionSpec};
6
- use proc_macro2::TokenStream;
5
+ use anchor_trait::{DefaultAccounts, DefaultImpl, InstructionSpec};
7
6
  use quote::{format_ident, quote};
7
+ use syn::parse_quote;
8
8
 
9
9
  use super::CodegenContext;
10
10
 
@@ -14,7 +14,6 @@ pub(super) fn spec(_ctx: &CodegenContext) -> InstructionSpec<CodegenContext> {
14
14
  return_type: quote!(u64),
15
15
  is_view: true,
16
16
  default_impl: Some(DefaultImpl {
17
- accounts_ident: format_ident!("StdComputePerimeter"),
18
17
  handler_ident: format_ident!("apply"),
19
18
  generator: generate_default_context,
20
19
  }),
@@ -24,27 +23,26 @@ pub(super) fn spec(_ctx: &CodegenContext) -> InstructionSpec<CodegenContext> {
24
23
  fn generate_default_context(
25
24
  ctx: &CodegenContext,
26
25
  spec: &InstructionSpec<CodegenContext>,
27
- ) -> TokenStream {
26
+ ) -> DefaultAccounts {
28
27
  let state_type = &ctx.state_type;
29
-
30
28
  let params_type = spec.params_type.as_ref().unwrap();
31
29
  let return_type = &spec.return_type;
32
- let default_impl = spec.default_impl.as_ref().unwrap();
33
-
34
- let default_accounts_ident = &default_impl.accounts_ident;
35
- let handler_ident = &default_impl.handler_ident;
30
+ let handler_ident = &spec.default_impl.as_ref().unwrap().handler_ident;
36
31
 
37
- quote! {
38
- #[derive(Accounts)]
39
- pub struct #default_accounts_ident<'info> {
40
- pub shape: Account<'info, #state_type>,
41
- }
42
-
43
- impl #default_accounts_ident<'_> {
44
- pub fn #handler_ident(ctx: &Context<Self>, _params: &#params_type) -> Result<#return_type> {
45
- let s = &ctx.accounts.shape;
46
- Ok(2 * (s.width + s.height))
32
+ DefaultAccounts {
33
+ struct_type: parse_quote! {
34
+ #[derive(Accounts)]
35
+ pub struct StdComputePerimeter<'info> {
36
+ pub shape: Account<'info, #state_type>,
37
+ }
38
+ },
39
+ impl_block: parse_quote! {
40
+ impl StdComputePerimeter<'_> {
41
+ pub fn #handler_ident(ctx: &Context<Self>, _params: &#params_type) -> Result<#return_type> {
42
+ let s = &ctx.accounts.shape;
43
+ Ok(2 * (s.width + s.height))
44
+ }
47
45
  }
48
- }
46
+ },
49
47
  }
50
48
  }
@@ -0,0 +1,19 @@
1
+ //! Code generator for the `get_dimension` instruction.
2
+ //!
3
+ //! Required instruction with params. Returns one dimension by index (0=width, 1=height).
4
+ //! Demonstrates a **required + view + params** instruction — every shape must implement
5
+ //! this since there is no sensible universal default for dimension indexing.
6
+
7
+ use anchor_trait::InstructionSpec;
8
+ use quote::quote;
9
+
10
+ use super::CodegenContext;
11
+
12
+ pub(super) fn spec() -> InstructionSpec<CodegenContext> {
13
+ InstructionSpec {
14
+ params_type: Some(quote!(DimensionParams)),
15
+ return_type: quote!(u64),
16
+ is_view: true,
17
+ default_impl: None, // Required — implementor MUST provide
18
+ }
19
+ }
@@ -2,9 +2,9 @@
2
2
  //!
3
3
  //! Provided instruction with no params. Default returns 2 (all shapes are 2D).
4
4
 
5
- use anchor_trait::{DefaultImpl, InstructionSpec};
6
- use proc_macro2::TokenStream;
5
+ use anchor_trait::{DefaultAccounts, DefaultImpl, InstructionSpec};
7
6
  use quote::{format_ident, quote};
7
+ use syn::parse_quote;
8
8
 
9
9
  use super::CodegenContext;
10
10
 
@@ -14,7 +14,6 @@ pub(super) fn spec(_ctx: &CodegenContext) -> InstructionSpec<CodegenContext> {
14
14
  return_type: quote!(u8),
15
15
  is_view: true,
16
16
  default_impl: Some(DefaultImpl {
17
- accounts_ident: format_ident!("StdGetDimensionCount"),
18
17
  handler_ident: format_ident!("apply"),
19
18
  generator: generate_default_context,
20
19
  }),
@@ -22,23 +21,26 @@ pub(super) fn spec(_ctx: &CodegenContext) -> InstructionSpec<CodegenContext> {
22
21
  }
23
22
 
24
23
  fn generate_default_context(
25
- _ctx: &CodegenContext,
24
+ ctx: &CodegenContext,
26
25
  spec: &InstructionSpec<CodegenContext>,
27
- ) -> TokenStream {
26
+ ) -> DefaultAccounts {
27
+ let state_type = &ctx.state_type;
28
28
  let return_type = &spec.return_type;
29
- let default_impl = spec.default_impl.as_ref().unwrap();
29
+ let handler_ident = &spec.default_impl.as_ref().unwrap().handler_ident;
30
30
 
31
- let default_accounts_ident = &default_impl.accounts_ident;
32
- let handler_ident = &default_impl.handler_ident;
33
-
34
- quote! {
35
- #[derive(Accounts)]
36
- pub struct #default_accounts_ident {}
37
-
38
- impl #default_accounts_ident {
39
- pub fn #handler_ident(_ctx: &Context<Self>) -> Result<#return_type> {
40
- Ok(2) // All shapes in this domain are 2D
31
+ DefaultAccounts {
32
+ struct_type: parse_quote! {
33
+ #[derive(Accounts)]
34
+ pub struct StdGetDimensionCount<'info> {
35
+ pub shape: Account<'info, #state_type>,
36
+ }
37
+ },
38
+ impl_block: parse_quote! {
39
+ impl StdGetDimensionCount<'_> {
40
+ pub fn #handler_ident(_ctx: &Context<Self>) -> Result<#return_type> {
41
+ Ok(2)
42
+ }
41
43
  }
42
- }
44
+ },
43
45
  }
44
46
  }
@@ -1,10 +1,14 @@
1
1
  //! Shapes instruction definitions and code generation.
2
2
 
3
+ mod clear;
3
4
  mod compute_area;
4
5
  mod compute_perimeter;
6
+ mod get_dimension;
5
7
  mod get_dimension_count;
6
8
  mod get_name;
7
9
  mod initialize;
10
+ mod reset;
11
+ mod scale;
8
12
 
9
13
  use anchor_trait::declare_instructions;
10
14
  use proc_macro2::TokenStream;
@@ -20,7 +24,11 @@ declare_instructions! {
20
24
 
21
25
  Initialize => initialize,
22
26
  GetName => get_name,
27
+ GetDimension => get_dimension,
28
+ Clear => clear,
23
29
  ComputeArea => compute_area(ctx),
24
30
  ComputePerimeter => compute_perimeter(ctx),
25
31
  GetDimensionCount => get_dimension_count(ctx),
32
+ Scale => scale(ctx),
33
+ Reset => reset(ctx),
26
34
  }
@@ -0,0 +1,50 @@
1
+ //! Code generator for the `reset` instruction.
2
+ //!
3
+ //! Provided instruction with no params. Default resets both dimensions to 1.
4
+ //! Demonstrates a **provided + mutable + no-params** instruction.
5
+
6
+ use anchor_trait::{DefaultAccounts, DefaultImpl, InstructionSpec};
7
+ use quote::{format_ident, quote};
8
+ use syn::parse_quote;
9
+
10
+ use super::CodegenContext;
11
+
12
+ pub(super) fn spec(_ctx: &CodegenContext) -> InstructionSpec<CodegenContext> {
13
+ InstructionSpec {
14
+ params_type: None,
15
+ return_type: quote!(()),
16
+ is_view: false,
17
+ default_impl: Some(DefaultImpl {
18
+ handler_ident: format_ident!("apply"),
19
+ generator: generate_default_context,
20
+ }),
21
+ }
22
+ }
23
+
24
+ fn generate_default_context(
25
+ ctx: &CodegenContext,
26
+ _spec: &InstructionSpec<CodegenContext>,
27
+ ) -> DefaultAccounts {
28
+ let state_type = &ctx.state_type;
29
+ let handler_ident = format_ident!("apply");
30
+
31
+ DefaultAccounts {
32
+ struct_type: parse_quote! {
33
+ #[derive(Accounts)]
34
+ pub struct StdReset<'info> {
35
+ #[account(mut)]
36
+ pub shape: Account<'info, #state_type>,
37
+ }
38
+ },
39
+ impl_block: parse_quote! {
40
+ impl StdReset<'_> {
41
+ pub fn #handler_ident(ctx: &mut Context<Self>) -> Result<()> {
42
+ let s = &mut ctx.accounts.shape;
43
+ s.width = 1;
44
+ s.height = 1;
45
+ Ok(())
46
+ }
47
+ }
48
+ },
49
+ }
50
+ }
@@ -0,0 +1,52 @@
1
+ //! Code generator for the `scale` instruction.
2
+ //!
3
+ //! Provided instruction with default handler: multiply both dimensions by a factor.
4
+ //! Demonstrates a **provided + mutable** instruction (the only combination not covered
5
+ //! by the other five instructions, which are all view or required).
6
+
7
+ use anchor_trait::{DefaultAccounts, DefaultImpl, InstructionSpec};
8
+ use quote::{format_ident, quote};
9
+ use syn::parse_quote;
10
+
11
+ use super::CodegenContext;
12
+
13
+ pub(super) fn spec(_ctx: &CodegenContext) -> InstructionSpec<CodegenContext> {
14
+ InstructionSpec {
15
+ params_type: Some(quote!(ScaleParams)),
16
+ return_type: quote!(()),
17
+ is_view: false,
18
+ default_impl: Some(DefaultImpl {
19
+ handler_ident: format_ident!("apply"),
20
+ generator: generate_default_context,
21
+ }),
22
+ }
23
+ }
24
+
25
+ fn generate_default_context(
26
+ ctx: &CodegenContext,
27
+ spec: &InstructionSpec<CodegenContext>,
28
+ ) -> DefaultAccounts {
29
+ let state_type = &ctx.state_type;
30
+ let params_type = spec.params_type.as_ref().unwrap();
31
+ let handler_ident = &spec.default_impl.as_ref().unwrap().handler_ident;
32
+
33
+ DefaultAccounts {
34
+ struct_type: parse_quote! {
35
+ #[derive(Accounts)]
36
+ pub struct StdScale<'info> {
37
+ #[account(mut)]
38
+ pub shape: Account<'info, #state_type>,
39
+ }
40
+ },
41
+ impl_block: parse_quote! {
42
+ impl StdScale<'_> {
43
+ pub fn #handler_ident(ctx: &mut Context<Self>, params: &#params_type) -> Result<()> {
44
+ let s = &mut ctx.accounts.shape;
45
+ s.width = s.width.saturating_mul(params.factor);
46
+ s.height = s.height.saturating_mul(params.factor);
47
+ Ok(())
48
+ }
49
+ }
50
+ },
51
+ }
52
+ }
@@ -3,30 +3,26 @@
3
3
  //! Provides `#[shapes]` and `#[shapes_instruction]` attribute macros
4
4
  //! demonstrating the anchor-trait instruction trait system.
5
5
 
6
+ mod audit;
6
7
  mod instructions;
7
8
  mod shapes;
9
+ mod state_types;
8
10
 
9
11
  use proc_macro::TokenStream;
10
12
 
11
13
  /// Program-level macro that auto-generates shape instruction entrypoints.
12
14
  ///
15
+ /// Generates `ShapeState` in the module prelude.
16
+ ///
13
17
  /// ## Usage
14
18
  ///
15
19
  /// ```ignore
16
- /// #[shapes_macros::shapes(state = ShapeState)]
20
+ /// #[shapes_macros::shapes]
17
21
  /// pub mod shapes_program {
18
- /// use super::*;
19
- ///
20
- /// // Required: must provide initialize (no default)
21
- /// pub fn initialize(ctx: Context<Initialize>, params: InitParams) -> Result<()> { ... }
22
- ///
23
- /// // Optional overrides for compute_area, compute_perimeter, get_dimension_count
22
+ /// // Required: must provide initialize, get_name, get_dimension, clear
23
+ /// // Optional: override compute_area, compute_perimeter, scale, reset, get_dimension_count
24
24
  /// }
25
25
  /// ```
26
- ///
27
- /// ## Attributes
28
- ///
29
- /// - `state = TypeName`: The program state account type (required)
30
26
  #[proc_macro_attribute]
31
27
  pub fn shapes(attr: TokenStream, item: TokenStream) -> TokenStream {
32
28
  shapes::expand(attr.into(), item.into())
@@ -34,6 +30,13 @@ pub fn shapes(attr: TokenStream, item: TokenStream) -> TokenStream {
34
30
  .into()
35
31
  }
36
32
 
33
+ #[proc_macro_attribute]
34
+ pub fn shapes_audit(attr: TokenStream, item: TokenStream) -> TokenStream {
35
+ audit::expand(attr.into(), item.into())
36
+ .unwrap_or_else(|err| err.to_compile_error())
37
+ .into()
38
+ }
39
+
37
40
  /// Marks a function as an override for a shapes instruction.
38
41
  ///
39
42
  /// ## Usage
@@ -2,55 +2,50 @@
2
2
  //!
3
3
  //! Flow: parse inputs and resolve domain types, then collect -> generate -> assemble.
4
4
 
5
- use crate::instructions::{CodegenContext, ShapesInstructionSet};
5
+ use crate::{
6
+ instructions::{CodegenContext, ShapesInstructionSet},
7
+ state_types,
8
+ };
6
9
  use anchor_trait::{generate_instructions, Assembly, InstructionOverrides, OverrideConfig};
7
- use darling::{ast::NestedMeta, FromMeta};
8
10
  use proc_macro2::TokenStream;
9
- use quote::quote;
10
- use syn::{ItemMod, Path};
11
-
12
- // ---------------------------------------------------------------------------
13
- // Attribute parsing
14
- // ---------------------------------------------------------------------------
15
-
16
- #[derive(FromMeta)]
17
- struct ShapesAttr {
18
- state: Path,
19
- }
11
+ use quote::{format_ident, quote};
12
+ use syn::ItemMod;
20
13
 
21
14
  const OVERRIDE_CONFIG: OverrideConfig = OverrideConfig {
22
15
  attr_name: "shapes_instruction",
23
16
  domain: "Shapes",
24
17
  };
25
18
 
26
- // ---------------------------------------------------------------------------
27
- // Entry point
28
- // ---------------------------------------------------------------------------
29
-
30
- pub fn expand(attr: TokenStream, item: TokenStream) -> syn::Result<TokenStream> {
31
- // Parse inputs
32
- let attr_args = NestedMeta::parse_meta_list(attr)?;
33
- let attrs = ShapesAttr::from_list(&attr_args)?;
19
+ pub fn expand(_attr: TokenStream, item: TokenStream) -> syn::Result<TokenStream> {
34
20
  let module = syn::parse2::<ItemMod>(item)?;
35
21
 
36
- let state = &attrs.state;
37
-
38
22
  // 1. Collect overrides
39
23
  let overrides = InstructionOverrides::collect(&module, OVERRIDE_CONFIG)?;
40
24
 
41
25
  // 2. Generate instructions
42
26
  let codegen_ctx = CodegenContext {
43
- state_type: quote!(#state),
27
+ state_type: quote!(ShapeState),
44
28
  };
45
29
  let instructions = generate_instructions::<ShapesInstructionSet>(&codegen_ctx, &overrides)?;
46
30
 
47
31
  // 3. Assemble output
32
+ let prelude = {
33
+ let shape_state = state_types::generate_shape_state();
34
+ quote! {
35
+ #shape_state
36
+ }
37
+ };
38
+ let extra_mod_attrs = quote! {
39
+ #[shapes_macros::shapes_audit]
40
+ };
41
+
48
42
  Ok(Assembly {
49
- prelude: TokenStream::new(),
43
+ prelude,
50
44
  overrides,
51
45
  instructions,
52
- extra_mod_attrs: quote!(#[program]),
46
+ extra_mod_attrs,
53
47
  source_mod: module,
48
+ extend_macro_name: Some(format_ident!("shapes_extend_accounts")),
54
49
  }
55
50
  .assemble())
56
51
  }
@@ -0,0 +1,14 @@
1
+ use proc_macro2::TokenStream;
2
+ use quote::quote;
3
+
4
+ pub fn generate_shape_state() -> TokenStream {
5
+ quote! {
6
+ #[account]
7
+ #[derive(InitSpace)]
8
+ pub struct ShapeState {
9
+ pub width: u64,
10
+ pub height: u64,
11
+ pub bump: u8,
12
+ }
13
+ }
14
+ }
@@ -28,3 +28,10 @@ unexpected_cfgs = { level = "allow", check-cfg = [
28
28
  [dependencies]
29
29
  anchor-lang = { workspace = true }
30
30
  shapes-macros = { workspace = true }
31
+
32
+ [dev-dependencies]
33
+ mollusk-svm = { workspace = true }
34
+ solana-account = { workspace = true }
35
+ solana-instruction = { workspace = true }
36
+ solana-program-error = { workspace = true }
37
+ solana-pubkey = { workspace = true }