diff --git a/CHANGELOG.md b/CHANGELOG.md index 86d1b77dec..b942a01c8c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -31,6 +31,7 @@ The minor version will be incremented upon a breaking change and the patch versi ### Fixes +* lang: Fix parsing for bytes literals in the IDL. ([#2261](https://github.com/coral-xyz/anchor/pull/2261)) * lang: Fix IDL `seed` generation for byte string literals. ([#2125](https://github.com/coral-xyz/anchor/pull/2125)) * ts: Update seeds inference to allow nested user defined structs within the seeds ([#2198](https://github.com/coral-xyz/anchor/pull/2198)) diff --git a/lang/syn/src/idl/file.rs b/lang/syn/src/idl/file.rs index f10431b0cd..e1bcc41587 100644 --- a/lang/syn/src/idl/file.rs +++ b/lang/syn/src/idl/file.rs @@ -8,6 +8,10 @@ use heck::MixedCase; use quote::ToTokens; use std::collections::{HashMap, HashSet}; use std::path::Path; +use syn::{ + Expr, ExprLit, ItemConst, + Lit::{Byte, ByteStr}, +}; const DERIVE_NAME: &str = "Accounts"; // TODO: share this with `anchor_lang` crate. @@ -281,11 +285,7 @@ pub fn parse( let constants = parse_consts(&ctx) .iter() - .map(|c: &&syn::ItemConst| IdlConst { - name: c.ident.to_string(), - ty: c.ty.to_token_stream().to_string().parse().unwrap(), - value: c.expr.to_token_stream().to_string().parse().unwrap(), - }) + .map(|c: &&syn::ItemConst| to_idl_const(c)) .collect::>(); Ok(Some(Idl { @@ -615,6 +615,37 @@ fn to_idl_type(ctx: &CrateContext, ty: &syn::Type) -> IdlType { tts_string.parse().unwrap() } +// TODO parse other issues +fn to_idl_const(item: &ItemConst) -> IdlConst { + let name = item.ident.to_string(); + + if let Expr::Lit(ExprLit { lit, .. }) = &*item.expr { + match lit { + ByteStr(lit_byte_str) => { + return IdlConst { + name, + ty: IdlType::Bytes, + value: format!("{:?}", lit_byte_str.value()), + } + } + Byte(lit_byte) => { + return IdlConst { + name, + ty: IdlType::U8, + value: lit_byte.value().to_string(), + } + } + _ => (), + } + } + + IdlConst { + name, + ty: item.ty.to_token_stream().to_string().parse().unwrap(), + value: item.expr.to_token_stream().to_string().parse().unwrap(), + } +} + fn idl_accounts( ctx: &CrateContext, accounts: &AccountsStruct, diff --git a/tests/misc/programs/misc/src/lib.rs b/tests/misc/programs/misc/src/lib.rs index 7afe0a85c2..d6b646b2a0 100644 --- a/tests/misc/programs/misc/src/lib.rs +++ b/tests/misc/programs/misc/src/lib.rs @@ -17,6 +17,10 @@ declare_id!("3TEqcc8xhrhdspwbvoamUJe2borm4Nr72JxL66k6rgrh"); pub const BASE: u128 = 1_000_000; #[constant] pub const DECIMALS: u8 = 6; +#[constant] +pub const BYTES_STR: &[u8] = b"test"; +#[constant] +pub const BYTE_STR: u8 = b't'; pub const NO_IDL: u16 = 55; #[program] diff --git a/tests/misc/tests/misc/misc.ts b/tests/misc/tests/misc/misc.ts index 1d95feaf56..effce1b9d0 100644 --- a/tests/misc/tests/misc/misc.ts +++ b/tests/misc/tests/misc/misc.ts @@ -1105,6 +1105,25 @@ describe("misc", () => { ); }); + it("Should include BYTES_STR const in IDL", async () => { + assert.isDefined( + miscIdl.constants.find( + (c) => + c.name === "BYTES_STR" && + c.type === "bytes" && + c.value === "[116, 101, 115, 116]" + ) + ); + }); + + it("Should include BYTE_STR const in IDL", async () => { + assert.isDefined( + miscIdl.constants.find( + (c) => c.name === "BYTE_STR" && c.type === "u8" && c.value === "116" + ) + ); + }); + it("Should not include NO_IDL const in IDL", async () => { assert.isUndefined(miscIdl.constants.find((c) => c.name === "NO_IDL")); });