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.
cargo install solores
to install the CLI binary.
Lets say you had the following shank generated IDL, my_token_idl.json
:
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:
```rust use mytokeninterface::{TransferAccounts, TransferArgs, transferinvokesigned}; use solanaprogram::{accountinfo::{AccountInfo, nextaccountinfo}, entrypoint::ProgramResult, program::invoke, pubkey::Pubkey};
pub fn process(programid: &Pubkey, accounts: &[AccountInfo], input: &[u8]) -> ProgramResult { let accountinfoiter = &mut accounts.iter(); let src = nextaccountinfo(accountinfoiter)?; let dest = nextaccountinfo(accountinfo_iter)?;
transfer_invoke_signed(
&TransferAccounts { src, dest },
TransferArgs { amount: 1_000u64 },
&[&[&[0u8]]],
)
} ```
or in a client-side app:
```rust use mytokeninterface::{TransferKeys, TransferArgs, transfer_ix};
pub fn dosomethingwith_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.
The usage for anchor IDLs is essentially the same as Shank IDL's. The crate will also export all accounts' discriminant as consts.
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:
```rust use mytokeninterface::{TransferArgs, TransferKeys, ID}; use solana_program::pubkey::Pubkey;
struct MyTransferKeys { pub src: Pubkey, }
impl From<&MyTransferKeys> for TransferKeys { fn from(mytransferkeys: MyTransferKeys) -> Self { let (mypdadest, bump) = Pubkey::findprogramaddress( &[&[0u8]], &ID, ); Self { src: mytransferkeys.src, dest: mypda_dest, } } }
struct MyTransferArgs {};
impl From
// Now you can do: // let ix = transferix( // &MyTransferKeys { src: mypubkey }, // MyTransferArgs {}, // ); ```
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.
Please check the repo's issues list for more.
pub enum MyEnum { MyVariant(field1: u8, field2: u64) }