diff --git a/Cargo.lock b/Cargo.lock index 08748b40..ab9dee71 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -374,7 +374,7 @@ dependencies = [ "ark-std", "derivative", "hashbrown 0.13.2", - "itertools", + "itertools 0.10.5", "num-traits", "zeroize", ] @@ -391,7 +391,7 @@ dependencies = [ "ark-std", "derivative", "digest 0.10.7", - "itertools", + "itertools 0.10.5", "num-bigint 0.4.6", "num-traits", "paste", @@ -2145,6 +2145,15 @@ dependencies = [ "either", ] +[[package]] +name = "itertools" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569" +dependencies = [ + "either", +] + [[package]] name = "itoa" version = "1.0.11" @@ -2282,6 +2291,43 @@ version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" +[[package]] +name = "litesvm" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7b24683a28745e9931facef01e786a38bf91723b87fbed98950e4d78d48b4b5" +dependencies = [ + "bincode", + "indexmap 2.6.0", + "itertools 0.12.1", + "log", + "solana-address-lookup-table-program", + "solana-bpf-loader-program", + "solana-compute-budget-program", + "solana-config-program", + "solana-loader-v4-program", + "solana-program", + "solana-program-runtime", + "solana-sdk", + "solana-stake-program", + "solana-system-program", + "solana-vote-program", + "thiserror", +] + +[[package]] +name = "litesvm-token" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c03b0ae6d1fadc9ee6fbe9cdde9244e808127e8ace0877b32070fb12381d0b99" +dependencies = [ + "litesvm", + "smallvec", + "solana-sdk", + "spl-associated-token-account 3.0.4", + "spl-token 3.5.0", +] + [[package]] name = "lock_api" version = "0.4.12" @@ -3377,7 +3423,12 @@ dependencies = [ "anchor-lang", "anchor-spl", "bytemuck", + "litesvm", + "litesvm-token", "sablier-utils", + "solana-sdk", + "spl-associated-token-account 1.1.3", + "spl-token 3.5.0", ] [[package]] @@ -3394,7 +3445,11 @@ name = "sablier-sdk" version = "1.2.1" dependencies = [ "anchor-lang", + "litesvm", + "litesvm-token", + "sablier-network-program", "sablier-thread-program", + "solana-sdk", ] [[package]] @@ -3757,12 +3812,52 @@ dependencies = [ "solana-sdk", "spl-token 4.0.0", "spl-token-2022 1.0.0", - "spl-token-group-interface", - "spl-token-metadata-interface", + "spl-token-group-interface 0.1.0", + "spl-token-metadata-interface 0.2.0", "thiserror", "zstd", ] +[[package]] +name = "solana-address-lookup-table-program" +version = "1.18.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed8aab3582ef7422bd8936f23b2e275f2046450497c7d9363f94b4038792c7c9" +dependencies = [ + "bincode", + "bytemuck", + "log", + "num-derive 0.4.2", + "num-traits", + "rustc_version", + "serde", + "solana-frozen-abi", + "solana-frozen-abi-macro", + "solana-program", + "solana-program-runtime", + "solana-sdk", + "thiserror", +] + +[[package]] +name = "solana-bpf-loader-program" +version = "1.18.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c52233e6e755f8e373e98360fdcb7c1be2f687dd77f28fee1b729dbb4dcca5c" +dependencies = [ + "bincode", + "byteorder", + "libsecp256k1", + "log", + "scopeguard", + "solana-measure", + "solana-program-runtime", + "solana-sdk", + "solana-zk-token-sdk", + "solana_rbpf", + "thiserror", +] + [[package]] name = "solana-clap-utils" version = "1.18.25" @@ -3829,6 +3924,16 @@ dependencies = [ "tokio", ] +[[package]] +name = "solana-compute-budget-program" +version = "1.18.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "15bd6622368e53d2ce779c86b1f4b6c3d7d9bff9fa349d46d5395db041d76e43" +dependencies = [ + "solana-program-runtime", + "solana-sdk", +] + [[package]] name = "solana-config-program" version = "1.18.25" @@ -3914,6 +4019,19 @@ dependencies = [ "thiserror", ] +[[package]] +name = "solana-loader-v4-program" +version = "1.18.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "305a01a37cb1d61bc17d4fbac110fa8ae67f2d8009f73533abe30a08c931e07b" +dependencies = [ + "log", + "solana-measure", + "solana-program-runtime", + "solana-sdk", + "solana_rbpf", +] + [[package]] name = "solana-logger" version = "1.18.25" @@ -4026,7 +4144,7 @@ dependencies = [ "console_log", "curve25519-dalek", "getrandom 0.2.15", - "itertools", + "itertools 0.10.5", "js-sys", "lazy_static", "libc", @@ -4066,7 +4184,7 @@ dependencies = [ "bincode", "eager", "enum-iterator", - "itertools", + "itertools 0.10.5", "libc", "log", "num-derive 0.4.2", @@ -4118,7 +4236,7 @@ dependencies = [ "async-mutex", "async-trait", "futures", - "itertools", + "itertools 0.10.5", "lazy_static", "log", "quinn", @@ -4247,7 +4365,7 @@ dependencies = [ "ed25519-dalek-bip32", "generic-array", "hmac 0.12.1", - "itertools", + "itertools 0.10.5", "js-sys", "lazy_static", "libsecp256k1", @@ -4300,6 +4418,21 @@ version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "468aa43b7edb1f9b7b7b686d5c3aeb6630dc1708e86e31343499dd5c4d775183" +[[package]] +name = "solana-stake-program" +version = "1.18.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "764b9acc6d994f650d9f8a6b8714e9e3827c70e3156d3d103739e3191dbba7d6" +dependencies = [ + "bincode", + "log", + "rustc_version", + "solana-config-program", + "solana-program-runtime", + "solana-sdk", + "solana-vote-program", +] + [[package]] name = "solana-streamer" version = "1.18.25" @@ -4312,7 +4445,7 @@ dependencies = [ "futures-util", "histogram", "indexmap 2.6.0", - "itertools", + "itertools 0.10.5", "libc", "log", "nix", @@ -4333,6 +4466,20 @@ dependencies = [ "x509-parser", ] +[[package]] +name = "solana-system-program" +version = "1.18.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e9a7c1fc46057d971a7daaf45051f35d8beef15b71986caac362b489afeba80c" +dependencies = [ + "bincode", + "log", + "serde", + "serde_derive", + "solana-program-runtime", + "solana-sdk", +] + [[package]] name = "solana-thin-client" version = "1.18.25" @@ -4463,7 +4610,7 @@ dependencies = [ "byteorder", "curve25519-dalek", "getrandom 0.1.16", - "itertools", + "itertools 0.10.5", "lazy_static", "merlin", "num-derive 0.4.2", @@ -4552,6 +4699,22 @@ dependencies = [ "thiserror", ] +[[package]] +name = "spl-associated-token-account" +version = "3.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "143109d789171379e6143ef23191786dfaac54289ad6e7917cfb26b36c432b10" +dependencies = [ + "assert_matches", + "borsh 1.5.1", + "num-derive 0.4.2", + "num-traits", + "solana-program", + "spl-token 4.0.0", + "spl-token-2022 3.0.4", + "thiserror", +] + [[package]] name = "spl-discriminator" version = "0.1.0" @@ -4560,7 +4723,18 @@ checksum = "cce5d563b58ef1bb2cdbbfe0dfb9ffdc24903b10ae6a4df2d8f425ece375033f" dependencies = [ "bytemuck", "solana-program", - "spl-discriminator-derive", + "spl-discriminator-derive 0.1.2", +] + +[[package]] +name = "spl-discriminator" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "210101376962bb22bb13be6daea34656ea1cbc248fce2164b146e39203b55e03" +dependencies = [ + "bytemuck", + "solana-program", + "spl-discriminator-derive 0.2.0", ] [[package]] @@ -4570,7 +4744,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "07fd7858fc4ff8fb0e34090e41d7eb06a823e1057945c26d480bfc21d2338a93" dependencies = [ "quote", - "spl-discriminator-syn", + "spl-discriminator-syn 0.1.2", + "syn 2.0.79", +] + +[[package]] +name = "spl-discriminator-derive" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9e8418ea6269dcfb01c712f0444d2c75542c04448b480e87de59d2865edc750" +dependencies = [ + "quote", + "spl-discriminator-syn 0.2.0", "syn 2.0.79", ] @@ -4587,6 +4772,19 @@ dependencies = [ "thiserror", ] +[[package]] +name = "spl-discriminator-syn" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c1f05593b7ca9eac7caca309720f2eafb96355e037e6d373b909a80fe7b69b9" +dependencies = [ + "proc-macro2", + "quote", + "sha2 0.10.8", + "syn 2.0.79", + "thiserror", +] + [[package]] name = "spl-memo" version = "3.0.1" @@ -4615,7 +4813,20 @@ dependencies = [ "bytemuck", "solana-program", "solana-zk-token-sdk", - "spl-program-error", + "spl-program-error 0.3.0", +] + +[[package]] +name = "spl-pod" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c52d84c55efeef8edcc226743dc089d7e3888b8e3474569aa3eff152b37b9996" +dependencies = [ + "borsh 1.5.1", + "bytemuck", + "solana-program", + "solana-zk-token-sdk", + "spl-program-error 0.4.4", ] [[package]] @@ -4627,7 +4838,20 @@ dependencies = [ "num-derive 0.4.2", "num-traits", "solana-program", - "spl-program-error-derive", + "spl-program-error-derive 0.3.2", + "thiserror", +] + +[[package]] +name = "spl-program-error" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e45a49acb925db68aa501b926096b2164adbdcade7a0c24152af9f0742d0a602" +dependencies = [ + "num-derive 0.4.2", + "num-traits", + "solana-program", + "spl-program-error-derive 0.4.1", "thiserror", ] @@ -4643,6 +4867,18 @@ dependencies = [ "syn 2.0.79", ] +[[package]] +name = "spl-program-error-derive" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6d375dd76c517836353e093c2dbb490938ff72821ab568b545fd30ab3256b3e" +dependencies = [ + "proc-macro2", + "quote", + "sha2 0.10.8", + "syn 2.0.79", +] + [[package]] name = "spl-tlv-account-resolution" version = "0.4.0" @@ -4651,10 +4887,10 @@ checksum = "062e148d3eab7b165582757453632ffeef490c02c86a48bfdb4988f63eefb3b9" dependencies = [ "bytemuck", "solana-program", - "spl-discriminator", - "spl-pod", - "spl-program-error", - "spl-type-length-value", + "spl-discriminator 0.1.0", + "spl-pod 0.1.0", + "spl-program-error 0.3.0", + "spl-type-length-value 0.3.0", ] [[package]] @@ -4665,10 +4901,24 @@ checksum = "615d381f48ddd2bb3c57c7f7fb207591a2a05054639b18a62e785117dd7a8683" dependencies = [ "bytemuck", "solana-program", - "spl-discriminator", - "spl-pod", - "spl-program-error", - "spl-type-length-value", + "spl-discriminator 0.1.0", + "spl-pod 0.1.0", + "spl-program-error 0.3.0", + "spl-type-length-value 0.3.0", +] + +[[package]] +name = "spl-tlv-account-resolution" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fab8edfd37be5fa17c9e42c1bff86abbbaf0494b031b37957f2728ad2ff842ba" +dependencies = [ + "bytemuck", + "solana-program", + "spl-discriminator 0.2.5", + "spl-pod 0.2.5", + "spl-program-error 0.4.4", + "spl-type-length-value 0.4.6", ] [[package]] @@ -4733,11 +4983,11 @@ dependencies = [ "solana-program", "solana-zk-token-sdk", "spl-memo 4.0.0", - "spl-pod", + "spl-pod 0.1.0", "spl-token 4.0.0", - "spl-token-metadata-interface", + "spl-token-metadata-interface 0.2.0", "spl-transfer-hook-interface 0.3.0", - "spl-type-length-value", + "spl-type-length-value 0.3.0", "thiserror", ] @@ -4756,12 +5006,36 @@ dependencies = [ "solana-security-txt", "solana-zk-token-sdk", "spl-memo 4.0.0", - "spl-pod", + "spl-pod 0.1.0", "spl-token 4.0.0", - "spl-token-group-interface", - "spl-token-metadata-interface", + "spl-token-group-interface 0.1.0", + "spl-token-metadata-interface 0.2.0", "spl-transfer-hook-interface 0.4.1", - "spl-type-length-value", + "spl-type-length-value 0.3.0", + "thiserror", +] + +[[package]] +name = "spl-token-2022" +version = "3.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b01d1b2851964e257187c0bca43a0de38d0af59192479ca01ac3e2b58b1bd95a" +dependencies = [ + "arrayref", + "bytemuck", + "num-derive 0.4.2", + "num-traits", + "num_enum 0.7.3", + "solana-program", + "solana-security-txt", + "solana-zk-token-sdk", + "spl-memo 4.0.0", + "spl-pod 0.2.5", + "spl-token 4.0.0", + "spl-token-group-interface 0.2.5", + "spl-token-metadata-interface 0.3.5", + "spl-transfer-hook-interface 0.6.5", + "spl-type-length-value 0.4.6", "thiserror", ] @@ -4773,9 +5047,22 @@ checksum = "b889509d49fa74a4a033ca5dae6c2307e9e918122d97e58562f5c4ffa795c75d" dependencies = [ "bytemuck", "solana-program", - "spl-discriminator", - "spl-pod", - "spl-program-error", + "spl-discriminator 0.1.0", + "spl-pod 0.1.0", + "spl-program-error 0.3.0", +] + +[[package]] +name = "spl-token-group-interface" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "014817d6324b1e20c4bbc883e8ee30a5faa13e59d91d1b2b95df98b920150c17" +dependencies = [ + "bytemuck", + "solana-program", + "spl-discriminator 0.2.5", + "spl-pod 0.2.5", + "spl-program-error 0.4.4", ] [[package]] @@ -4786,10 +5073,24 @@ checksum = "4c16ce3ba6979645fb7627aa1e435576172dd63088dc7848cb09aa331fa1fe4f" dependencies = [ "borsh 0.10.4", "solana-program", - "spl-discriminator", - "spl-pod", - "spl-program-error", - "spl-type-length-value", + "spl-discriminator 0.1.0", + "spl-pod 0.1.0", + "spl-program-error 0.3.0", + "spl-type-length-value 0.3.0", +] + +[[package]] +name = "spl-token-metadata-interface" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3da00495b602ebcf5d8ba8b3ecff1ee454ce4c125c9077747be49c2d62335ba" +dependencies = [ + "borsh 1.5.1", + "solana-program", + "spl-discriminator 0.2.5", + "spl-pod 0.2.5", + "spl-program-error 0.4.4", + "spl-type-length-value 0.4.6", ] [[package]] @@ -4801,11 +5102,11 @@ dependencies = [ "arrayref", "bytemuck", "solana-program", - "spl-discriminator", - "spl-pod", - "spl-program-error", + "spl-discriminator 0.1.0", + "spl-pod 0.1.0", + "spl-program-error 0.3.0", "spl-tlv-account-resolution 0.4.0", - "spl-type-length-value", + "spl-type-length-value 0.3.0", ] [[package]] @@ -4817,11 +5118,27 @@ dependencies = [ "arrayref", "bytemuck", "solana-program", - "spl-discriminator", - "spl-pod", - "spl-program-error", + "spl-discriminator 0.1.0", + "spl-pod 0.1.0", + "spl-program-error 0.3.0", "spl-tlv-account-resolution 0.5.1", - "spl-type-length-value", + "spl-type-length-value 0.3.0", +] + +[[package]] +name = "spl-transfer-hook-interface" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9b5c08a89838e5a2931f79b17f611857f281a14a2100968a3ccef352cb7414b" +dependencies = [ + "arrayref", + "bytemuck", + "solana-program", + "spl-discriminator 0.2.5", + "spl-pod 0.2.5", + "spl-program-error 0.4.4", + "spl-tlv-account-resolution 0.6.5", + "spl-type-length-value 0.4.6", ] [[package]] @@ -4832,9 +5149,22 @@ checksum = "a468e6f6371f9c69aae760186ea9f1a01c2908351b06a5e0026d21cfc4d7ecac" dependencies = [ "bytemuck", "solana-program", - "spl-discriminator", - "spl-pod", - "spl-program-error", + "spl-discriminator 0.1.0", + "spl-pod 0.1.0", + "spl-program-error 0.3.0", +] + +[[package]] +name = "spl-type-length-value" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c872f93d0600e743116501eba2d53460e73a12c9a496875a42a7d70e034fe06d" +dependencies = [ + "bytemuck", + "solana-program", + "spl-discriminator 0.2.5", + "spl-pod 0.2.5", + "spl-program-error 0.4.4", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index a4b39295..aaa8e9e8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -36,6 +36,8 @@ clap = { version = "4.5" } dirs-next = "2.0.0" futures = "0.3" indicatif = "0.17" +litesvm = "0.2" +litesvm-token = "0.2" log = "0.4" nom = "~7" proc-macro2 = "1.0" diff --git a/programs/network/Cargo.toml b/programs/network/Cargo.toml index 36a94c8b..b3ab3615 100644 --- a/programs/network/Cargo.toml +++ b/programs/network/Cargo.toml @@ -26,3 +26,12 @@ anchor-lang.workspace = true anchor-spl = { features = ["mint", "token"], workspace = true } sablier-utils.workspace = true bytemuck = { workspace = true, features = ["derive", "min_const_generics"] } + +[dev-dependencies] +litesvm.workspace = true +litesvm-token.workspace = true +solana-sdk.workspace = true +spl-token = { workspace = true, features = ["no-entrypoint"] } +spl-associated-token-account = { workspace = true, features = [ + "no-entrypoint", +] } diff --git a/programs/network/tests/integration.rs b/programs/network/tests/integration.rs new file mode 100644 index 00000000..4b9d6803 --- /dev/null +++ b/programs/network/tests/integration.rs @@ -0,0 +1,35 @@ +use litesvm::LiteSVM; +use litesvm_token::CreateMint; +use solana_sdk::{native_token::LAMPORTS_PER_SOL, signature::Keypair, signer::Signer}; + +mod test_instructions; +mod utils; + +fn setup() -> (LiteSVM, Keypair) { + let mut svm = LiteSVM::new(); + + let path = format!( + "{}/../deploy/sablier_network_program.so", + env!("CARGO_TARGET_TMPDIR") + ); + svm.add_program_from_file(sablier_network_program::ID, path) + .unwrap(); + + let admin_kp = Keypair::new(); + + svm.airdrop(&admin_kp.pubkey(), 10 * LAMPORTS_PER_SOL) + .unwrap(); + + (svm, admin_kp) +} + +#[test] +pub fn integration_test() { + let (mut svm, admin_kp) = setup(); + + let mint = CreateMint::new(&mut svm, &admin_kp).send().unwrap(); + + test_instructions::initialize(&mut svm, &admin_kp, &mint).unwrap(); + test_instructions::pool_create(&mut svm, &admin_kp).unwrap(); + test_instructions::worker_create(&mut svm, &admin_kp, &mint).unwrap(); +} diff --git a/programs/network/tests/test_instructions/initialize.rs b/programs/network/tests/test_instructions/initialize.rs new file mode 100644 index 00000000..03cf8296 --- /dev/null +++ b/programs/network/tests/test_instructions/initialize.rs @@ -0,0 +1,60 @@ +use litesvm::{types::FailedTransactionMetadata, LiteSVM}; +use sablier_network_program::{ + constants::SEED_REGISTRY, + state::{Config, Registry, Snapshot}, +}; +use solana_sdk::{ + pubkey::Pubkey, signature::Keypair, signer::Signer, system_program, transaction::Transaction, +}; + +use crate::utils::{build_ix, get_anchor_account}; + +pub fn initialize( + svm: &mut LiteSVM, + admin_kp: &Keypair, + mint: &Pubkey, +) -> Result<(), FailedTransactionMetadata> { + let admin = admin_kp.pubkey(); + + let (registry, registry_bump) = + Pubkey::find_program_address(&[SEED_REGISTRY], &sablier_network_program::ID); + let ix = build_ix( + sablier_network_program::accounts::Initialize { + admin, + config: Config::pubkey(), + mint: *mint, + registry, + snapshot: Snapshot::pubkey(0), + system_program: system_program::ID, + }, + sablier_network_program::instruction::Initialize {}, + ); + + let blockhash = svm.latest_blockhash(); + let tx = Transaction::new_signed_with_payer(&[ix], Some(&admin), &[&admin_kp], blockhash); + svm.send_transaction(tx)?; + + // CHECKS + + let config: Config = get_anchor_account(svm, &Config::pubkey()); + assert_eq!(config.admin, admin); + assert_eq!(config.mint, *mint); + assert_eq!(config.hasher_thread, Pubkey::default()); + assert_eq!(config.hasher_thread, Pubkey::default()); + + let registry: Registry = get_anchor_account(svm, &Registry::pubkey()); + assert_eq!(registry.current_epoch, 0); + assert_eq!(registry.locked, false); + assert_eq!(registry.nonce, 0); + assert_eq!(registry.total_pools, 0); + assert_eq!(registry.total_unstakes, 0); + assert_eq!(registry.total_workers, 0); + assert_eq!(registry.bump, registry_bump); + + let snapshot: Snapshot = get_anchor_account(svm, &Snapshot::pubkey(0)); + assert_eq!(snapshot.id, 0); + assert_eq!(snapshot.total_frames, 0); + assert_eq!(snapshot.total_stake, 0); + + Ok(()) +} diff --git a/programs/network/tests/test_instructions/mod.rs b/programs/network/tests/test_instructions/mod.rs new file mode 100644 index 00000000..2918d65e --- /dev/null +++ b/programs/network/tests/test_instructions/mod.rs @@ -0,0 +1,7 @@ +mod initialize; +mod pool_create; +mod worker_create; + +pub use initialize::*; +pub use pool_create::*; +pub use worker_create::*; diff --git a/programs/network/tests/test_instructions/pool_create.rs b/programs/network/tests/test_instructions/pool_create.rs new file mode 100644 index 00000000..ecb66956 --- /dev/null +++ b/programs/network/tests/test_instructions/pool_create.rs @@ -0,0 +1,45 @@ +use std::collections::VecDeque; + +use anchor_lang::system_program; +use litesvm::{types::FailedTransactionMetadata, LiteSVM}; +use sablier_network_program::state::{Config, Pool, Registry}; +use solana_sdk::{signature::Keypair, signer::Signer, transaction::Transaction}; + +use crate::utils::{build_ix, get_anchor_account}; + +pub fn pool_create(svm: &mut LiteSVM, admin_kp: &Keypair) -> Result<(), FailedTransactionMetadata> { + let admin = admin_kp.pubkey(); + + let ix = build_ix( + sablier_network_program::accounts::PoolCreate { + config: Config::pubkey(), + system_program: system_program::ID, + payer: admin, + pool: Pool::pubkey(0), + admin, + registry: Registry::pubkey(), + }, + sablier_network_program::instruction::PoolCreate {}, + ); + + let blockhash = svm.latest_blockhash(); + let tx = Transaction::new_signed_with_payer(&[ix], Some(&admin), &[&admin_kp], blockhash); + svm.send_transaction(tx)?; + + // CHECKS + + let registry: Registry = get_anchor_account(svm, &Registry::pubkey()); + assert_eq!(registry.current_epoch, 0); + assert_eq!(registry.locked, false); + assert_eq!(registry.nonce, 0); + assert_eq!(registry.total_pools, 1); + assert_eq!(registry.total_unstakes, 0); + assert_eq!(registry.total_workers, 0); + + let pool: Pool = get_anchor_account(svm, &Pool::pubkey(0)); + assert_eq!(pool.id, 0); + assert_eq!(pool.size, 1); + assert_eq!(pool.workers, VecDeque::new()); + + Ok(()) +} diff --git a/programs/network/tests/test_instructions/worker_create.rs b/programs/network/tests/test_instructions/worker_create.rs new file mode 100644 index 00000000..04997e96 --- /dev/null +++ b/programs/network/tests/test_instructions/worker_create.rs @@ -0,0 +1,66 @@ +use litesvm::{types::FailedTransactionMetadata, LiteSVM}; +use sablier_network_program::state::{Config, Registry, Worker}; +use solana_sdk::{ + native_token::LAMPORTS_PER_SOL, pubkey::Pubkey, signature::Keypair, signer::Signer, + system_program, transaction::Transaction, +}; +use spl_associated_token_account::get_associated_token_address; + +use crate::utils::{build_ix, get_anchor_account}; + +pub fn worker_create( + svm: &mut LiteSVM, + admin_kp: &Keypair, + mint: &Pubkey, +) -> Result<(), FailedTransactionMetadata> { + let admin = admin_kp.pubkey(); + let worker_authority = Keypair::new(); + + svm.airdrop(&worker_authority.pubkey(), 2 * LAMPORTS_PER_SOL)?; + + let worker = Worker::pubkey(0); + let worker_tokens = get_associated_token_address(&worker, mint); + + let ix = build_ix( + sablier_network_program::accounts::WorkerCreate { + authority: admin, + config: Config::pubkey(), + mint: *mint, + registry: Registry::pubkey(), + signatory: worker_authority.pubkey(), + worker, + worker_tokens, + system_program: system_program::ID, + associated_token_program: spl_associated_token_account::ID, + token_program: spl_token::ID, + }, + sablier_network_program::instruction::WorkerCreate {}, + ); + + let blockhash = svm.latest_blockhash(); + let tx = Transaction::new_signed_with_payer( + &[ix], + Some(&admin), + &[&admin_kp, &worker_authority], + blockhash, + ); + svm.send_transaction(tx)?; + + let worker: Worker = get_anchor_account(svm, &Worker::pubkey(0)); + assert_eq!(worker.id, 0); + assert_eq!(worker.total_delegations, 0); + assert_eq!(worker.authority, admin); + assert_eq!(worker.commission_balance, 0); + assert_eq!(worker.commission_rate, 0); + assert_eq!(worker.signatory, worker_authority.pubkey()); + + let registry: Registry = get_anchor_account(svm, &Registry::pubkey()); + assert_eq!(registry.current_epoch, 0); + assert_eq!(registry.locked, false); + assert_eq!(registry.nonce, 0); + assert_eq!(registry.total_pools, 1); + assert_eq!(registry.total_unstakes, 0); + assert_eq!(registry.total_workers, 1); + + Ok(()) +} diff --git a/programs/network/tests/utils/mod.rs b/programs/network/tests/utils/mod.rs new file mode 100644 index 00000000..7821c6e1 --- /dev/null +++ b/programs/network/tests/utils/mod.rs @@ -0,0 +1,16 @@ +use anchor_lang::{AccountDeserialize, InstructionData, ToAccountMetas}; +use litesvm::LiteSVM; +use solana_sdk::{instruction::Instruction, pubkey::Pubkey}; + +pub fn build_ix(accounts: impl ToAccountMetas, data: impl InstructionData) -> Instruction { + Instruction { + program_id: sablier_network_program::ID, + accounts: accounts.to_account_metas(None), + data: data.data(), + } +} + +pub fn get_anchor_account(svm: &mut LiteSVM, key: &Pubkey) -> T { + let account = svm.get_account(key).unwrap(); + T::try_deserialize(&mut &account.data[..]).unwrap() +} diff --git a/sdk/Cargo.toml b/sdk/Cargo.toml index 799e0f03..f774758b 100644 --- a/sdk/Cargo.toml +++ b/sdk/Cargo.toml @@ -17,5 +17,11 @@ name = "sablier_sdk" anchor-lang.workspace = true sablier-thread-program = { workspace = true, features = ["cpi"] } +[dev-dependencies] +sablier-network-program = { workspace = true, features = ["cpi"] } +litesvm.workspace = true +litesvm-token.workspace = true +solana-sdk.workspace = true + [features] default = [] diff --git a/sdk/src/lib.rs b/sdk/src/lib.rs index 582c4f4e..a85a2980 100644 --- a/sdk/src/lib.rs +++ b/sdk/src/lib.rs @@ -1,3 +1,6 @@ +#[cfg(test)] +mod litesvm; + pub use sablier_thread_program::errors; pub use sablier_thread_program::program::ThreadProgram; pub use sablier_thread_program::ID; diff --git a/sdk/src/litesvm/mod.rs b/sdk/src/litesvm/mod.rs new file mode 100644 index 00000000..eb2f6fcc --- /dev/null +++ b/sdk/src/litesvm/mod.rs @@ -0,0 +1,43 @@ +use std::path::Path; + +use litesvm::{ + types::{FailedTransactionMetadata, TransactionResult}, + LiteSVM, +}; +use litesvm_token::{CreateAssociatedTokenAccount, CreateMint, MintTo}; +use solana_sdk::{ + native_token::LAMPORTS_PER_SOL, pubkey::Pubkey, signature::Keypair, signer::Signer, +}; + +fn setup_test_environment( + network_program_path: impl AsRef, + thread_program_path: impl AsRef, +) -> Result<(), FailedTransactionMetadata> { + let mut svm = LiteSVM::new(); + + let sablier_admin_kp = Keypair::new(); + let sablier_admin_pk = sablier_admin_kp.pubkey(); + + svm.airdrop(&sablier_admin_pk, 10 * LAMPORTS_PER_SOL)?; + + svm.add_program_from_file(sablier_network_program::id(), network_program_path.as_ref()) + .unwrap(); + svm.add_program_from_file(sablier_thread_program::id(), thread_program_path.as_ref()) + .unwrap(); + + let mint = setup_sablier_token(&mut svm, &sablier_admin_kp)?; + + Ok(()) +} + +fn setup_sablier_token( + svm: &mut LiteSVM, + sablier_admin_kp: &Keypair, +) -> Result { + let mint = CreateMint::new(svm, sablier_admin_kp).send()?; + + let ata = CreateAssociatedTokenAccount::new(svm, sablier_admin_kp, &mint).send()?; + MintTo::new(svm, sablier_admin_kp, &mint, &ata, 10).send()?; + + Ok(mint) +}