#![no_std]
pub use jiminy_core::{abi, account, check, compat, event, instruction, interface, math, state, sysvar, time};
#[cfg(feature = "programs")]
pub use jiminy_core::programs;
#[cfg(feature = "log")]
pub use jiminy_core::log;
pub use jiminy_solana::{
authority, balance, compute, compose, cpi, crypto, introspect, oracle, token, twap,
};
#[cfg(feature = "programs")]
pub use jiminy_solana::upgrade;
pub mod amm {
pub use jiminy_finance::amm::*;
}
pub mod slippage {
pub use jiminy_finance::slippage::*;
}
pub mod lending {
pub use jiminy_lending::*;
}
pub mod staking {
pub use jiminy_staking::*;
}
pub mod vesting {
pub use jiminy_vesting::*;
}
pub mod multisig {
pub use jiminy_multisig::*;
}
pub mod distribute {
pub use jiminy_distribute::*;
}
pub use jiminy_core;
pub use jiminy_solana;
pub use jiminy_finance;
pub use jiminy_lending;
pub use jiminy_staking;
pub use jiminy_vesting;
pub use jiminy_multisig;
pub use jiminy_distribute;
pub use hopper_runtime;
pub use hopper_runtime::{ProgramError, AccountView, Address, ProgramResult};
pub mod prelude;
#[macro_export]
macro_rules! require {
($cond:expr, $err:expr $(,)?) => {
if !($cond) {
return Err($err.into());
}
};
}
#[macro_export]
macro_rules! require_keys_eq {
($a:expr, $b:expr, $err:expr $(,)?) => {
let __jiminy_a: &$crate::Address = &$a;
let __jiminy_b: &$crate::Address = &$b;
if __jiminy_a != __jiminy_b {
return Err($err.into());
}
};
}
#[macro_export]
macro_rules! require_keys_neq {
($a:expr, $b:expr, $err:expr $(,)?) => {
let __jiminy_a: &$crate::Address = &$a;
let __jiminy_b: &$crate::Address = &$b;
if __jiminy_a == __jiminy_b {
return Err($err.into());
}
};
}
#[macro_export]
macro_rules! require_accounts_ne {
($a:expr, $b:expr, $err:expr $(,)?) => {
if $a.address() == $b.address() {
return Err($err.into());
}
};
}
#[macro_export]
macro_rules! require_gte {
($a:expr, $b:expr, $err:expr $(,)?) => {
if $a < $b {
return Err($err.into());
}
};
}
#[macro_export]
macro_rules! require_gt {
($a:expr, $b:expr, $err:expr $(,)?) => {
if $a <= $b {
return Err($err.into());
}
};
}
#[macro_export]
macro_rules! require_lt {
($a:expr, $b:expr, $err:expr $(,)?) => {
if $a >= $b {
return Err($err.into());
}
};
}
#[macro_export]
macro_rules! require_lte {
($a:expr, $b:expr, $err:expr $(,)?) => {
if $a > $b {
return Err($err.into());
}
};
}
#[macro_export]
macro_rules! require_eq {
($a:expr, $b:expr, $err:expr $(,)?) => {
if $a != $b {
return Err($err.into());
}
};
}
#[macro_export]
macro_rules! require_neq {
($a:expr, $b:expr, $err:expr $(,)?) => {
if $a == $b {
return Err($err.into());
}
};
}
#[macro_export]
macro_rules! require_flag {
($byte:expr, $n:expr, $err:expr $(,)?) => {
if ($byte >> $n) & 1 == 0 {
return Err($err.into());
}
};
}
#[macro_export]
macro_rules! check_accounts_unique {
($a:expr, $b:expr) => {
if $a.address() == $b.address() {
return Err($crate::ProgramError::InvalidArgument);
}
};
($head:expr, $($tail:expr),+ $(,)?) => {
$( if $head.address() == $tail.address() {
return Err($crate::ProgramError::InvalidArgument);
} )+
$crate::check_accounts_unique!($($tail),+);
};
}
#[macro_export]
macro_rules! error_codes {
(
base = $base:expr;
$( $(#[$meta:meta])* $name:ident ),+ $(,)?
) => {
#[allow(non_upper_case_globals)]
pub mod errors {
$crate::error_codes!(@count $base; $( $(#[$meta])* $name ),+ );
}
$(
impl From<errors::$name> for $crate::ProgramError {
#[inline(always)]
fn from(_: errors::$name) -> Self {
$crate::ProgramError::Custom(errors::$name::CODE)
}
}
)+
};
(@count $code:expr; $(#[$meta:meta])* $name:ident) => {
$(#[$meta])*
pub struct $name;
impl $name { pub const CODE: u32 = $code; }
};
(@count $code:expr; $(#[$meta:meta])* $name:ident, $( $(#[$rmeta:meta])* $rest:ident ),+ ) => {
$(#[$meta])*
pub struct $name;
impl $name { pub const CODE: u32 = $code; }
$crate::error_codes!(@count $code + 1; $( $(#[$rmeta])* $rest ),+ );
};
}
#[macro_export]
macro_rules! instruction_dispatch {
(
$pid:expr, $accs:expr, $data:expr;
$( $tag:expr => $handler:expr ),+ $(,)?
) => {{
let mut ix = $crate::account::SliceCursor::new($data);
let tag = ix.read_u8()?;
match tag {
$( $tag => { let _ = &ix; $handler } )+
_ => Err($crate::ProgramError::InvalidInstructionData),
}
}};
}
#[macro_export]
macro_rules! impl_pod {
($($t:ty),+ $(,)?) => {
$( unsafe impl $crate::account::Pod for $t {} )+
};
}
#[macro_export]
macro_rules! assert_legacy_layout {
($ty:ty, $size:expr $(,)?) => {
$crate::assert_legacy_layout!(@inner $ty, $size, 8usize);
};
($ty:ty, size = $size:expr $(,)?) => {
$crate::assert_legacy_layout!(@inner $ty, $size, 8usize);
};
($ty:ty, size = $size:expr, max_align = $max_align:expr $(,)?) => {
$crate::assert_legacy_layout!(@inner $ty, $size, $max_align);
};
(@inner $ty:ty, $size:expr, $max_align:expr) => {
const _: fn() = {
fn __jiminy_assert_legacy_layout<T: $crate::account::Pod + $crate::account::FixedLayout>() {}
__jiminy_assert_legacy_layout::<$ty>
};
const _: () = assert!(
core::mem::size_of::<$ty>() == $size,
"legacy layout size_of does not match declared size"
);
const _: () = assert!(
<$ty as $crate::account::FixedLayout>::SIZE == $size,
"legacy layout FixedLayout::SIZE does not match declared size"
);
const _: () = assert!(
core::mem::align_of::<$ty>() <= $max_align,
"legacy layout alignment exceeds configured maximum"
);
};
}
#[macro_export]
macro_rules! init_account {
($payer:expr, $account:expr, $program_id:expr, $Layout:ty) => {{
let space = <$Layout>::LEN as u64;
let lamports = $crate::check::rent_exempt_min(<$Layout>::LEN);
$crate::hopper_runtime::system::instructions::CreateAccount {
from: $payer,
to: $account,
lamports,
space,
owner: $program_id,
}
.invoke()?;
let mut data = $account.try_borrow_mut()?;
$crate::account::zero_init(&mut data);
$crate::account::write_header(
&mut data,
<$Layout>::DISC,
<$Layout>::VERSION,
&<$Layout>::LAYOUT_ID,
)?;
Ok::<(), $crate::ProgramError>(())
}};
}
#[macro_export]
macro_rules! close_account {
($account:expr, $destination:expr) => {
$crate::account::safe_close_with_sentinel($account, $destination)
};
}
#[macro_export]
macro_rules! check_account {
($account:expr, $($constraint:tt)*) => {{
$crate::__check_account_inner!($account, $($constraint)*)
}};
}
#[doc(hidden)]
#[macro_export]
macro_rules! __check_account_inner {
($account:expr, ) => { Ok::<(), $crate::ProgramError>(()) };
($account:expr $(,)?) => { Ok::<(), $crate::ProgramError>(()) };
($account:expr, owner = $id:expr $(, $($rest:tt)*)?) => {{
$crate::check::check_owner($account, $id)?;
$crate::__check_account_inner!($account, $($($rest)*)?)
}};
($account:expr, writable $(, $($rest:tt)*)?) => {{
$crate::check::check_writable($account)?;
$crate::__check_account_inner!($account, $($($rest)*)?)
}};
($account:expr, signer $(, $($rest:tt)*)?) => {{
$crate::check::check_signer($account)?;
$crate::__check_account_inner!($account, $($($rest)*)?)
}};
($account:expr, disc = $d:expr $(, $($rest:tt)*)?) => {{
{
let data = $account.try_borrow()?;
$crate::check::check_discriminator(&data, $d)?;
}
$crate::__check_account_inner!($account, $($($rest)*)?)
}};
($account:expr, version >= $v:expr $(, $($rest:tt)*)?) => {{
{
let data = $account.try_borrow()?;
$crate::check::check_version(&data, $v)?;
}
$crate::__check_account_inner!($account, $($($rest)*)?)
}};
($account:expr, layout_id = $id:expr $(, $($rest:tt)*)?) => {{
{
let data = $account.try_borrow()?;
$crate::account::check_layout_id(&data, $id)?;
}
$crate::__check_account_inner!($account, $($($rest)*)?)
}};
($account:expr, size >= $n:expr $(, $($rest:tt)*)?) => {{
{
let data = $account.try_borrow()?;
$crate::check::check_size(&data, $n)?;
}
$crate::__check_account_inner!($account, $($($rest)*)?)
}};
}
#[macro_export]
macro_rules! check_account_strict {
($account:expr, owner = $owner:expr, disc = $disc:expr, layout_id = $lid:expr
$(, $($rest:tt)*)?) => {{
$crate::check::check_owner($account, $owner)?;
{
let data = $account.try_borrow()?;
$crate::check::check_discriminator(&data, $disc)?;
$crate::account::check_layout_id(&data, $lid)?;
}
$crate::__check_account_inner!($account, $($($rest)*)?)
}};
}
#[macro_export]
macro_rules! find_pda {
($program_id:expr, $($seed:expr),+ $(,)?) => {{
#[cfg(target_os = "solana")]
{
let seeds: &[&[u8]] = &[$($seed.as_ref()),+];
::hopper_runtime::Address::find_program_address(seeds, $program_id)
}
#[cfg(not(target_os = "solana"))]
{
let _ = ($program_id, $($seed),+);
unreachable!("find_pda! is only available on target solana")
}
}};
}
#[macro_export]
macro_rules! derive_pda {
($program_id:expr, $bump:expr, $($seed:expr),+ $(,)?) => {{
::hopper_runtime::Address::new_from_array($crate::check::pda::derive_address(
&[$($seed.as_ref()),+],
Some($bump),
($program_id).as_array(),
))
}};
}
#[macro_export]
macro_rules! derive_pda_const {
($program_id:expr, $bump:expr, $($seed:expr),+ $(,)?) => {
::hopper_runtime::Address::new_from_array($crate::check::pda::derive_address_const(
&[$(&$seed),+],
Some($bump),
&$program_id,
))
};
}
#[macro_export]
macro_rules! require_pda {
($account:expr, $program_id:expr, $($seed:expr),+ $(,)?) => {{
let seeds: &[&[u8]] = &[$($seed.as_ref()),+];
$crate::check::assert_pda($account, seeds, $program_id)
}};
}