use proc_macro2::TokenStream;
use quote::quote;
use syn::DeriveInput;
pub fn derive_upgradeable(input: &DeriveInput) -> TokenStream {
let name = &input.ident;
let binver = set_binver_from_env();
quote! {
use stellar_contract_utils::upgradeable::Upgradeable as _;
#binver
#[soroban_sdk::contractimpl]
impl stellar_contract_utils::upgradeable::Upgradeable for #name {
fn upgrade(
e: &soroban_sdk::Env, new_wasm_hash: soroban_sdk::BytesN<32>, operator: soroban_sdk::Address
) {
Self::_require_auth(e, &operator);
stellar_contract_utils::upgradeable::enable_migration(e);
e.deployer().update_current_contract_wasm(new_wasm_hash);
}
}
}
}
pub fn derive_upgradeable_migratable(input: &DeriveInput) -> proc_macro2::TokenStream {
let name = &input.ident;
let binver = set_binver_from_env();
quote! {
use stellar_contract_utils::upgradeable::UpgradeableMigratable as _;
#binver
type MigrationData = <#name as stellar_contract_utils::upgradeable::UpgradeableMigratableInternal>::MigrationData;
#[soroban_sdk::contractimpl]
impl stellar_contract_utils::upgradeable::UpgradeableMigratable for #name {
fn upgrade(
e: &soroban_sdk::Env, new_wasm_hash: soroban_sdk::BytesN<32>, operator: soroban_sdk::Address
) {
Self::_require_auth(e, &operator);
stellar_contract_utils::upgradeable::enable_migration(e);
e.deployer().update_current_contract_wasm(new_wasm_hash);
}
fn migrate(e: &soroban_sdk::Env, migration_data: MigrationData, operator: soroban_sdk::Address) {
Self::_require_auth(e, &operator);
stellar_contract_utils::upgradeable::ensure_can_complete_migration(e);
Self::_migrate(e, &migration_data);
stellar_contract_utils::upgradeable::complete_migration(e);
}
}
}
}
fn set_binver_from_env() -> proc_macro2::TokenStream {
let version = std::env::var("CARGO_PKG_VERSION");
match version {
Ok(v) if v != "0.0.0" => {
quote! { soroban_sdk::contractmeta!(key = "binver", val = #v); }
}
_ => quote! {},
}
}
#[cfg(test)]
mod tests {
use std::env;
use super::*;
#[test]
fn test_set_binver_from_env_zero_version() {
env::set_var("CARGO_PKG_VERSION", "0.0.0");
let result = set_binver_from_env();
let result_str = result.to_string();
assert_eq!(result_str.trim(), "");
}
}