solores 0.1.3

Solana IDL to Rust client / CPI interface generator
solores-0.1.3 is not a library.
Visit the last successful build: solores-0.7.0

solores

Solana IDL to Rust client / CPI interface generator.

solita, light of my life, fire of my loins

This software is still in its early stages of development. USE AT YOUR OWN RISK.

Contents

Supported IDL Formats

Installation

cargo install solores to install the CLI binary.

Examples

Shank IDL

Lets say you had the following shank generated IDL, my_token_idl.json:

{
  "name": "my_token",
  "instructions": [
    {
      "name": "transfer",
      "accounts": [
        {
          "name": "src",
          "isMut": true,
          "isSigner": true,
        },
        {
          "name": "dest",
          "isMut": true,
          "isSigner": false,
        },
      ],
      "args": [
        {
          "name": "transferArgs",
          "type": {
            "defined": "TransferArgs"
          }
        }
      ],
      "discriminant": {
        "type": "u8",
        "value": 0
      }
    }
  ],
  "types": [
    {
      "name": "TransferArgs",
      "type": {
        "kind": "struct",
        "fields": [
          {
            "name": "amount",
            "type": "u64"
          }
        ]
      }
    }
  ]
}

Running solores my_token_idl.json should generate a my_token_interface rust crate that allows you to use it in an on-chain program as so:

use my_token_interface::{TransferAccounts, TransferArgs, transfer_invoke_signed};
use solana_program::{account_info::{AccountInfo, next_account_info}, entrypoint::ProgramResult, program::invoke, pubkey::Pubkey};

pub fn process(program_id: &Pubkey, accounts: &[AccountInfo], input: &[u8]) -> ProgramResult {
    let account_info_iter = &mut accounts.iter();
    let src = next_account_info(account_info_iter)?;
    let dest = next_account_info(account_info_iter)?;

    transfer_invoke_signed(
        &TransferAccounts { src, dest },
        TransferArgs { amount: 1_000u64 },
        &[&[&[0u8]]],
    )
}

or in a client-side app:

use my_token_interface::{TransferKeys, TransferArgs, transfer_ix};

pub fn do_something_with_instruction() -> std::io::Result<()> {
    ...

    let transfer_accounts = TransferKeys {
        src: some_pubkey,
        dest: another_pubkey,
    };
    let transfer_ix_args = TransferArgs { amount: 1_000u64 };
    let ix = transfer_ix(&transfer_accounts, transfer_ix_args)?;

    ...
}

The crate will also export the instructions' discriminant as consts, and any error types defined in the IDL as an enum convertible to/from u32.

Anchor IDL

The usage for anchor IDLs is essentially the same as Shank IDL's. The crate will also export all accounts' discriminant as consts.

Features

Instruction Function Generics

The generated *_ix() function parameters are genericized over any type that impls Into<*Keys> for the first arg and any type that impls Into<*Args> for the second arg. This allows users to easily implement, for example, account structs that compute/retrieve known pubkeys (like PDAs) at runtime:

use my_token_interface::{TransferArgs, TransferKeys, ID};
use solana_program::pubkey::Pubkey;

struct MyTransferKeys {
    pub src: Pubkey,
}

impl From<&MyTransferKeys> for TransferKeys {
    fn from(my_transfer_keys: MyTransferKeys) -> Self {
        let (my_pda_dest, _bump) = Pubkey::find_program_address(
            &[&[0u8]],
            &ID,
        );
        Self {
          src: my_transfer_keys.src,
          dest: my_pda_dest,
        }
    }
}

struct MyTransferArgs {};

impl From<MyTransferArgs> for TransferArgs {
    fn from(_unused: MyTransferArgs) -> Self {
        Self {
            amount: 1000u64,
        }
    }
}

//  Now you can do:
//  let ix = transfer_ix(
//      &MyTransferKeys { src: my_pubkey },
//      MyTransferArgs {},
//  );

Comparison to similar libs

anchor-gen

Compared to anchor-gen, solores:

  • Has no dependency on anchor. The generated crate's dependencies are borsh + solana-program, and also thiserror + num-derive + num-traits if the idl contains error enum definitions.

  • Produces (almost) human-readable rust code in a new, separate crate instead of using a proc-macro.

  • Exposes lower-level constructs such as functions for creating the solana_program::instruction::Instruction struct to allow for greater customizability.

Known Missing Features

Please check the repo's issues list for more.

Anchor

  • Does not handle account namespaces
  • Does not handle the state instruction namespace