Skip to content

Commit

Permalink
Include kinobi IDL (#84)
Browse files Browse the repository at this point in the history
* write idl/asset-program.kinobi.json

* add support for kinobi idls

* use include_kinobi_idl instead of include_idl

* remove unused deps

* Fix lint

* Add include setting to upload action

* Add kinobi idl

---------

Co-authored-by: febo <[email protected]>
  • Loading branch information
ngundotra and febo authored Oct 11, 2024
1 parent c68f221 commit 67a4679
Show file tree
Hide file tree
Showing 8 changed files with 87 additions and 21 deletions.
1 change: 1 addition & 0 deletions .github/workflows/build-programs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -72,4 +72,5 @@ jobs:
name: program-builds
# First wildcard ensures exported paths are consistently under the programs folder.
path: ./program*/.bin/*.so
include-hidden-files: true
if-no-files-found: error
3 changes: 3 additions & 0 deletions configs/kinobi-asset.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ const anchorIdl = require("@kinobi-so/nodes-from-anchor");
const jsRenderer = require("@kinobi-so/renderers-js-umi");
const rustRenderer = require("@kinobi-so/renderers-rust");
const k = require("kinobi");
const { writeFileSync } = require("fs");

// Paths.
const path = require("path");
Expand Down Expand Up @@ -627,3 +628,5 @@ kinobi.accept(
}
)
);

writeFileSync(path.join(idlDir, "asset-program.kinobi.json"), kinobi.getJson());
1 change: 1 addition & 0 deletions idls/asset-program.kinobi.json

Large diffs are not rendered by default.

24 changes: 15 additions & 9 deletions include-idl-cli/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
use std::path::PathBuf;

use goblin::error::Result;
use include_idl::parse_idl_from_program_binary;
// use goblin::error::Result;
use include_idl::parse::{parse_idl_from_program_binary, IdlType};

use clap::{Parser, Subcommand};
use clap::{Error, Parser, Subcommand};

#[derive(Parser)]
#[command(version, about, long_about = None)]
Expand All @@ -17,19 +17,25 @@ enum Commands {
Parse {
/// Read IDL from a solana program binary
path: PathBuf,
idl_type: IdlType,
},
}

pub fn main() -> Result<()> {
// This example uses ArgEnum, so this might not be necessary.

pub fn main() -> Result<(), Error> {
let cli = Cli::parse();

match &cli.command {
Some(Commands::Parse { path }) => {
Some(Commands::Parse { path, idl_type }) => {
let buffer = std::fs::read(path).expect("Could not read file.");
let idl = parse_idl_from_program_binary(&buffer)?;
println!(" Program IDL");
println!("============================");
println!("{}", idl);
if let Ok(idl) = parse_idl_from_program_binary(&buffer, idl_type.clone()) {
println!(" Program IDL");
println!("============================");
println!("{}", idl);
} else {
println!("Could not find {:?} IDL in program binary", idl_type);
}
}
None => {}
}
Expand Down
18 changes: 15 additions & 3 deletions include-idl/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
#[cfg(feature = "parse")]
mod parse;
#[cfg(feature = "parse")]
pub use parse::parse_idl_from_program_binary;
pub mod parse;

#[cfg(feature = "shrink")]
mod shrink;

#[cfg(feature = "shrink")]
pub use shrink::compress_idl;

Expand All @@ -20,3 +19,16 @@ macro_rules! include_idl {
pub static IDL_BYTES: &[u8] = include_bytes!($s);
};
}

#[macro_export]
macro_rules! include_kinobi_idl {
($s:expr) => {
#[cfg_attr(
any(target_arch = "sbf", target_arch = "bpf"),
link_section = ".kinobi.idl"
)]
#[allow(dead_code)]
#[no_mangle]
pub static KINOBI_IDL_BYTES: &[u8] = include_bytes!($s);
};
}
48 changes: 43 additions & 5 deletions include-idl/src/parse.rs
Original file line number Diff line number Diff line change
@@ -1,17 +1,55 @@
#[cfg(feature = "parse")]
use {
flate2::bufread::ZlibDecoder, goblin::elf::Elf, goblin::error::Result, serde_json::Value,
std::io::Read,
flate2::bufread::ZlibDecoder, goblin::elf::Elf, serde_json::Value, std::fmt, std::io::Read,
std::str::FromStr,
};

#[cfg(feature = "parse")]
pub fn parse_idl_from_program_binary(buffer: &[u8]) -> Result<Value> {
#[derive(Clone, Debug)]
pub enum IdlType {
Anchor,
Kinobi,
}

impl fmt::Display for IdlType {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
IdlType::Anchor => write!(f, "Anchor"),
IdlType::Kinobi => write!(f, "Kinobi"),
}
}
}

impl FromStr for IdlType {
type Err = &'static str;

fn from_str(s: &str) -> Result<Self, &'static str> {
match s.to_lowercase().as_str() {
"anchor" => Ok(IdlType::Anchor),
"kinobi" => Ok(IdlType::Kinobi),
_ => Err("Invalid IDL type"),
}
}
}

fn get_section_name(idl_type: IdlType) -> String {
match idl_type {
IdlType::Anchor => ".solana.idl".to_string(),
IdlType::Kinobi => ".kinobi.idl".to_string(),
}
}

pub fn parse_idl_from_program_binary(
buffer: &[u8],
idl_type: IdlType,
) -> goblin::error::Result<Value> {
let elf = Elf::parse(buffer)?;

let section_name = get_section_name(idl_type);

// Iterate over section headers and print information
for sh in &elf.section_headers {
let name = elf.shdr_strtab.get_at(sh.sh_name).unwrap_or("<invalid>");
if name == ".solana.idl" {
if name == section_name {
// Get offset of .solana.idl section data
let offset = sh.sh_offset as usize;

Expand Down
9 changes: 7 additions & 2 deletions programs/asset/program/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,17 @@ fn main() {
.output()
.expect("Failed to run shank");

let _output = Command::new("pnpm")
.arg("generate:clients")
.output()
.expect("Failed to create the kinobi IDLs");

// Get the IDL path
let idl_path = PathBuf::from("../../../idls").join("asset_program.json");
let idl_path = PathBuf::from("../../../idls").join("asset-program.kinobi.json");

// Concat output path of compressed IDL
let out_dir = env::var("OUT_DIR").unwrap();
let dest_path = PathBuf::from(out_dir).join("idl.json.zip");
let dest_path = PathBuf::from(out_dir).join("kinobi.idl.zip");

compress_idl(&idl_path, &dest_path);
}
4 changes: 2 additions & 2 deletions programs/asset/program/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,13 @@ pub mod utils;
pub use solana_program;

#[cfg(not(feature = "no-entrypoint"))]
use include_idl::include_idl;
use include_idl::include_kinobi_idl;

#[cfg(not(feature = "no-entrypoint"))]
use solana_security_txt::security_txt;

#[cfg(not(feature = "no-entrypoint"))]
include_idl!(concat!(env!("OUT_DIR"), "/idl.json.zip"));
include_kinobi_idl!(concat!(env!("OUT_DIR"), "/kinobi.idl.zip"));

#[cfg(not(feature = "no-entrypoint"))]
security_txt! {
Expand Down

0 comments on commit 67a4679

Please sign in to comment.