1#![no_std]
105#![deny(unsafe_op_in_unsafe_fn)]
106
107#[cfg(any(
108 all(feature = "hopper-native-backend", feature = "legacy-pinocchio-compat"),
109 all(feature = "hopper-native-backend", feature = "solana-program-backend"),
110 all(
111 feature = "legacy-pinocchio-compat",
112 feature = "solana-program-backend"
113 ),
114))]
115compile_error!("Enable exactly one Hopper backend: hopper-native-backend, legacy-pinocchio-compat, or solana-program-backend.");
116
117#[doc(hidden)]
120pub mod __macro_support;
121pub mod guards;
122pub mod pda;
123pub mod prelude;
124pub mod receipts;
125
126pub use hopper_associated_token;
128pub use hopper_core;
129pub use hopper_runtime;
130pub use hopper_schema;
131pub use hopper_solana;
132pub use hopper_system;
133pub use hopper_token;
134pub use hopper_token_2022;
135
136pub mod account {
143 pub use hopper_core::abi::{
144 Authority, Mint, Token, TokenAccount, TypedAddress, UntypedAddress,
145 };
146 pub use hopper_core::accounts::{
147 HopperAccount, HopperAccounts, HopperCtx, HopperIx, ProgramAccount, ProgramRef,
148 SegmentedAccount, SignerAccount, ValidateAccount,
149 };
150 pub use hopper_runtime::{
151 Account, AccountView, HopperSigner as Signer, InitAccount, Interface, InterfaceAccount,
152 InterfaceAccountLayout, InterfaceAccountResolve, InterfaceSpec, Program, ProgramId,
153 SystemAccount, SystemId, UncheckedAccount,
154 };
155
156 pub type System = SystemId;
158}
159
160pub mod context {
162 pub use hopper_core::accounts::{hopper_entry, HopperAccounts, HopperCtx, HopperIx};
163 pub use hopper_runtime::Context;
164}
165
166pub mod cpi {
168 pub use hopper_core::cpi::*;
169 pub use hopper_runtime::cpi::{
170 invoke, invoke_signed, invoke_signed_unchecked, invoke_signed_with_bounds,
171 invoke_unchecked, invoke_with_bounds, set_return_data, MAX_CPI_ACCOUNTS, MAX_RETURN_DATA,
172 MAX_STATIC_CPI_ACCOUNTS,
173 };
174 pub use hopper_runtime::{CpiAccount, InstructionAccount, InstructionView, Seed, Signer};
175}
176
177#[allow(unused_imports)]
179pub mod system {
180 pub use hopper_system::instructions::*;
181 pub use hopper_system::SYSTEM_PROGRAM_ID;
182 pub use hopper_system::*;
183}
184
185#[allow(ambiguous_glob_reexports, unused_imports)]
187pub mod token {
188 pub use hopper_runtime::token::*;
189 pub use hopper_solana::interface::{
190 interface_transfer_checked, interface_transfer_checked_signed, InterfaceMint,
191 InterfaceTokenAccount, TokenProgramKind,
192 };
193 pub use hopper_token::instructions::*;
194 pub use hopper_token::TOKEN_PROGRAM_ID;
195 pub use hopper_token::*;
196}
197
198#[allow(ambiguous_glob_reexports, unused_imports)]
200pub mod token_2022 {
201 pub use hopper_runtime::token_2022_ext::*;
202 pub use hopper_token_2022::instructions::*;
203 pub use hopper_token_2022::TOKEN_2022_PROGRAM_ID;
204 pub use hopper_token_2022::*;
205}
206
207#[allow(unused_imports)]
209pub mod associated_token {
210 pub use hopper_associated_token::instructions::*;
211 pub use hopper_associated_token::ATA_PROGRAM_ID;
212 pub use hopper_associated_token::*;
213}
214
215pub mod memo {
217 pub use hopper_memo::*;
218}
219
220pub mod events {
222 pub use crate::receipts::{emit_receipt, emit_tagged_receipt, emit_typed_receipt, Receipt};
223 #[cfg(feature = "cpi")]
224 pub use hopper_core::event::emit_event_cpi;
225 pub use hopper_core::event::{emit_event, emit_event_tagged, emit_slices};
226 pub use hopper_runtime::{hopper_emit_cpi, hopper_log, msg};
227}
228
229pub mod layout {
231 pub use hopper_core::abi::{FingerprintTransition, LayoutFingerprint, WireType};
232 pub use hopper_core::account::{
233 check_header, read_discriminator, read_header_flags, read_layout_id, read_version,
234 write_header, AccountHeader, AccountReader, FixedLayout, HEADER_FORMAT, HEADER_LEN,
235 };
236 pub use hopper_core::field_map::{FieldInfo, FieldMap};
237 pub use hopper_runtime::layout::{init_header, HopperHeader, LayoutContract, LayoutInfo};
238 pub use hopper_runtime::{AccountLayout, Pod, WireLayout, ZeroCopy};
239}
240
241pub mod segment {
243 pub use hopper_core::account::segment_role::{
244 SegmentRole, SEG_ROLE_AUDIT, SEG_ROLE_CACHE, SEG_ROLE_CORE, SEG_ROLE_EXTENSION,
245 SEG_ROLE_INDEX, SEG_ROLE_JOURNAL, SEG_ROLE_SHARD,
246 };
247 pub use hopper_core::account::{
248 segment_id, SegmentDescriptor, SegmentEntry, SegmentId, SegmentRegistry,
249 SegmentRegistryMut, SegmentSlice, SegmentSliceMut, SegmentTable, SegmentTableMut,
250 MAX_REGISTRY_SEGMENTS, MAX_SEGMENTS, REGISTRY_HEADER_SIZE, REGISTRY_OFFSET,
251 SEGMENT_DESC_SIZE, SEGMENT_ENTRY_SIZE, SEG_FLAG_DYNAMIC, SEG_FLAG_FROZEN, SEG_FLAG_LOCKED,
252 };
253 pub use hopper_core::segment_map::{assert_segment_field_alignment, SegmentMap, StaticSegment};
254 pub use hopper_runtime::{
255 AccessKind, Ref, RefMut, SegRef, SegRefMut, Segment, SegmentBorrow, SegmentBorrowGuard,
256 SegmentBorrowRegistry, SegmentLease, TypedSegment,
257 };
258}
259
260pub mod receipt {
262 pub use crate::receipts::{emit_receipt, emit_tagged_receipt, emit_typed_receipt, Receipt};
263 #[cfg(feature = "receipt")]
264 pub use hopper_core::receipt::*;
265}
266
267pub mod migration {
269 #[cfg(feature = "migrate")]
270 pub use hopper_core::migrate::*;
271 pub use hopper_runtime::{apply_pending_migrations, LayoutMigration, MigrationEdge};
272}
273
274pub mod interface {
276 pub use hopper_runtime::{
277 ForeignLens, ForeignManifest, Interface, InterfaceAccount, InterfaceAccountLayout,
278 InterfaceAccountResolve, InterfaceSpec, TransparentAddress,
279 };
280 pub use hopper_solana::interface::*;
281}
282
283pub mod schema {
285 pub use hopper_schema::*;
286}
287
288pub mod policy {
290 #[cfg(feature = "policy")]
291 pub use hopper_core::policy::*;
292 pub use hopper_runtime::{HopperInstructionPolicy, HopperProgramPolicy};
293}
294
295#[allow(ambiguous_glob_reexports, unused_imports)]
301pub mod systems {
302 pub use crate::interface::*;
303 pub use crate::layout::*;
304 pub use crate::migration::*;
305 pub use crate::policy::*;
306 pub use crate::receipt::*;
307 pub use crate::schema::*;
308 pub use crate::segment::*;
309 pub use crate::{interface, layout, migration, policy, receipt, schema, segment};
310
311 pub use hopper_core::account::{
312 overlay, overlay_mut, read_dynamic_u16, read_dynamic_u32, read_dynamic_u8, safe_close,
313 safe_close_with_sentinel, safe_realloc, write_dynamic_u16, write_dynamic_u32,
314 write_dynamic_u8, DynamicView, DynamicViewMut, ReallocGuard, VerifiedAccount,
315 VerifiedAccountMut, CLOSE_SENTINEL,
316 };
317 pub use hopper_core::check::{find_and_verify_pda, rent_exempt_min};
318 pub use hopper_core::prelude_advanced::*;
319 pub use hopper_core::prelude_core::*;
320 pub use hopper_runtime::{
321 fast_entrypoint, hopper_entrypoint, hopper_fast_entrypoint, hopper_lazy_entrypoint,
322 lazy_entrypoint, no_allocator, nostd_panic_handler, program_entrypoint, BoundedString,
323 BoundedVec, CpiAccount, HopperString, HopperVec, InstructionAccount, InstructionView, Seed,
324 TailCodec, TailElement,
325 };
326
327 pub use crate::{
328 const_assert_pod, hopper_accounts, hopper_assert_compatible, hopper_assert_fingerprint,
329 hopper_check, hopper_close, hopper_dynamic_fields, hopper_dynamic_tail, hopper_error,
330 hopper_init, hopper_interface, hopper_invariant, hopper_layout, hopper_load,
331 hopper_manifest, hopper_register_discs, hopper_require, hopper_segment, hopper_validate,
332 hopper_verify_pda, hopper_virtual, layout_migrations,
333 };
334
335 #[cfg(feature = "proc-macros")]
336 pub use crate::{args, declare_program, dynamic, migrate, pod, state};
337}
338
339#[cfg(feature = "finance")]
341pub mod finance {
342 pub use hopper_finance::*;
343}
344
345#[cfg(feature = "lending")]
347pub mod lending {
348 pub use hopper_lending::*;
349}
350
351#[cfg(feature = "staking")]
353pub mod staking {
354 pub use hopper_staking::*;
355}
356
357#[cfg(feature = "vesting")]
359pub mod vesting {
360 pub use hopper_vesting::*;
361}
362
363#[cfg(feature = "distribute")]
365pub mod distribute {
366 pub use hopper_distribute::*;
367}
368
369#[cfg(feature = "multisig")]
371pub mod multisig {
372 pub use hopper_multisig::*;
373}
374
375#[cfg(feature = "anchor-interop")]
377pub mod anchor {
378 pub use hopper_anchor::*;
379}
380
381#[doc(hidden)]
383pub mod internal {
384 pub use crate::{hopper_core, hopper_runtime, hopper_schema, hopper_solana};
385}
386
387#[cfg(feature = "metaplex")]
392pub use hopper_metaplex;
393
394pub use hopper_runtime::utils;
397
398pub use hopper_core::hopper_dispatch;
400pub use hopper_macros::{
401 const_assert_pod, hopper_accounts, hopper_assert_compatible, hopper_assert_fingerprint,
402 hopper_check, hopper_close, hopper_error, hopper_init, hopper_interface, hopper_invariant,
403 hopper_layout, hopper_manifest, hopper_register_discs, hopper_require, hopper_segment,
404 hopper_validate, hopper_verify_pda, hopper_virtual,
405};
406
407pub use hopper_runtime::layout_migrations;
412
413#[macro_export]
467macro_rules! hopper_load {
468 ( $slice:expr => [ $($binding:ident),+ $(, ..)? $(,)? ] ) => {
469 let [ $($binding,)+ .. ] = $slice else {
470 return ::core::result::Result::Err(
471 $crate::hopper_runtime::error::ProgramError::NotEnoughAccountKeys,
472 );
473 };
474 };
475}
476
477#[macro_export]
497macro_rules! hopper_dynamic_tail {
498 (
499 $(#[$meta:meta])*
500 $vis:vis struct $name:ident {
501 $( $field:ident : $ty:ty ),* $(,)?
502 }
503 ) => {
504 $(#[$meta])*
505 #[derive(Clone, Copy, Default)]
506 $vis struct $name {
507 $( pub $field: $ty, )*
508 }
509
510 impl $crate::__runtime::TailCodec for $name {
511 const MAX_ENCODED_LEN: usize = 0 $(+ <$ty as $crate::__runtime::TailCodec>::MAX_ENCODED_LEN)*;
512
513 #[inline]
514 fn encode(
515 &self,
516 out: &mut [u8],
517 ) -> ::core::result::Result<usize, $crate::__runtime::ProgramError> {
518 let mut cursor = 0usize;
519 $(
520 let written = <$ty as $crate::__runtime::TailCodec>::encode(
521 &self.$field,
522 &mut out[cursor..],
523 )?;
524 cursor = cursor
525 .checked_add(written)
526 .ok_or($crate::__runtime::ProgramError::AccountDataTooSmall)?;
527 )*
528 Ok(cursor)
529 }
530
531 #[inline]
532 fn decode(
533 input: &[u8],
534 ) -> ::core::result::Result<(Self, usize), $crate::__runtime::ProgramError> {
535 let mut cursor = 0usize;
536 $(
537 let ($field, consumed) = <$ty as $crate::__runtime::TailCodec>::decode(
538 &input[cursor..],
539 )?;
540 cursor = cursor
541 .checked_add(consumed)
542 .ok_or($crate::__runtime::ProgramError::InvalidAccountData)?;
543 )*
544 Ok((Self { $( $field, )* }, cursor))
545 }
546 }
547 };
548}
549
550#[doc(hidden)]
551#[macro_export]
552macro_rules! __hopper_dynamic_fields_tail {
553 (@emit [$($meta:tt)*] [$vis:vis] [$name:ident] [$($fields:tt)*]) => {
554 $crate::hopper_dynamic_tail! {
555 $($meta)*
556 $vis struct $name {
557 $($fields)*
558 }
559 }
560 };
561
562 (@parse [$($meta:tt)*] [$vis:vis] [$name:ident] [$($fields:tt)*]) => {
563 $crate::__hopper_dynamic_fields_tail!(@emit [$($meta)*] [$vis] [$name] [$($fields)*]);
564 };
565 (@parse [$($meta:tt)*] [$vis:vis] [$name:ident] [$($fields:tt)*] ,) => {
566 $crate::__hopper_dynamic_fields_tail!(@emit [$($meta)*] [$vis] [$name] [$($fields)*]);
567 };
568
569 (@parse [$($meta:tt)*] [$vis:vis] [$name:ident] [$($fields:tt)*]
570 $field:ident : string < $cap:literal >, $($rest:tt)+
571 ) => {
572 $crate::__hopper_dynamic_fields_tail!(@parse [$($meta)*] [$vis] [$name]
573 [$($fields)* $field: $crate::__runtime::HopperString<$cap>,]
574 $($rest)+
575 );
576 };
577 (@parse [$($meta:tt)*] [$vis:vis] [$name:ident] [$($fields:tt)*]
578 $field:ident : string < $cap:literal > $(,)?
579 ) => {
580 $crate::__hopper_dynamic_fields_tail!(@emit [$($meta)*] [$vis] [$name]
581 [$($fields)* $field: $crate::__runtime::HopperString<$cap>,]
582 );
583 };
584
585 (@parse [$($meta:tt)*] [$vis:vis] [$name:ident] [$($fields:tt)*]
586 $field:ident : vec < $ty:ty, $cap:literal >, $($rest:tt)+
587 ) => {
588 $crate::__hopper_dynamic_fields_tail!(@parse [$($meta)*] [$vis] [$name]
589 [$($fields)* $field: $crate::__runtime::HopperVec<$ty, $cap>,]
590 $($rest)+
591 );
592 };
593 (@parse [$($meta:tt)*] [$vis:vis] [$name:ident] [$($fields:tt)*]
594 $field:ident : vec < $ty:ty, $cap:literal > $(,)?
595 ) => {
596 $crate::__hopper_dynamic_fields_tail!(@emit [$($meta)*] [$vis] [$name]
597 [$($fields)* $field: $crate::__runtime::HopperVec<$ty, $cap>,]
598 );
599 };
600
601 (@parse [$($meta:tt)*] [$vis:vis] [$name:ident] [$($fields:tt)*]
602 $field:ident : $ty:ty, $($rest:tt)+
603 ) => {
604 $crate::__hopper_dynamic_fields_tail!(@parse [$($meta)*] [$vis] [$name]
605 [$($fields)* $field: $ty,]
606 $($rest)+
607 );
608 };
609 (@parse [$($meta:tt)*] [$vis:vis] [$name:ident] [$($fields:tt)*]
610 $field:ident : $ty:ty $(,)?
611 ) => {
612 $crate::__hopper_dynamic_fields_tail!(@emit [$($meta)*] [$vis] [$name]
613 [$($fields)* $field: $ty,]
614 );
615 };
616}
617
618#[macro_export]
635macro_rules! hopper_dynamic_fields {
636 (
637 $(#[$meta:meta])*
638 $vis:vis struct $name:ident {
639 $($body:tt)*
640 }
641 ) => {
642 $crate::__hopper_dynamic_fields_tail!(@parse [$(#[$meta])*] [$vis] [$name] [] $($body)*);
643 };
644}
645
646pub use hopper_runtime::{
652 address, err, error, fast_entrypoint, hopper_emit_cpi, hopper_entrypoint,
653 hopper_fast_entrypoint, hopper_lazy_entrypoint, hopper_log, hopper_unsafe_region,
654 lazy_entrypoint, msg, no_allocator, nostd_panic_handler, program_entrypoint, require,
655 require_eq, require_gt, require_gte, require_keys_eq, require_keys_neq, require_lt,
656 require_lte, require_neq,
657};
658
659#[macro_export]
675macro_rules! interface_account_set {
676 (
677 $(#[$marker_meta:meta])*
678 $vis:vis struct $marker:ident : $interface:ty;
679 $(#[$resolved_meta:meta])*
680 $enum_vis:vis enum $resolved:ident {
681 $($variant:ident($layout:ty)),+ $(,)?
682 }
683 ) => {
684 $(#[$marker_meta])*
685 #[derive(Clone, Copy, Debug, Default)]
686 $vis struct $marker;
687
688 impl $crate::__runtime::FieldMap for $marker {
689 const FIELDS: &'static [$crate::__runtime::FieldInfo] = &[];
690 }
691
692 impl $crate::__runtime::LayoutContract for $marker {
693 const DISC: u8 = 0;
694 const VERSION: u8 = 0;
695 const LAYOUT_ID: [u8; 8] = [0; 8];
696 const SIZE: usize = $crate::__runtime::HopperHeader::SIZE;
697 }
698
699 impl $crate::__runtime::InterfaceAccountLayout for $marker {
700 type Interface = $interface;
701
702 #[inline]
703 fn validate_interface_account(
704 view: &$crate::__runtime::AccountView,
705 ) -> ::core::result::Result<(), $crate::__runtime::ProgramError> {
706 let data = view.try_borrow()?;
707 let info = $crate::__runtime::LayoutInfo::from_data(&data)
708 .ok_or($crate::__runtime::ProgramError::AccountDataTooSmall)?;
709 if false $(|| info.matches::<$layout>())+ {
710 Ok(())
711 } else {
712 Err($crate::__runtime::ProgramError::InvalidAccountData)
713 }
714 }
715 }
716
717 $(#[$resolved_meta])*
718 $enum_vis enum $resolved<'a> {
719 $($variant($crate::__runtime::Ref<'a, $layout>)),+
720 }
721
722 impl $crate::__runtime::InterfaceAccountResolve for $marker {
723 type Resolved<'a> = $resolved<'a>;
724
725 #[inline]
726 fn resolve<'a>(
727 view: &'a $crate::__runtime::AccountView,
728 ) -> ::core::result::Result<Self::Resolved<'a>, $crate::__runtime::ProgramError> {
729 let info = {
730 let data = view.try_borrow()?;
731 $crate::__runtime::LayoutInfo::from_data(&data)
732 .ok_or($crate::__runtime::ProgramError::AccountDataTooSmall)?
733 };
734 $(
735 if info.matches::<$layout>() {
736 return Ok($resolved::$variant(view.load_cross_program::<$layout>()?));
737 }
738 )+
739 Err($crate::__runtime::ProgramError::InvalidAccountData)
740 }
741 }
742 };
743}
744
745#[macro_export]
760macro_rules! program_dispatch {
761 ($program_mod:ident) => {
762 #[cfg(target_os = "solana")]
763 $crate::program_entrypoint!(__hopper_process_instruction);
764
765 #[doc(hidden)]
766 fn __hopper_process_instruction(
767 program_id: &$crate::__runtime::Address,
768 accounts: &[$crate::__runtime::AccountView],
769 instruction_data: &[u8],
770 ) -> ::core::result::Result<(), $crate::__runtime::ProgramError> {
771 let mut ctx = $crate::prelude::Context::new(program_id, accounts, instruction_data);
772 $program_mod::process_instruction(&mut ctx)
773 }
774 };
775}
776
777#[cfg(feature = "proc-macros")]
779pub use hopper_macros_proc::{
780 account, accounts, args, constant, context, crank, declare_program, dynamic, dynamic_account,
781 error as error_code, event, hopper_args, hopper_constant, hopper_context, hopper_crank,
782 hopper_dynamic, hopper_dynamic_account, hopper_event, hopper_migrate, hopper_pod,
783 hopper_program, hopper_state, migrate, pod, program, state, Accounts, HopperInitSpace,
784};
785
786#[doc(hidden)]
788pub mod __runtime {
789 pub use hopper_runtime::{
790 apply_pending_migrations, borrow_address_slice, borrow_bounded_str, read_tail,
791 read_tail_len, tail_capacity, tail_payload, write_tail, Account, AccountLayout,
792 AccountView, Address, BoundedString, BoundedVec, Context, FieldInfo, FieldMap,
793 HopperHeader, HopperInstructionPolicy, HopperProgramPolicy, HopperSigner, HopperString,
794 HopperVec, InitAccount, InstructionAccount, InstructionView, Interface, InterfaceAccount,
795 InterfaceAccountLayout, InterfaceAccountResolve, InterfaceSpec, LayoutContract, LayoutInfo,
796 LayoutMigration, MigrationEdge, Pod, Program, ProgramError, ProgramId, Ref, RefMut, SegRef,
797 SegRefMut, SegmentLease, SystemAccount, SystemId, TailCodec, TailElement, UncheckedAccount,
798 };
799
800 pub use hopper_runtime::crank::CrankMarker;
806 pub use hopper_runtime::dyn_cpi::DynCpi;
807
808 #[cfg(feature = "hopper-native-backend")]
813 pub use hopper_runtime::__hopper_native;
814
815 pub use hopper_runtime::__sealed;
820
821 pub use hopper_runtime::token;
829}