Browse Source

lang: Add `pubkey` macro for declaring `Pubkey` const values (#3021)

Michal Nazarewicz 1 year ago
parent
commit
81c2519a9b
5 changed files with 58 additions and 1 deletions
  1. 1 0
      CHANGELOG.md
  2. 19 0
      lang/attribute/account/src/id.rs
  3. 9 0
      lang/attribute/account/src/lib.rs
  4. 1 1
      lang/src/lib.rs
  5. 28 0
      lang/tests/macros.rs

+ 1 - 0
CHANGELOG.md

@@ -25,6 +25,7 @@ The minor version will be incremented upon a breaking change and the patch versi
 - lang: Support legacy IDLs with `declare_program!` ([#2997](https://github.com/coral-xyz/anchor/pull/2997)).
 - cli: Add `idl convert` command ([#3009](https://github.com/coral-xyz/anchor/pull/3009)).
 - cli: Add `idl type` command ([#3017](https://github.com/coral-xyz/anchor/pull/3017)).
+- lang: Add `anchor_lang::pubkey` macro for declaring `Pubkey` const values ([#3021](https://github.com/coral-xyz/anchor/pull/3021)).
 - cli: Sync program ids on the initial build ([#3023](https://github.com/coral-xyz/anchor/pull/3023)).
 
 ### Fixes

+ 19 - 0
lang/attribute/account/src/id.rs

@@ -94,6 +94,25 @@ fn deprecated_id_to_tokens(
     });
 }
 
+pub struct Pubkey(proc_macro2::TokenStream);
+
+impl Parse for Pubkey {
+    fn parse(input: ParseStream) -> Result<Self> {
+        parse_id(
+            input,
+            quote! { anchor_lang::solana_program::pubkey::Pubkey },
+        )
+        .map(Self)
+    }
+}
+
+impl ToTokens for Pubkey {
+    fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) {
+        let id = &self.0;
+        tokens.extend(quote! {#id})
+    }
+}
+
 pub struct Id(proc_macro2::TokenStream);
 
 impl Parse for Id {

+ 9 - 0
lang/attribute/account/src/lib.rs

@@ -424,6 +424,15 @@ pub fn zero_copy(
     proc_macro::TokenStream::from(ret)
 }
 
+/// Convenience macro to define a static public key.
+///
+/// Input: a single literal base58 string representation of a Pubkey.
+#[proc_macro]
+pub fn pubkey(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
+    let pk = parse_macro_input!(input as id::Pubkey);
+    proc_macro::TokenStream::from(quote! {#pk})
+}
+
 /// Defines the program's ID. This should be used at the root of all Anchor
 /// based programs.
 #[proc_macro]

+ 1 - 1
lang/src/lib.rs

@@ -48,7 +48,7 @@ pub mod system_program;
 mod vec;
 pub use crate::bpf_upgradeable_state::*;
 pub use anchor_attribute_access_control::access_control;
-pub use anchor_attribute_account::{account, declare_id, zero_copy};
+pub use anchor_attribute_account::{account, declare_id, pubkey, zero_copy};
 pub use anchor_attribute_constant::constant;
 pub use anchor_attribute_error::*;
 pub use anchor_attribute_event::{emit, event};

+ 28 - 0
lang/tests/macros.rs

@@ -0,0 +1,28 @@
+use core::str::FromStr;
+
+use anchor_lang::solana_program::pubkey::Pubkey;
+
+mod id {
+    anchor_lang::declare_id!("Fg6PaFpoGXkYsidMpWTK6W2BeZ7FEfcYkg476zPFsLnS");
+}
+
+#[test]
+fn test_declare_id() {
+    let good = Pubkey::from_str("Fg6PaFpoGXkYsidMpWTK6W2BeZ7FEfcYkg476zPFsLnS").unwrap();
+    let bad = Pubkey::from_str("A7yUYJNEVYRLE4QWsnc9rE9JRsm7DfqEmLscQVwkffAk").unwrap();
+    assert_eq!(good, id::ID);
+    assert_eq!(good, id::id());
+    assert!(id::check_id(&good));
+    assert!(!id::check_id(&bad));
+}
+
+mod pk {
+    pub(super) const PUBKEY: anchor_lang::solana_program::pubkey::Pubkey =
+        anchor_lang::pubkey!("A7yUYJNEVYRLE4QWsnc9rE9JRsm7DfqEmLscQVwkffAk");
+}
+
+#[test]
+fn test_pubkey() {
+    let want = Pubkey::from_str("A7yUYJNEVYRLE4QWsnc9rE9JRsm7DfqEmLscQVwkffAk");
+    assert_eq!(want.unwrap(), pk::PUBKEY);
+}