templar_common/versioned_state/
macros.rs1#[macro_export]
2macro_rules! impl_versioned_state {
3 ($contract: ident, $current_state: ty, $migrations: ty) => {
4 #[::near_sdk::near]
5 impl $crate::versioned_state::MigrateExternalInterface for $contract {
6 fn get_stored_state_version() -> u32 {
7 $crate::versioned_state::read_state_version()
8 .unwrap_or_else(|e| ::near_sdk::env::panic_str(&e.to_string()))
9 }
10
11 fn get_target_state_version() -> u32 {
12 <$current_state as $crate::versioned_state::StateVersion>::VERSION
13 }
14
15 fn needs_migration() -> bool {
16 <$current_state as $crate::versioned_state::StateVersion>::needs_migration()
17 .unwrap_or_else(|e| ::near_sdk::env::panic_str(&e.to_string()))
18 }
19 }
20
21 #[cfg_attr(target_arch = "wasm32", unsafe(no_mangle))]
22 #[cfg_attr(not(target_arch = "wasm32"), allow(dead_code))]
23 pub fn migrate() {
24 use near_sdk::env;
25 env::setup_panic_hook();
26
27 ::near_sdk::require!(
28 env::predecessor_account_id() == env::current_account_id(),
29 "migrate function is private",
30 );
31
32 let needs =
35 <$current_state as $crate::versioned_state::StateVersion>::needs_migration()
36 .unwrap_or_else(|e| env::panic_str(&e.to_string()));
37
38 let input = env::input().unwrap_or_default();
39
40 if !needs {
41 ::near_sdk::require!(
42 input.is_empty(),
43 "no state migration is needed; migrate_args must be empty",
44 );
45 return;
46 }
47
48 let migrations: Vec<$migrations> = $crate::versioned_state::parse_one_or_many(&input)
54 .unwrap_or_else(|e| env::panic_str(&e.to_string()));
55
56 $crate::versioned_state::run_migration_chain(
57 migrations,
58 <$current_state as $crate::versioned_state::StateVersion>::VERSION,
59 )
60 .unwrap_or_else(|e| env::panic_str(&e.to_string()));
61
62 ::near_sdk::require!(
65 !<$current_state as $crate::versioned_state::StateVersion>::needs_migration()
66 .unwrap_or_else(|e| env::panic_str(&e.to_string())),
67 "state migration incomplete: stored version is still behind target",
68 );
69 }
70 };
71}
72
73pub use impl_versioned_state;