refactor: split token program into crates

This commit is contained in:
Daniil Polyakov
2026-02-06 00:08:43 +03:00
parent ce29ca2fd0
commit 9909f02803
49 changed files with 2981 additions and 3804 deletions
+2
View File
@@ -24,7 +24,9 @@ risc0-build = "3.0.3"
risc0-binfmt = "3.0.2"
[dev-dependencies]
token_core.workspace = true
test_program_methods.workspace = true
env_logger.workspace = true
hex-literal = "1.0.0"
test-case = "3.3.1"
+27 -7
View File
@@ -20,8 +20,7 @@ pub struct ProgramInput<T> {
/// Each program can derive up to `2^256` unique account IDs by choosing different
/// seeds. PDAs allow programs to control namespaced account identifiers without
/// collisions between programs.
#[derive(Serialize, Deserialize, Clone, Eq, PartialEq)]
#[cfg_attr(any(feature = "host", test), derive(Debug))]
#[derive(Debug, Serialize, Deserialize, Clone, Eq, PartialEq)]
pub struct PdaSeed([u8; 32]);
impl PdaSeed {
@@ -65,23 +64,44 @@ impl From<(&ProgramId, &PdaSeed)> for AccountId {
}
}
#[derive(Serialize, Deserialize, Clone, PartialEq, Eq)]
#[cfg_attr(any(feature = "host", test), derive(Debug,))]
#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq)]
pub struct ChainedCall {
/// The program ID of the program to execute
pub program_id: ProgramId,
pub pre_states: Vec<AccountWithMetadata>,
/// The instruction data to pass
pub instruction_data: InstructionData,
pub pre_states: Vec<AccountWithMetadata>,
pub pda_seeds: Vec<PdaSeed>,
}
impl ChainedCall {
/// Creates a new chained call serializing the given instruction.
pub fn new<I: Serialize>(
program_id: ProgramId,
pre_states: Vec<AccountWithMetadata>,
instruction: &I,
) -> Self {
Self {
program_id,
pre_states,
instruction_data: risc0_zkvm::serde::to_vec(instruction)
.expect("Serialization to Vec<u32> should not fail"),
pda_seeds: Vec::new(),
}
}
pub fn with_pda_seeds(mut self, pda_seeds: Vec<PdaSeed>) -> Self {
self.pda_seeds = pda_seeds;
self
}
}
/// Represents the final state of an `Account` after a program execution.
/// A post state may optionally request that the executing program
/// becomes the owner of the account (a “claim”). This is used to signal
/// that the program intends to take ownership of the account.
#[derive(Serialize, Deserialize, Clone)]
#[cfg_attr(any(feature = "host", test), derive(Debug, PartialEq, Eq))]
#[derive(Debug, Serialize, Deserialize, Clone)]
#[cfg_attr(any(feature = "host", test), derive(PartialEq, Eq))]
pub struct AccountPostState {
account: Account,
claim: bool,
+62 -145
View File
@@ -317,6 +317,7 @@ pub mod tests {
encryption::{EphemeralPublicKey, IncomingViewingPublicKey, Scalar},
program::{PdaSeed, ProgramId},
};
use token_core::{TokenDefinition, TokenHolding};
use crate::{
PublicKey, PublicTransaction, V02State,
@@ -2328,53 +2329,6 @@ pub mod tests {
));
}
// TODO: repeated code needs to be cleaned up
// from token.rs (also repeated in amm.rs)
const TOKEN_DEFINITION_DATA_SIZE: usize = 55;
const TOKEN_HOLDING_DATA_SIZE: usize = 49;
struct TokenDefinition {
account_type: u8,
name: [u8; 6],
total_supply: u128,
metadata_id: AccountId,
}
struct TokenHolding {
account_type: u8,
definition_id: AccountId,
balance: u128,
}
impl TokenDefinition {
fn into_data(self) -> Data {
let mut bytes = Vec::<u8>::new();
bytes.extend_from_slice(&[self.account_type]);
bytes.extend_from_slice(&self.name);
bytes.extend_from_slice(&self.total_supply.to_le_bytes());
bytes.extend_from_slice(&self.metadata_id.to_bytes());
if bytes.len() != TOKEN_DEFINITION_DATA_SIZE {
panic!("Invalid Token Definition data");
}
Data::try_from(bytes).expect("Token definition data size must fit into data")
}
}
impl TokenHolding {
fn into_data(self) -> Data {
let mut bytes = [0; TOKEN_HOLDING_DATA_SIZE];
bytes[0] = self.account_type;
bytes[1..33].copy_from_slice(&self.definition_id.to_bytes());
bytes[33..].copy_from_slice(&self.balance.to_le_bytes());
bytes
.to_vec()
.try_into()
.expect("33 bytes should fit into Data")
}
}
// TODO repeated code should ultimately be removed;
fn compute_pool_pda(
amm_program_id: ProgramId,
@@ -2747,8 +2701,7 @@ pub mod tests {
Account {
program_owner: Program::token().id(),
balance: 0u128,
data: TokenHolding::into_data(TokenHolding {
account_type: 1u8,
data: Data::from(&TokenHolding::Fungible {
definition_id: IdForTests::token_a_definition_id(),
balance: BalanceForTests::user_token_a_holding_init(),
}),
@@ -2760,8 +2713,7 @@ pub mod tests {
Account {
program_owner: Program::token().id(),
balance: 0u128,
data: TokenHolding::into_data(TokenHolding {
account_type: 1u8,
data: Data::from(&TokenHolding::Fungible {
definition_id: IdForTests::token_b_definition_id(),
balance: BalanceForTests::user_token_b_holding_init(),
}),
@@ -2793,11 +2745,10 @@ pub mod tests {
Account {
program_owner: Program::token().id(),
balance: 0u128,
data: TokenDefinition::into_data(TokenDefinition {
account_type: 0u8,
name: [1u8; 6],
data: Data::from(&TokenDefinition::Fungible {
name: String::from("test"),
total_supply: BalanceForTests::token_a_supply(),
metadata_id: AccountId::new([0; 32]),
metadata_id: None,
}),
nonce: 0,
}
@@ -2807,11 +2758,10 @@ pub mod tests {
Account {
program_owner: Program::token().id(),
balance: 0u128,
data: TokenDefinition::into_data(TokenDefinition {
account_type: 0u8,
name: [1u8; 6],
data: Data::from(&TokenDefinition::Fungible {
name: String::from("test"),
total_supply: BalanceForTests::token_b_supply(),
metadata_id: AccountId::new([0; 32]),
metadata_id: None,
}),
nonce: 0,
}
@@ -2821,11 +2771,10 @@ pub mod tests {
Account {
program_owner: Program::token().id(),
balance: 0u128,
data: TokenDefinition::into_data(TokenDefinition {
account_type: 0u8,
name: [1u8; 6],
data: Data::from(&TokenDefinition::Fungible {
name: String::from("LP Token"),
total_supply: BalanceForTests::token_lp_supply(),
metadata_id: AccountId::new([0; 32]),
metadata_id: None,
}),
nonce: 0,
}
@@ -2835,8 +2784,7 @@ pub mod tests {
Account {
program_owner: Program::token().id(),
balance: 0u128,
data: TokenHolding::into_data(TokenHolding {
account_type: 1u8,
data: Data::from(&TokenHolding::Fungible {
definition_id: IdForTests::token_a_definition_id(),
balance: BalanceForTests::vault_a_balance_init(),
}),
@@ -2848,8 +2796,7 @@ pub mod tests {
Account {
program_owner: Program::token().id(),
balance: 0u128,
data: TokenHolding::into_data(TokenHolding {
account_type: 1u8,
data: Data::from(&TokenHolding::Fungible {
definition_id: IdForTests::token_b_definition_id(),
balance: BalanceForTests::vault_b_balance_init(),
}),
@@ -2861,8 +2808,7 @@ pub mod tests {
Account {
program_owner: Program::token().id(),
balance: 0u128,
data: TokenHolding::into_data(TokenHolding {
account_type: 1u8,
data: Data::from(&TokenHolding::Fungible {
definition_id: IdForTests::token_lp_definition_id(),
balance: BalanceForTests::user_token_lp_holding_init(),
}),
@@ -2874,8 +2820,7 @@ pub mod tests {
Account {
program_owner: Program::token().id(),
balance: 0u128,
data: TokenHolding::into_data(TokenHolding {
account_type: 1u8,
data: Data::from(&TokenHolding::Fungible {
definition_id: IdForTests::token_a_definition_id(),
balance: BalanceForTests::vault_a_balance_swap_1(),
}),
@@ -2887,8 +2832,7 @@ pub mod tests {
Account {
program_owner: Program::token().id(),
balance: 0u128,
data: TokenHolding::into_data(TokenHolding {
account_type: 1u8,
data: Data::from(&TokenHolding::Fungible {
definition_id: IdForTests::token_b_definition_id(),
balance: BalanceForTests::vault_b_balance_swap_1(),
}),
@@ -2920,8 +2864,7 @@ pub mod tests {
Account {
program_owner: Program::token().id(),
balance: 0u128,
data: TokenHolding::into_data(TokenHolding {
account_type: 1u8,
data: Data::from(&TokenHolding::Fungible {
definition_id: IdForTests::token_a_definition_id(),
balance: BalanceForTests::user_token_a_holding_swap_1(),
}),
@@ -2933,8 +2876,7 @@ pub mod tests {
Account {
program_owner: Program::token().id(),
balance: 0u128,
data: TokenHolding::into_data(TokenHolding {
account_type: 1u8,
data: Data::from(&TokenHolding::Fungible {
definition_id: IdForTests::token_b_definition_id(),
balance: BalanceForTests::user_token_b_holding_swap_1(),
}),
@@ -2946,8 +2888,7 @@ pub mod tests {
Account {
program_owner: Program::token().id(),
balance: 0u128,
data: TokenHolding::into_data(TokenHolding {
account_type: 1u8,
data: Data::from(&TokenHolding::Fungible {
definition_id: IdForTests::token_a_definition_id(),
balance: BalanceForTests::vault_a_balance_swap_2(),
}),
@@ -2959,8 +2900,7 @@ pub mod tests {
Account {
program_owner: Program::token().id(),
balance: 0u128,
data: TokenHolding::into_data(TokenHolding {
account_type: 1u8,
data: Data::from(&TokenHolding::Fungible {
definition_id: IdForTests::token_b_definition_id(),
balance: BalanceForTests::vault_b_balance_swap_2(),
}),
@@ -2992,8 +2932,7 @@ pub mod tests {
Account {
program_owner: Program::token().id(),
balance: 0u128,
data: TokenHolding::into_data(TokenHolding {
account_type: 1u8,
data: Data::from(&TokenHolding::Fungible {
definition_id: IdForTests::token_a_definition_id(),
balance: BalanceForTests::user_token_a_holding_swap_2(),
}),
@@ -3005,8 +2944,7 @@ pub mod tests {
Account {
program_owner: Program::token().id(),
balance: 0u128,
data: TokenHolding::into_data(TokenHolding {
account_type: 1u8,
data: Data::from(&TokenHolding::Fungible {
definition_id: IdForTests::token_b_definition_id(),
balance: BalanceForTests::user_token_b_holding_swap_2(),
}),
@@ -3018,8 +2956,7 @@ pub mod tests {
Account {
program_owner: Program::token().id(),
balance: 0u128,
data: TokenHolding::into_data(TokenHolding {
account_type: 1u8,
data: Data::from(&TokenHolding::Fungible {
definition_id: IdForTests::token_a_definition_id(),
balance: BalanceForTests::vault_a_balance_add(),
}),
@@ -3031,8 +2968,7 @@ pub mod tests {
Account {
program_owner: Program::token().id(),
balance: 0u128,
data: TokenHolding::into_data(TokenHolding {
account_type: 1u8,
data: Data::from(&TokenHolding::Fungible {
definition_id: IdForTests::token_b_definition_id(),
balance: BalanceForTests::vault_b_balance_add(),
}),
@@ -3064,8 +3000,7 @@ pub mod tests {
Account {
program_owner: Program::token().id(),
balance: 0u128,
data: TokenHolding::into_data(TokenHolding {
account_type: 1u8,
data: Data::from(&TokenHolding::Fungible {
definition_id: IdForTests::token_a_definition_id(),
balance: BalanceForTests::user_token_a_holding_add(),
}),
@@ -3077,8 +3012,7 @@ pub mod tests {
Account {
program_owner: Program::token().id(),
balance: 0u128,
data: TokenHolding::into_data(TokenHolding {
account_type: 1u8,
data: Data::from(&TokenHolding::Fungible {
definition_id: IdForTests::token_b_definition_id(),
balance: BalanceForTests::user_token_b_holding_add(),
}),
@@ -3090,8 +3024,7 @@ pub mod tests {
Account {
program_owner: Program::token().id(),
balance: 0u128,
data: TokenHolding::into_data(TokenHolding {
account_type: 1u8,
data: Data::from(&TokenHolding::Fungible {
definition_id: IdForTests::token_lp_definition_id(),
balance: BalanceForTests::user_token_lp_holding_add(),
}),
@@ -3103,11 +3036,10 @@ pub mod tests {
Account {
program_owner: Program::token().id(),
balance: 0u128,
data: TokenDefinition::into_data(TokenDefinition {
account_type: 0u8,
name: [1u8; 6],
data: Data::from(&TokenDefinition::Fungible {
name: String::from("LP Token"),
total_supply: BalanceForTests::token_lp_supply_add(),
metadata_id: AccountId::new([0; 32]),
metadata_id: None,
}),
nonce: 0,
}
@@ -3117,8 +3049,7 @@ pub mod tests {
Account {
program_owner: Program::token().id(),
balance: 0u128,
data: TokenHolding::into_data(TokenHolding {
account_type: 1u8,
data: Data::from(&TokenHolding::Fungible {
definition_id: IdForTests::token_a_definition_id(),
balance: BalanceForTests::vault_a_balance_remove(),
}),
@@ -3130,8 +3061,7 @@ pub mod tests {
Account {
program_owner: Program::token().id(),
balance: 0u128,
data: TokenHolding::into_data(TokenHolding {
account_type: 1u8,
data: Data::from(&TokenHolding::Fungible {
definition_id: IdForTests::token_b_definition_id(),
balance: BalanceForTests::vault_b_balance_remove(),
}),
@@ -3163,8 +3093,7 @@ pub mod tests {
Account {
program_owner: Program::token().id(),
balance: 0u128,
data: TokenHolding::into_data(TokenHolding {
account_type: 1u8,
data: Data::from(&TokenHolding::Fungible {
definition_id: IdForTests::token_a_definition_id(),
balance: BalanceForTests::user_token_a_holding_remove(),
}),
@@ -3176,8 +3105,7 @@ pub mod tests {
Account {
program_owner: Program::token().id(),
balance: 0u128,
data: TokenHolding::into_data(TokenHolding {
account_type: 1u8,
data: Data::from(&TokenHolding::Fungible {
definition_id: IdForTests::token_b_definition_id(),
balance: BalanceForTests::user_token_b_holding_remove(),
}),
@@ -3189,8 +3117,7 @@ pub mod tests {
Account {
program_owner: Program::token().id(),
balance: 0u128,
data: TokenHolding::into_data(TokenHolding {
account_type: 1u8,
data: Data::from(&TokenHolding::Fungible {
definition_id: IdForTests::token_lp_definition_id(),
balance: BalanceForTests::user_token_lp_holding_remove(),
}),
@@ -3202,11 +3129,10 @@ pub mod tests {
Account {
program_owner: Program::token().id(),
balance: 0u128,
data: TokenDefinition::into_data(TokenDefinition {
account_type: 0u8,
name: [1u8; 6],
data: Data::from(&TokenDefinition::Fungible {
name: String::from("LP Token"),
total_supply: BalanceForTests::token_lp_supply_remove(),
metadata_id: AccountId::new([0; 32]),
metadata_id: None,
}),
nonce: 0,
}
@@ -3216,11 +3142,10 @@ pub mod tests {
Account {
program_owner: Program::token().id(),
balance: 0u128,
data: TokenDefinition::into_data(TokenDefinition {
account_type: 0u8,
name: [1u8; 6],
data: Data::from(&TokenDefinition::Fungible {
name: String::from("LP Token"),
total_supply: 0,
metadata_id: AccountId::new([0; 32]),
metadata_id: None,
}),
nonce: 0,
}
@@ -3230,8 +3155,7 @@ pub mod tests {
Account {
program_owner: Program::token().id(),
balance: 0u128,
data: TokenHolding::into_data(TokenHolding {
account_type: 1u8,
data: Data::from(&TokenHolding::Fungible {
definition_id: IdForTests::token_a_definition_id(),
balance: 0,
}),
@@ -3243,8 +3167,7 @@ pub mod tests {
Account {
program_owner: Program::token().id(),
balance: 0u128,
data: TokenHolding::into_data(TokenHolding {
account_type: 1u8,
data: Data::from(&TokenHolding::Fungible {
definition_id: IdForTests::token_b_definition_id(),
balance: 0,
}),
@@ -3276,8 +3199,7 @@ pub mod tests {
Account {
program_owner: Program::token().id(),
balance: 0u128,
data: TokenHolding::into_data(TokenHolding {
account_type: 1u8,
data: Data::from(&TokenHolding::Fungible {
definition_id: IdForTests::token_a_definition_id(),
balance: BalanceForTests::user_token_a_holding_new_definition(),
}),
@@ -3289,8 +3211,7 @@ pub mod tests {
Account {
program_owner: Program::token().id(),
balance: 0u128,
data: TokenHolding::into_data(TokenHolding {
account_type: 1u8,
data: Data::from(&TokenHolding::Fungible {
definition_id: IdForTests::token_b_definition_id(),
balance: BalanceForTests::user_token_b_holding_new_definition(),
}),
@@ -3302,8 +3223,7 @@ pub mod tests {
Account {
program_owner: Program::token().id(),
balance: 0u128,
data: TokenHolding::into_data(TokenHolding {
account_type: 1u8,
data: Data::from(&TokenHolding::Fungible {
definition_id: IdForTests::token_lp_definition_id(),
balance: BalanceForTests::user_token_a_holding_new_definition(),
}),
@@ -3315,11 +3235,10 @@ pub mod tests {
Account {
program_owner: Program::token().id(),
balance: 0u128,
data: TokenDefinition::into_data(TokenDefinition {
account_type: 0u8,
name: [1u8; 6],
data: Data::from(&TokenDefinition::Fungible {
name: String::from("LP Token"),
total_supply: BalanceForTests::vault_a_balance_init(),
metadata_id: AccountId::new([0; 32]),
metadata_id: None,
}),
nonce: 0,
}
@@ -3349,8 +3268,7 @@ pub mod tests {
Account {
program_owner: Program::token().id(),
balance: 0u128,
data: TokenHolding::into_data(TokenHolding {
account_type: 1u8,
data: Data::from(&TokenHolding::Fungible {
definition_id: IdForTests::token_lp_definition_id(),
balance: 0,
}),
@@ -4115,13 +4033,13 @@ pub mod tests {
let pinata_token_holding_id = AccountId::from((&pinata_token.id(), &PdaSeed::new([0; 32])));
let winner_token_holding_id = AccountId::new([3; 32]);
let mut expected_winner_account_data = [0; 49];
expected_winner_account_data[0] = 1;
expected_winner_account_data[1..33].copy_from_slice(pinata_token_definition_id.value());
expected_winner_account_data[33..].copy_from_slice(&150u128.to_le_bytes());
let expected_winner_account_holding = token_core::TokenHolding::Fungible {
definition_id: pinata_token_definition_id,
balance: 150,
};
let expected_winner_token_holding_post = Account {
program_owner: token.id(),
data: expected_winner_account_data.to_vec().try_into().unwrap(),
data: Data::from(&expected_winner_account_holding),
..Account::default()
};
@@ -4131,10 +4049,10 @@ pub mod tests {
// Execution of the token program to create new token for the pinata token
// definition and supply accounts
let total_supply: u128 = 10_000_000;
// instruction: [0x00 || total_supply (little-endian 16 bytes) || name (6 bytes)]
let mut instruction = vec![0; 23];
instruction[1..17].copy_from_slice(&total_supply.to_le_bytes());
instruction[17..].copy_from_slice(b"PINATA");
let instruction = token_core::Instruction::NewFungibleDefinition {
name: String::from("PINATA"),
total_supply,
};
let message = public_transaction::Message::try_new(
token.id(),
vec![pinata_token_definition_id, pinata_token_holding_id],
@@ -4146,9 +4064,8 @@ pub mod tests {
let tx = PublicTransaction::new(message, witness_set);
state.transition_from_public_transaction(&tx).unwrap();
// Execution of the token program transfer just to initialize the winner token account
let mut instruction = vec![0; 23];
instruction[0] = 2;
// Execution of winner's token holding account initialization
let instruction = token_core::Instruction::InitializeAccount;
let message = public_transaction::Message::try_new(
token.id(),
vec![pinata_token_definition_id, winner_token_holding_id],