2026-05-06 17:08:15 -03:00
#![ cfg_attr(not(test), no_main) ]
2026-03-17 18:08:53 +01:00
2026-06-06 03:15:30 +05:30
use nssa_core ::account ::{ AccountId , AccountWithMetadata } ;
2026-06-03 01:10:08 +05:30
use spel_framework ::context ::ProgramContext ;
use spel_framework ::prelude ::* ;
2026-03-17 18:08:53 +01:00
2026-05-06 17:08:15 -03:00
#[ cfg(not(test)) ]
2026-03-17 18:08:53 +01:00
risc0_zkvm ::guest ::entry! ( main ) ;
#[ lez_program(instruction = " token_core::Instruction " ) ]
mod token {
2026-05-06 17:08:15 -03:00
#[ expect(
unused_imports ,
reason = " SPEL instruction macro requires importing parent-scope handler types "
) ]
2026-03-17 18:08:53 +01:00
use super ::* ;
/// Transfer tokens from sender to recipient.
2026-04-15 14:55:04 -03:00
/// Fresh public recipients must be explicitly authorized in the same transaction.
2026-03-17 18:08:53 +01:00
#[ instruction ]
pub fn transfer (
2026-06-26 16:55:23 -03:00
#[ account(mut, signer) ]
2026-03-17 18:08:53 +01:00
sender : AccountWithMetadata ,
2026-06-26 16:55:23 -03:00
#[ account(mut) ]
2026-03-17 18:08:53 +01:00
recipient : AccountWithMetadata ,
amount_to_transfer : u128 ,
) -> SpelResult {
2026-06-03 01:10:08 +05:30
Ok ( spel_framework ::SpelOutput ::execute (
token_program ::transfer ::transfer ( sender , recipient , amount_to_transfer ) ,
vec! [ ] ,
) )
2026-03-17 18:08:53 +01:00
}
/// Create a new fungible token definition without metadata.
2026-04-15 14:55:04 -03:00
/// Definition and holding targets must be uninitialized and authorized.
2026-06-06 03:15:30 +05:30
/// `mint_authority` is `Some(id)` for a mintable token or `None` for fixed supply.
2026-03-17 18:08:53 +01:00
#[ instruction ]
pub fn new_fungible_definition (
2026-06-26 16:55:23 -03:00
#[ account(init, signer) ]
2026-03-17 18:08:53 +01:00
definition_target_account : AccountWithMetadata ,
2026-06-26 16:55:23 -03:00
#[ account(init, signer) ]
2026-03-17 18:08:53 +01:00
holding_target_account : AccountWithMetadata ,
name : String ,
total_supply : u128 ,
2026-06-06 03:15:30 +05:30
mint_authority : Option < AccountId > ,
2026-03-17 18:08:53 +01:00
) -> SpelResult {
2026-05-12 11:33:19 +02:00
Ok ( spel_framework ::SpelOutput ::execute (
2026-03-17 18:08:53 +01:00
token_program ::new_definition ::new_fungible_definition (
definition_target_account ,
holding_target_account ,
name ,
total_supply ,
2026-06-06 03:15:30 +05:30
mint_authority ,
2026-03-17 18:08:53 +01:00
) ,
2026-05-12 11:33:19 +02:00
vec! [ ] ,
2026-03-17 18:08:53 +01:00
) )
}
/// Create a new fungible or non-fungible token definition with metadata.
2026-04-15 14:55:04 -03:00
/// Definition, holding, and metadata targets must be uninitialized and authorized.
2026-05-06 17:08:15 -03:00
#[ expect(
clippy ::boxed_local ,
reason = " boxed metadata keeps the instruction argument size bounded on the stack "
) ]
2026-03-17 18:08:53 +01:00
#[ instruction ]
pub fn new_definition_with_metadata (
2026-06-26 16:55:23 -03:00
#[ account(init, signer) ]
2026-03-17 18:08:53 +01:00
definition_target_account : AccountWithMetadata ,
2026-06-26 16:55:23 -03:00
#[ account(init, signer) ]
2026-03-17 18:08:53 +01:00
holding_target_account : AccountWithMetadata ,
2026-06-26 16:55:23 -03:00
#[ account(init, signer) ]
2026-03-17 18:08:53 +01:00
metadata_target_account : AccountWithMetadata ,
new_definition : token_core ::NewTokenDefinition ,
metadata : Box < token_core ::NewTokenMetadata > ,
) -> SpelResult {
2026-05-12 11:33:19 +02:00
Ok ( spel_framework ::SpelOutput ::execute (
2026-03-17 18:08:53 +01:00
token_program ::new_definition ::new_definition_with_metadata (
definition_target_account ,
holding_target_account ,
metadata_target_account ,
new_definition ,
* metadata ,
) ,
2026-05-12 11:33:19 +02:00
vec! [ ] ,
2026-03-17 18:08:53 +01:00
) )
}
/// Initialize a token holding account for a given token definition.
2026-04-15 14:55:04 -03:00
/// The holding target must be uninitialized and authorized.
2026-03-17 18:08:53 +01:00
#[ instruction ]
pub fn initialize_account (
2026-05-04 10:34:10 -03:00
ctx : ProgramContext ,
2026-03-17 18:08:53 +01:00
definition_account : AccountWithMetadata ,
2026-06-26 16:55:23 -03:00
#[ account(init, signer) ]
2026-03-17 18:08:53 +01:00
account_to_initialize : AccountWithMetadata ,
) -> SpelResult {
2026-05-12 11:33:19 +02:00
Ok ( spel_framework ::SpelOutput ::execute (
2026-03-17 18:08:53 +01:00
token_program ::initialize ::initialize_account (
definition_account ,
account_to_initialize ,
2026-05-04 10:34:10 -03:00
ctx . self_program_id ,
2026-03-17 18:08:53 +01:00
) ,
2026-05-12 11:33:19 +02:00
vec! [ ] ,
2026-03-17 18:08:53 +01:00
) )
}
/// Burn tokens from the holder's account.
#[ instruction ]
pub fn burn (
2026-06-26 16:55:23 -03:00
#[ account(mut) ]
2026-03-17 18:08:53 +01:00
definition_account : AccountWithMetadata ,
2026-06-26 16:55:23 -03:00
#[ account(mut, signer) ]
2026-03-17 18:08:53 +01:00
user_holding_account : AccountWithMetadata ,
amount_to_burn : u128 ,
) -> SpelResult {
2026-06-03 01:10:08 +05:30
Ok ( spel_framework ::SpelOutput ::execute (
token_program ::burn ::burn ( definition_account , user_holding_account , amount_to_burn ) ,
vec! [ ] ,
) )
2026-03-17 18:08:53 +01:00
}
/// Mint new tokens to the holder's account.
2026-06-23 04:05:44 +05:30
/// The current mint authority must authorize the transaction: either the definition account itself when `authority_accounts` is empty (self/PDA authority), or an external authority account passed as the first rest account after rotation.
2026-04-15 14:55:04 -03:00
/// Fresh public holders must be explicitly authorized in the same transaction.
2026-03-17 18:08:53 +01:00
#[ instruction ]
pub fn mint (
2026-05-04 10:34:10 -03:00
ctx : ProgramContext ,
2026-06-26 16:55:23 -03:00
#[ account(mut, signer) ]
2026-03-17 18:08:53 +01:00
definition_account : AccountWithMetadata ,
user_holding_account : AccountWithMetadata ,
2026-06-19 17:51:56 +05:30
authority_accounts : Vec < AccountWithMetadata > ,
2026-03-17 18:08:53 +01:00
amount_to_mint : u128 ,
) -> SpelResult {
2026-06-03 01:10:08 +05:30
Ok ( spel_framework ::SpelOutput ::execute (
token_program ::mint ::mint (
definition_account ,
user_holding_account ,
amount_to_mint ,
2026-06-19 17:51:56 +05:30
authority_accounts ,
2026-06-03 01:10:08 +05:30
ctx . self_program_id ,
) ,
vec! [ ] ,
) )
2026-03-17 18:08:53 +01:00
}
2026-06-06 03:15:30 +05:30
/// Rotate or renounce the mint authority for a fungible token definition.
/// Pass `new_authority: None` to permanently renounce minting (fixed supply).
2026-06-23 04:05:44 +05:30
/// The current mint authority must authorize the transaction: either the definition account itself when `authority_accounts` is empty (self/PDA authority), or an external authority account passed as the first rest account after rotation.
2026-05-27 15:04:28 +05:30
#[ instruction ]
pub fn set_authority (
2026-06-19 23:07:59 +05:30
ctx : ProgramContext ,
2026-05-27 15:04:28 +05:30
definition_account : AccountWithMetadata ,
2026-06-19 17:51:56 +05:30
authority_accounts : Vec < AccountWithMetadata > ,
2026-06-06 03:15:30 +05:30
new_authority : Option < AccountId > ,
2026-05-27 15:04:28 +05:30
) -> SpelResult {
Ok ( spel_framework ::SpelOutput ::execute (
2026-06-19 17:51:56 +05:30
token_program ::set_authority ::set_authority (
definition_account ,
new_authority ,
authority_accounts ,
2026-06-19 23:07:59 +05:30
ctx . self_program_id ,
2026-06-19 17:51:56 +05:30
) ,
2026-05-27 15:04:28 +05:30
vec! [ ] ,
) )
}
2026-03-17 18:08:53 +01:00
/// Print a new NFT from the master copy.
2026-04-15 14:55:04 -03:00
/// The printed copy target must be uninitialized and authorized.
2026-03-17 18:08:53 +01:00
#[ instruction ]
pub fn print_nft (
2026-06-26 16:55:23 -03:00
#[ account(mut, signer) ]
2026-03-17 18:08:53 +01:00
master_account : AccountWithMetadata ,
2026-06-26 16:55:23 -03:00
#[ account(init, signer) ]
2026-03-17 18:08:53 +01:00
printed_account : AccountWithMetadata ,
) -> SpelResult {
2026-06-03 01:10:08 +05:30
Ok ( spel_framework ::SpelOutput ::execute (
token_program ::print_nft ::print_nft ( master_account , printed_account ) ,
vec! [ ] ,
) )
2026-03-17 18:08:53 +01:00
}
}