diff --git a/.github/.ghaignore b/.github/.ghaignore index 3ad0e17a7..1397efbc9 100644 --- a/.github/.ghaignore +++ b/.github/.ghaignore @@ -34,15 +34,7 @@ tokens/token-extensions/group/quasar # CPI quasar project uses subdirectories (hand/ and lever/) instead of a root Quasar.toml basics/cross-program-invocation/quasar -# has Cargo.toml but no Quasar.toml -tokens/spl-token-minter/quasar -tokens/external-delegate-token-master/quasar -tokens/nft-minter/quasar -tokens/nft-operations/quasar -tokens/token-swap/quasar - -# build failed - outdated quasar-lang API (no AccountView.data, no log_64) -oracles/pyth/quasar + # error in tests tokens/external-delegate-token-master/anchor diff --git a/.github/workflows/quasar.yml b/.github/workflows/quasar.yml index 2a416810c..25e604b64 100644 --- a/.github/workflows/quasar.yml +++ b/.github/workflows/quasar.yml @@ -199,7 +199,16 @@ jobs: with: solana-cli-version: stable - name: Install Quasar CLI - run: cargo install --git https://github.com/blueshift-gg/quasar quasar-cli --locked + # Pinned to quasar rev 3d6fb0d8 (the HEAD this migration was written + # against, immediately after PRs #195 + #196). The next merged PR + # (#198 "idl-redesign-clean", rev 096c8f7c) regressed `quasar build` + # for flat-layout projects: the new IDL flow chdirs to + # `crate_path.parent()` which evaluates to an empty PathBuf when + # the program crate is at the project root (src/lib.rs in `.`), + # causing posix_spawn child chdir("") to fail with ENOENT before + # any compilation begins. Symptom in CI is a bare "Anyhow error". + # Unpin once upstream lands a fix that handles the flat layout. + run: cargo install --git https://github.com/blueshift-gg/quasar --rev 3d6fb0d8 quasar-cli --locked - name: Build and Test with Stable run: | source build_and_test.sh diff --git a/basics/account-data/quasar/Cargo.toml b/basics/account-data/quasar/Cargo.toml index 993ca2b42..bfc56484d 100644 --- a/basics/account-data/quasar/Cargo.toml +++ b/basics/account-data/quasar/Cargo.toml @@ -22,7 +22,7 @@ client = [] debug = [] [dependencies] -quasar-lang = { git = "https://github.com/blueshift-gg/quasar" } +quasar-lang = { git = "https://github.com/blueshift-gg/quasar", branch = "master" } solana-instruction = { version = "3.2.0" } [dev-dependencies] diff --git a/basics/account-data/quasar/src/instructions/create.rs b/basics/account-data/quasar/src/instructions/create.rs index 1a3503e00..efd4fe733 100644 --- a/basics/account-data/quasar/src/instructions/create.rs +++ b/basics/account-data/quasar/src/instructions/create.rs @@ -8,9 +8,9 @@ use { pub struct CreateAddressInfo { #[account(mut)] pub payer: Signer, - #[account(mut, init, payer = payer, seeds = AddressInfo::seeds(payer), bump)] + #[account(mut, init, payer = payer, address = AddressInfo::seeds(payer.address()))] pub address_info: Account, - pub system_program: Program, + pub system_program: Program, } #[inline(always)] diff --git a/basics/checking-accounts/quasar/Cargo.toml b/basics/checking-accounts/quasar/Cargo.toml index eec54aa7d..f3cbe232a 100644 --- a/basics/checking-accounts/quasar/Cargo.toml +++ b/basics/checking-accounts/quasar/Cargo.toml @@ -22,7 +22,7 @@ client = [] debug = [] [dependencies] -quasar-lang = { git = "https://github.com/blueshift-gg/quasar" } +quasar-lang = { git = "https://github.com/blueshift-gg/quasar", branch = "master" } solana-instruction = { version = "3.2.0" } [dev-dependencies] diff --git a/basics/checking-accounts/quasar/src/instructions/check_accounts.rs b/basics/checking-accounts/quasar/src/instructions/check_accounts.rs index f25b55aef..aa1efda92 100644 --- a/basics/checking-accounts/quasar/src/instructions/check_accounts.rs +++ b/basics/checking-accounts/quasar/src/instructions/check_accounts.rs @@ -3,7 +3,7 @@ use quasar_lang::prelude::*; /// Demonstrates Quasar's account type constraints: /// - `Signer`: automatically verified as a transaction signer /// - `UncheckedAccount`: no runtime checks (opt-in unchecked access) -/// - `Program`: verified as the system program (executable + address check) +/// - `Program`: verified as the system program (executable + address check) /// /// Note: Anchor's `#[account(owner = id())]` owner constraint is not directly available /// in Quasar. Owner checks can be done manually in the instruction body if needed. @@ -18,7 +18,7 @@ pub struct CheckAccounts { #[account(mut)] pub account_to_change: UncheckedAccount, /// Checks the account is executable and matches the system program address. - pub system_program: Program, + pub system_program: Program, } #[inline(always)] diff --git a/basics/close-account/quasar/Cargo.toml b/basics/close-account/quasar/Cargo.toml index 9da62371f..61b2bd26f 100644 --- a/basics/close-account/quasar/Cargo.toml +++ b/basics/close-account/quasar/Cargo.toml @@ -20,7 +20,7 @@ client = [] debug = [] [dependencies] -quasar-lang = { git = "https://github.com/blueshift-gg/quasar" } +quasar-lang = { git = "https://github.com/blueshift-gg/quasar", branch = "master" } solana-instruction = { version = "3.2.0" } [dev-dependencies] diff --git a/basics/close-account/quasar/src/instructions/close_user.rs b/basics/close-account/quasar/src/instructions/close_user.rs index ff56535f3..98f694f8a 100644 --- a/basics/close-account/quasar/src/instructions/close_user.rs +++ b/basics/close-account/quasar/src/instructions/close_user.rs @@ -1,18 +1,18 @@ use {crate::state::UserState, quasar_lang::prelude::*}; /// Accounts for closing a user account. -/// The `close = user` attribute in the Anchor version triggers an automatic epilogue. -/// In Quasar, we call `close()` explicitly — it zeros the discriminator, drains lamports -/// to the destination, reassigns the owner to the system program, and resizes to 0. +/// The `close(dest = user)` attribute mirrors Anchor's `close = user`: at the +/// derive epilogue Quasar zeroes the discriminator, drains lamports to the +/// destination, reassigns the owner to the system program, and resizes to 0. #[derive(Accounts)] pub struct CloseUser { #[account(mut)] pub user: Signer, - #[account(mut)] + #[account(mut, close(dest = user))] pub user_account: Account, } #[inline(always)] -pub fn handle_close_user(accounts: &mut CloseUser) -> Result<(), ProgramError> { - accounts.user_account.close(accounts.user.to_account_view()) +pub fn handle_close_user(_accounts: &mut CloseUser) -> Result<(), ProgramError> { + Ok(()) } diff --git a/basics/close-account/quasar/src/instructions/create_user.rs b/basics/close-account/quasar/src/instructions/create_user.rs index be2da0b88..9a0a16ef6 100644 --- a/basics/close-account/quasar/src/instructions/create_user.rs +++ b/basics/close-account/quasar/src/instructions/create_user.rs @@ -8,9 +8,9 @@ use { pub struct CreateUser { #[account(mut)] pub user: Signer, - #[account(mut, init, payer = user, seeds = UserState::seeds(user), bump)] + #[account(mut, init, payer = user, address = UserState::seeds(user.address()))] pub user_account: Account, - pub system_program: Program, + pub system_program: Program, } #[inline(always)] diff --git a/basics/counter/quasar/Cargo.toml b/basics/counter/quasar/Cargo.toml index 2ac1aa296..299c82d64 100644 --- a/basics/counter/quasar/Cargo.toml +++ b/basics/counter/quasar/Cargo.toml @@ -22,7 +22,7 @@ client = [] debug = [] [dependencies] -quasar-lang = { git = "https://github.com/blueshift-gg/quasar" } +quasar-lang = { git = "https://github.com/blueshift-gg/quasar", branch = "master" } solana-instruction = { version = "3.2.0" } [dev-dependencies] diff --git a/basics/counter/quasar/src/instructions/initialize_counter.rs b/basics/counter/quasar/src/instructions/initialize_counter.rs index c7335c0cf..d438f1274 100644 --- a/basics/counter/quasar/src/instructions/initialize_counter.rs +++ b/basics/counter/quasar/src/instructions/initialize_counter.rs @@ -7,9 +7,9 @@ use quasar_lang::prelude::*; pub struct InitializeCounter { #[account(mut)] pub payer: Signer, - #[account(mut, init, payer = payer, seeds = Counter::seeds(payer), bump)] + #[account(mut, init, payer = payer, address = Counter::seeds(payer.address()))] pub counter: Account, - pub system_program: Program, + pub system_program: Program, } #[inline(always)] diff --git a/basics/create-account/quasar/Cargo.toml b/basics/create-account/quasar/Cargo.toml index 2c3e2cae2..ef9df4f31 100644 --- a/basics/create-account/quasar/Cargo.toml +++ b/basics/create-account/quasar/Cargo.toml @@ -22,7 +22,7 @@ client = [] debug = [] [dependencies] -quasar-lang = { git = "https://github.com/blueshift-gg/quasar" } +quasar-lang = { git = "https://github.com/blueshift-gg/quasar", branch = "master" } solana-instruction = { version = "3.2.0" } [dev-dependencies] diff --git a/basics/create-account/quasar/src/instructions/create_system_account.rs b/basics/create-account/quasar/src/instructions/create_system_account.rs index 18f984ca0..c28253a9d 100644 --- a/basics/create-account/quasar/src/instructions/create_system_account.rs +++ b/basics/create-account/quasar/src/instructions/create_system_account.rs @@ -8,7 +8,7 @@ pub struct CreateSystemAccount { pub payer: Signer, #[account(mut)] pub new_account: Signer, - pub system_program: Program, + pub system_program: Program, } #[inline(always)] diff --git a/basics/cross-program-invocation/quasar/hand/Cargo.toml b/basics/cross-program-invocation/quasar/hand/Cargo.toml index f86dd8f0c..814a67965 100644 --- a/basics/cross-program-invocation/quasar/hand/Cargo.toml +++ b/basics/cross-program-invocation/quasar/hand/Cargo.toml @@ -21,7 +21,7 @@ client = [] debug = [] [dependencies] -quasar-lang = { git = "https://github.com/blueshift-gg/quasar" } +quasar-lang = { git = "https://github.com/blueshift-gg/quasar", branch = "master" } solana-instruction = { version = "3.2.0" } [dev-dependencies] diff --git a/basics/cross-program-invocation/quasar/hand/src/instructions/pull_lever.rs b/basics/cross-program-invocation/quasar/hand/src/instructions/pull_lever.rs index f602af292..95f1d7eb8 100644 --- a/basics/cross-program-invocation/quasar/hand/src/instructions/pull_lever.rs +++ b/basics/cross-program-invocation/quasar/hand/src/instructions/pull_lever.rs @@ -39,7 +39,7 @@ pub fn handle_pull_lever(accounts: &PullLever, name: &str) -> Result<(), Program i += 1; } - let mut cpi = DynCpiCall::<1, 128>::new(accounts.lever_program.address()); + let mut cpi = CpiDynamic::<1, 128>::new(accounts.lever_program.address()); cpi.push_account(accounts.power.to_account_view(), false, true)?; cpi.set_data(&data[..data_len])?; cpi.invoke() diff --git a/basics/cross-program-invocation/quasar/lever/Cargo.toml b/basics/cross-program-invocation/quasar/lever/Cargo.toml index fceab3f06..4e90b3304 100644 --- a/basics/cross-program-invocation/quasar/lever/Cargo.toml +++ b/basics/cross-program-invocation/quasar/lever/Cargo.toml @@ -21,7 +21,7 @@ client = [] debug = [] [dependencies] -quasar-lang = { git = "https://github.com/blueshift-gg/quasar" } +quasar-lang = { git = "https://github.com/blueshift-gg/quasar", branch = "master" } solana-instruction = { version = "3.2.0" } [dev-dependencies] diff --git a/basics/cross-program-invocation/quasar/lever/src/instructions/initialize.rs b/basics/cross-program-invocation/quasar/lever/src/instructions/initialize.rs index 832a8732b..e820b8517 100644 --- a/basics/cross-program-invocation/quasar/lever/src/instructions/initialize.rs +++ b/basics/cross-program-invocation/quasar/lever/src/instructions/initialize.rs @@ -8,9 +8,9 @@ use { pub struct InitializeLever { #[account(mut)] pub payer: Signer, - #[account(mut, init, payer = payer, seeds = PowerStatus::seeds(), bump)] + #[account(mut, init, payer = payer, address = PowerStatus::seeds())] pub power: Account, - pub system_program: Program, + pub system_program: Program, } #[inline(always)] diff --git a/basics/favorites/quasar/Cargo.toml b/basics/favorites/quasar/Cargo.toml index 3fbf2f1b4..90636759e 100644 --- a/basics/favorites/quasar/Cargo.toml +++ b/basics/favorites/quasar/Cargo.toml @@ -20,7 +20,7 @@ client = [] debug = [] [dependencies] -quasar-lang = { git = "https://github.com/blueshift-gg/quasar" } +quasar-lang = { git = "https://github.com/blueshift-gg/quasar", branch = "master" } solana-instruction = { version = "3.2.0" } [dev-dependencies] diff --git a/basics/favorites/quasar/src/instructions/set_favorites.rs b/basics/favorites/quasar/src/instructions/set_favorites.rs index f1c4e1f0b..ebb60bee7 100644 --- a/basics/favorites/quasar/src/instructions/set_favorites.rs +++ b/basics/favorites/quasar/src/instructions/set_favorites.rs @@ -9,9 +9,9 @@ use { pub struct SetFavorites { #[account(mut)] pub user: Signer, - #[account(mut, init_if_needed, payer = user, seeds = Favorites::seeds(user), bump)] + #[account(mut, init(idempotent), payer = user, address = Favorites::seeds(user.address()))] pub favorites: Account, - pub system_program: Program, + pub system_program: Program, } #[inline(always)] diff --git a/basics/pda-rent-payer/quasar/Cargo.toml b/basics/pda-rent-payer/quasar/Cargo.toml index a0af6710b..9e1398a16 100644 --- a/basics/pda-rent-payer/quasar/Cargo.toml +++ b/basics/pda-rent-payer/quasar/Cargo.toml @@ -22,7 +22,7 @@ client = [] debug = [] [dependencies] -quasar-lang = { git = "https://github.com/blueshift-gg/quasar" } +quasar-lang = { git = "https://github.com/blueshift-gg/quasar", branch = "master" } solana-instruction = { version = "3.2.0" } [dev-dependencies] diff --git a/basics/pda-rent-payer/quasar/src/instructions/create_new_account.rs b/basics/pda-rent-payer/quasar/src/instructions/create_new_account.rs index 3fdf30b91..da30f5900 100644 --- a/basics/pda-rent-payer/quasar/src/instructions/create_new_account.rs +++ b/basics/pda-rent-payer/quasar/src/instructions/create_new_account.rs @@ -1,4 +1,7 @@ -use quasar_lang::{prelude::*, sysvars::Sysvar}; +use { + crate::instructions::init_rent_vault::RentVault, + quasar_lang::{prelude::*, sysvars::Sysvar}, +}; /// Accounts for creating a new account funded by the rent vault PDA. /// The rent vault signs the create_account CPI via PDA seeds. @@ -6,9 +9,9 @@ use quasar_lang::{prelude::*, sysvars::Sysvar}; pub struct CreateNewAccount { #[account(mut)] pub new_account: Signer, - #[account(mut, seeds = [b"rent_vault"], bump)] + #[account(mut, address = RentVault::seeds())] pub rent_vault: UncheckedAccount, - pub system_program: Program, + pub system_program: Program, } #[inline(always)] diff --git a/basics/pda-rent-payer/quasar/src/instructions/init_rent_vault.rs b/basics/pda-rent-payer/quasar/src/instructions/init_rent_vault.rs index 191b46f45..c186c8453 100644 --- a/basics/pda-rent-payer/quasar/src/instructions/init_rent_vault.rs +++ b/basics/pda-rent-payer/quasar/src/instructions/init_rent_vault.rs @@ -1,5 +1,12 @@ use quasar_lang::prelude::*; +/// PDA seed marker for the rent-vault account. With the new derive grammar +/// (`address = `) we need a `Seeds` impl to validate the address; +/// `seeds = [b"rent_vault"]` is no longer accepted. +#[derive(Seeds)] +#[seeds(b"rent_vault")] +pub struct RentVault; + /// Accounts for funding the rent vault PDA. /// Transfers lamports from the payer to the vault via system program CPI. /// When lamports are sent to a new address, the system program creates @@ -8,9 +15,9 @@ use quasar_lang::prelude::*; pub struct InitRentVault { #[account(mut)] pub payer: Signer, - #[account(mut, seeds = [b"rent_vault"], bump)] + #[account(mut, address = RentVault::seeds())] pub rent_vault: UncheckedAccount, - pub system_program: Program, + pub system_program: Program, } #[inline(always)] diff --git a/basics/processing-instructions/quasar/Cargo.toml b/basics/processing-instructions/quasar/Cargo.toml index 26cf2e808..fe9ddd6c9 100644 --- a/basics/processing-instructions/quasar/Cargo.toml +++ b/basics/processing-instructions/quasar/Cargo.toml @@ -20,7 +20,7 @@ client = [] debug = [] [dependencies] -quasar-lang = { git = "https://github.com/blueshift-gg/quasar" } +quasar-lang = { git = "https://github.com/blueshift-gg/quasar", branch = "master" } solana-instruction = { version = "3.2.0" } [dev-dependencies] diff --git a/basics/program-derived-addresses/quasar/Cargo.toml b/basics/program-derived-addresses/quasar/Cargo.toml index 1f4e9e287..ba4323d0a 100644 --- a/basics/program-derived-addresses/quasar/Cargo.toml +++ b/basics/program-derived-addresses/quasar/Cargo.toml @@ -22,7 +22,7 @@ client = [] debug = [] [dependencies] -quasar-lang = { git = "https://github.com/blueshift-gg/quasar" } +quasar-lang = { git = "https://github.com/blueshift-gg/quasar", branch = "master" } solana-instruction = { version = "3.2.0" } [dev-dependencies] diff --git a/basics/program-derived-addresses/quasar/src/instructions/create.rs b/basics/program-derived-addresses/quasar/src/instructions/create.rs index 2b4210d08..3088b4221 100644 --- a/basics/program-derived-addresses/quasar/src/instructions/create.rs +++ b/basics/program-derived-addresses/quasar/src/instructions/create.rs @@ -9,9 +9,9 @@ use { pub struct CreatePageVisits { #[account(mut)] pub payer: Signer, - #[account(mut, init, payer = payer, seeds = PageVisits::seeds(payer), bump)] + #[account(mut, init, payer = payer, address = PageVisits::seeds(payer.address()))] pub page_visits: Account, - pub system_program: Program, + pub system_program: Program, } #[inline(always)] diff --git a/basics/realloc/quasar/Cargo.toml b/basics/realloc/quasar/Cargo.toml index d61ef5b9d..a6b5cbcb3 100644 --- a/basics/realloc/quasar/Cargo.toml +++ b/basics/realloc/quasar/Cargo.toml @@ -20,7 +20,7 @@ client = [] debug = [] [dependencies] -quasar-lang = { git = "https://github.com/blueshift-gg/quasar" } +quasar-lang = { git = "https://github.com/blueshift-gg/quasar", branch = "master" } solana-instruction = { version = "3.2.0" } [dev-dependencies] diff --git a/basics/realloc/quasar/src/instructions/initialize.rs b/basics/realloc/quasar/src/instructions/initialize.rs index ad652200d..82409c47b 100644 --- a/basics/realloc/quasar/src/instructions/initialize.rs +++ b/basics/realloc/quasar/src/instructions/initialize.rs @@ -11,7 +11,7 @@ pub struct Initialize { pub payer: Signer, #[account(mut, init, payer = payer)] pub message_account: Account, - pub system_program: Program, + pub system_program: Program, } #[inline(always)] diff --git a/basics/realloc/quasar/src/instructions/update.rs b/basics/realloc/quasar/src/instructions/update.rs index c0aa1a022..88d3bd755 100644 --- a/basics/realloc/quasar/src/instructions/update.rs +++ b/basics/realloc/quasar/src/instructions/update.rs @@ -12,7 +12,7 @@ pub struct Update { pub payer: Signer, #[account(mut)] pub message_account: Account, - pub system_program: Program, + pub system_program: Program, } #[inline(always)] diff --git a/basics/rent/quasar/Cargo.toml b/basics/rent/quasar/Cargo.toml index 84c8f1eb4..f66b8bc82 100644 --- a/basics/rent/quasar/Cargo.toml +++ b/basics/rent/quasar/Cargo.toml @@ -22,7 +22,7 @@ client = [] debug = [] [dependencies] -quasar-lang = { git = "https://github.com/blueshift-gg/quasar" } +quasar-lang = { git = "https://github.com/blueshift-gg/quasar", branch = "master" } solana-instruction = { version = "3.2.0" } [dev-dependencies] diff --git a/basics/rent/quasar/src/instructions/create_system_account.rs b/basics/rent/quasar/src/instructions/create_system_account.rs index ccd087a15..0fbcfb6f1 100644 --- a/basics/rent/quasar/src/instructions/create_system_account.rs +++ b/basics/rent/quasar/src/instructions/create_system_account.rs @@ -7,7 +7,7 @@ pub struct CreateSystemAccount { pub payer: Signer, #[account(mut)] pub new_account: Signer, - pub system_program: Program, + pub system_program: Program, } #[inline(always)] diff --git a/basics/repository-layout/quasar/Cargo.toml b/basics/repository-layout/quasar/Cargo.toml index a476a5926..5006411c6 100644 --- a/basics/repository-layout/quasar/Cargo.toml +++ b/basics/repository-layout/quasar/Cargo.toml @@ -22,7 +22,7 @@ client = [] debug = [] [dependencies] -quasar-lang = { git = "https://github.com/blueshift-gg/quasar" } +quasar-lang = { git = "https://github.com/blueshift-gg/quasar", branch = "master" } solana-instruction = { version = "3.2.0" } [dev-dependencies] diff --git a/basics/transfer-sol/quasar/Cargo.toml b/basics/transfer-sol/quasar/Cargo.toml index dacb49696..ec0b3f69a 100644 --- a/basics/transfer-sol/quasar/Cargo.toml +++ b/basics/transfer-sol/quasar/Cargo.toml @@ -22,7 +22,7 @@ client = [] debug = [] [dependencies] -quasar-lang = { git = "https://github.com/blueshift-gg/quasar" } +quasar-lang = { git = "https://github.com/blueshift-gg/quasar", branch = "master" } solana-instruction = { version = "3.2.0" } [dev-dependencies] diff --git a/basics/transfer-sol/quasar/src/instructions/transfer_sol_with_cpi.rs b/basics/transfer-sol/quasar/src/instructions/transfer_sol_with_cpi.rs index cd85cf08f..26d7ea622 100644 --- a/basics/transfer-sol/quasar/src/instructions/transfer_sol_with_cpi.rs +++ b/basics/transfer-sol/quasar/src/instructions/transfer_sol_with_cpi.rs @@ -7,7 +7,7 @@ pub struct TransferSolWithCpi { pub payer: Signer, #[account(mut)] pub recipient: UncheckedAccount, - pub system_program: Program, + pub system_program: Program, } #[inline(always)] diff --git a/compression/cnft-burn/quasar/src/instructions/burn_cnft.rs b/compression/cnft-burn/quasar/src/instructions/burn_cnft.rs index e5eeab412..3a0e69e1f 100644 --- a/compression/cnft-burn/quasar/src/instructions/burn_cnft.rs +++ b/compression/cnft-burn/quasar/src/instructions/burn_cnft.rs @@ -27,7 +27,7 @@ pub struct BurnCnft { /// mpl-bubblegum program. #[account(address = MPL_BUBBLEGUM_ID)] pub bubblegum_program: UncheckedAccount, - pub system_program: Program, + pub system_program: Program, } pub fn handle_burn_cnft(accounts: &mut BurnCnft, data: &[u8], remaining: RemainingAccounts<'_>) -> Result<(), ProgramError> { diff --git a/compression/cnft-vault/quasar/src/instructions/withdraw.rs b/compression/cnft-vault/quasar/src/instructions/withdraw.rs index c1bde7f46..f3c4ccb8f 100644 --- a/compression/cnft-vault/quasar/src/instructions/withdraw.rs +++ b/compression/cnft-vault/quasar/src/instructions/withdraw.rs @@ -17,7 +17,7 @@ pub struct Withdraw { #[account(mut)] pub tree_authority: UncheckedAccount, /// Vault PDA that owns the cNFT — signs the transfer via invoke_signed. - #[account(seeds = [b"cNFT-vault"], bump)] + #[account(address = crate::VaultPda::seeds())] pub leaf_owner: UncheckedAccount, /// New owner to receive the cNFT. pub new_leaf_owner: UncheckedAccount, @@ -32,7 +32,7 @@ pub struct Withdraw { /// mpl-bubblegum program. #[account(address = MPL_BUBBLEGUM_ID)] pub bubblegum_program: UncheckedAccount, - pub system_program: Program, + pub system_program: Program, } /// Build mpl-bubblegum Transfer instruction data from raw args. diff --git a/compression/cnft-vault/quasar/src/instructions/withdraw_two.rs b/compression/cnft-vault/quasar/src/instructions/withdraw_two.rs index 72a58c77a..fca3df2d8 100644 --- a/compression/cnft-vault/quasar/src/instructions/withdraw_two.rs +++ b/compression/cnft-vault/quasar/src/instructions/withdraw_two.rs @@ -18,7 +18,7 @@ pub struct WithdrawTwo { #[account(mut)] pub tree_authority1: UncheckedAccount, /// Vault PDA that owns the cNFTs — signs both transfers. - #[account(seeds = [b"cNFT-vault"], bump)] + #[account(address = crate::VaultPda::seeds())] pub leaf_owner: UncheckedAccount, /// Recipient for cNFT 1. pub new_leaf_owner1: UncheckedAccount, @@ -41,7 +41,7 @@ pub struct WithdrawTwo { /// mpl-bubblegum program. #[account(address = MPL_BUBBLEGUM_ID)] pub bubblegum_program: UncheckedAccount, - pub system_program: Program, + pub system_program: Program, } #[allow(clippy::too_many_lines)] diff --git a/compression/cnft-vault/quasar/src/lib.rs b/compression/cnft-vault/quasar/src/lib.rs index c066b0245..5bc921ff5 100644 --- a/compression/cnft-vault/quasar/src/lib.rs +++ b/compression/cnft-vault/quasar/src/lib.rs @@ -26,6 +26,13 @@ const SPL_ACCOUNT_COMPRESSION_ID: Address = Address::new_from_array([ declare_id!("Fd4iwpPWaCU8BNwGQGtvvrcvG4Tfizq3RgLm8YLBJX6D"); +/// Marker carrying the seeds for the vault PDA. Used by the new +/// `address = VaultPda::seeds()` derive form (post-PR-#195) since +/// inline `seeds = [...]` is no longer accepted. +#[derive(Seeds)] +#[seeds(b"cNFT-vault")] +pub struct VaultPda; + #[program] mod quasar_cnft_vault { use super::*; diff --git a/compression/cutils/quasar/src/instructions/mint.rs b/compression/cutils/quasar/src/instructions/mint.rs index 9f95275b4..1864e346d 100644 --- a/compression/cutils/quasar/src/instructions/mint.rs +++ b/compression/cutils/quasar/src/instructions/mint.rs @@ -50,7 +50,7 @@ pub struct Mint { /// mpl-bubblegum program. #[account(address = MPL_BUBBLEGUM_ID)] pub bubblegum_program: UncheckedAccount, - pub system_program: Program, + pub system_program: Program, } pub fn handle_mint(accounts: &mut Mint, data: &[u8]) -> Result<(), ProgramError> { diff --git a/tokens/create-token/quasar/Cargo.toml b/tokens/create-token/quasar/Cargo.toml index 3eef7659c..b29757626 100644 --- a/tokens/create-token/quasar/Cargo.toml +++ b/tokens/create-token/quasar/Cargo.toml @@ -22,8 +22,8 @@ client = [] debug = [] [dependencies] -quasar-lang = { git = "https://github.com/blueshift-gg/quasar" } -quasar-spl = { git = "https://github.com/blueshift-gg/quasar" } +quasar-lang = { git = "https://github.com/blueshift-gg/quasar", branch = "master" } +quasar-spl = { git = "https://github.com/blueshift-gg/quasar", branch = "master" } solana-instruction = { version = "3.2.0" } [dev-dependencies] diff --git a/tokens/create-token/quasar/src/lib.rs b/tokens/create-token/quasar/src/lib.rs index b68466633..6932eca26 100644 --- a/tokens/create-token/quasar/src/lib.rs +++ b/tokens/create-token/quasar/src/lib.rs @@ -1,7 +1,7 @@ #![cfg_attr(not(test), no_std)] use quasar_lang::prelude::*; -use quasar_spl::{Mint, Token, TokenCpi}; +use quasar_spl::prelude::*; #[cfg(test)] mod tests; @@ -10,9 +10,10 @@ declare_id!("22222222222222222222222222222222222222222222"); /// Creates a token mint and mints initial tokens to the creator's token account. /// -/// The Anchor version uses Metaplex for onchain metadata. Quasar does not have -/// a Metaplex integration crate, so this example focuses on the core SPL Token -/// operations: creating a mint and minting tokens. +/// The Anchor version uses Metaplex for onchain metadata. Quasar's metadata +/// crate is demonstrated in the `nft-minter` and `spl-token-minter` examples; +/// this example focuses on the core SPL Token operations: creating a mint and +/// minting tokens. #[program] mod quasar_create_token { use super::*; @@ -36,11 +37,16 @@ mod quasar_create_token { pub struct CreateToken { #[account(mut)] pub payer: Signer, - #[account(mut, init, payer = payer, mint::decimals = 9, mint::authority = payer)] + #[account( + mut, + init, + payer = payer, + mint(decimals = 9, authority = payer, freeze_authority = None, token_program = token_program), + )] pub mint: Account, pub rent: Sysvar, - pub token_program: Program, - pub system_program: Program, + pub token_program: Program, + pub system_program: Program, } /// Accounts for minting tokens to an existing token account. @@ -52,7 +58,7 @@ pub struct MintTokens { pub mint: Account, #[account(mut)] pub token_account: Account, - pub token_program: Program, + pub token_program: Program, } #[inline(always)] diff --git a/tokens/escrow/quasar/Cargo.toml b/tokens/escrow/quasar/Cargo.toml index 1e0e264cf..0e8f615ae 100644 --- a/tokens/escrow/quasar/Cargo.toml +++ b/tokens/escrow/quasar/Cargo.toml @@ -22,8 +22,8 @@ client = [] debug = [] [dependencies] -quasar-lang = { git = "https://github.com/blueshift-gg/quasar" } -quasar-spl = { git = "https://github.com/blueshift-gg/quasar" } +quasar-lang = { git = "https://github.com/blueshift-gg/quasar", branch = "master" } +quasar-spl = { git = "https://github.com/blueshift-gg/quasar", branch = "master" } solana-address = { version = "2.2.0" } solana-instruction = { version = "3.2.0" } diff --git a/tokens/escrow/quasar/src/instructions/make.rs b/tokens/escrow/quasar/src/instructions/make.rs index 9ab4ec730..8c298e365 100644 --- a/tokens/escrow/quasar/src/instructions/make.rs +++ b/tokens/escrow/quasar/src/instructions/make.rs @@ -1,26 +1,36 @@ use { crate::state::{Escrow, EscrowInner}, quasar_lang::prelude::*, - quasar_spl::{Mint, Token, TokenCpi}, + quasar_spl::prelude::*, }; #[derive(Accounts)] pub struct Make { #[account(mut)] pub maker: Signer, - #[account(mut, init, payer = maker, seeds = Escrow::seeds(maker), bump)] + #[account(mut, init, payer = maker, address = Escrow::seeds(maker.address()))] pub escrow: Account, pub mint_a: Account, pub mint_b: Account, #[account(mut)] pub maker_ta_a: Account, - #[account(mut, init_if_needed, payer = maker, token::mint = mint_b, token::authority = maker)] + #[account( + mut, + init(idempotent), + payer = maker, + token(mint = mint_b, authority = maker, token_program = token_program), + )] pub maker_ta_b: Account, - #[account(mut, init_if_needed, payer = maker, token::mint = mint_a, token::authority = escrow)] + #[account( + mut, + init(idempotent), + payer = maker, + token(mint = mint_a, authority = escrow, token_program = token_program), + )] pub vault_ta_a: Account, pub rent: Sysvar, - pub token_program: Program, - pub system_program: Program, + pub token_program: Program, + pub system_program: Program, } #[inline(always)] diff --git a/tokens/escrow/quasar/src/instructions/refund.rs b/tokens/escrow/quasar/src/instructions/refund.rs index d1e5d1f5b..03403e8a9 100644 --- a/tokens/escrow/quasar/src/instructions/refund.rs +++ b/tokens/escrow/quasar/src/instructions/refund.rs @@ -1,7 +1,7 @@ use { crate::state::Escrow, quasar_lang::prelude::*, - quasar_spl::{Mint, Token, TokenCpi}, + quasar_spl::prelude::*, }; #[derive(Accounts)] @@ -10,25 +10,34 @@ pub struct Refund { pub maker: Signer, #[account( mut, - has_one = maker, - close = maker, - seeds = Escrow::seeds(maker), - bump = escrow.bump + has_one(maker), + close(dest = maker), + address = Escrow::seeds(maker.address()) )] pub escrow: Account, pub mint_a: Account, - #[account(mut, init_if_needed, payer = maker, token::mint = mint_a, token::authority = maker)] + #[account( + mut, + init(idempotent), + payer = maker, + token(mint = mint_a, authority = maker, token_program = token_program), + )] pub maker_ta_a: Account, #[account(mut)] pub vault_ta_a: Account, pub rent: Sysvar, - pub token_program: Program, - pub system_program: Program, + pub token_program: Program, + pub system_program: Program, } #[inline(always)] pub fn handle_withdraw_tokens_and_close_refund(accounts: &mut Refund, bumps: &RefundBumps) -> Result<(), ProgramError> { - let seeds = accounts.escrow_seeds(bumps); + let bump = [bumps.escrow]; + let seeds = [ + Seed::from(b"escrow" as &[u8]), + Seed::from(accounts.maker.address().as_ref()), + Seed::from(bump.as_ref()), + ]; accounts.token_program .transfer( diff --git a/tokens/escrow/quasar/src/instructions/take.rs b/tokens/escrow/quasar/src/instructions/take.rs index 78b8e695c..b95176aac 100644 --- a/tokens/escrow/quasar/src/instructions/take.rs +++ b/tokens/escrow/quasar/src/instructions/take.rs @@ -1,7 +1,7 @@ use { crate::state::Escrow, quasar_lang::prelude::*, - quasar_spl::{Mint, Token, TokenCpi}, + quasar_spl::prelude::*, }; #[derive(Accounts)] @@ -10,29 +10,38 @@ pub struct Take { pub taker: Signer, #[account( mut, - has_one = maker, - has_one = maker_ta_b, - constraint = escrow.receive > 0, - close = taker, - seeds = Escrow::seeds(maker), - bump = escrow.bump + has_one(maker), + has_one(maker_ta_b), + constraints(escrow.receive > 0), + close(dest = taker), + address = Escrow::seeds(maker.address()) )] pub escrow: Account, #[account(mut)] pub maker: UncheckedAccount, pub mint_a: Account, pub mint_b: Account, - #[account(mut, init_if_needed, payer = taker, token::mint = mint_a, token::authority = taker)] + #[account( + mut, + init(idempotent), + payer = taker, + token(mint = mint_a, authority = taker, token_program = token_program), + )] pub taker_ta_a: Account, #[account(mut)] pub taker_ta_b: Account, - #[account(mut, init_if_needed, payer = taker, token::mint = mint_b, token::authority = maker)] + #[account( + mut, + init(idempotent), + payer = taker, + token(mint = mint_b, authority = maker, token_program = token_program), + )] pub maker_ta_b: Account, #[account(mut)] pub vault_ta_a: Account, pub rent: Sysvar, - pub token_program: Program, - pub system_program: Program, + pub token_program: Program, + pub system_program: Program, } #[inline(always)] @@ -49,7 +58,12 @@ pub fn handle_transfer_tokens(accounts: &mut Take) -> Result<(), ProgramError> { #[inline(always)] pub fn handle_withdraw_tokens_and_close_take(accounts: &mut Take, bumps: &TakeBumps) -> Result<(), ProgramError> { - let seeds = accounts.escrow_seeds(bumps); + let bump = [bumps.escrow]; + let seeds = [ + Seed::from(b"escrow" as &[u8]), + Seed::from(accounts.maker.address().as_ref()), + Seed::from(bump.as_ref()), + ]; accounts.token_program .transfer( diff --git a/tokens/external-delegate-token-master/quasar/Cargo.toml b/tokens/external-delegate-token-master/quasar/Cargo.toml index 347832b68..124065aa2 100644 --- a/tokens/external-delegate-token-master/quasar/Cargo.toml +++ b/tokens/external-delegate-token-master/quasar/Cargo.toml @@ -22,8 +22,10 @@ client = [] debug = [] [dependencies] -quasar-lang = { git = "https://github.com/blueshift-gg/quasar" } -quasar-spl = { git = "https://github.com/blueshift-gg/quasar" } +# Pin both quasar deps to the same source-id (branch = "master") so trait +# impls resolve consistently. +quasar-lang = { git = "https://github.com/blueshift-gg/quasar", branch = "master" } +quasar-spl = { git = "https://github.com/blueshift-gg/quasar", branch = "master" } solana-instruction = { version = "3.2.0" } solana-define-syscall = "4.0" solana-keccak-hasher = "3.1" diff --git a/tokens/external-delegate-token-master/quasar/Quasar.toml b/tokens/external-delegate-token-master/quasar/Quasar.toml new file mode 100644 index 000000000..077536de5 --- /dev/null +++ b/tokens/external-delegate-token-master/quasar/Quasar.toml @@ -0,0 +1,22 @@ +[project] +name = "quasar_external_delegate_token_master" + +[toolchain] +type = "solana" + +[testing] +language = "rust" + +[testing.rust] +framework = "quasar-svm" + +[testing.rust.test] +program = "cargo" +args = [ + "test", + "tests::", +] + +[clients] +path = "target/client" +languages = ["rust"] diff --git a/tokens/external-delegate-token-master/quasar/src/lib.rs b/tokens/external-delegate-token-master/quasar/src/lib.rs index d7923128e..f49e12256 100644 --- a/tokens/external-delegate-token-master/quasar/src/lib.rs +++ b/tokens/external-delegate-token-master/quasar/src/lib.rs @@ -1,7 +1,7 @@ #![cfg_attr(not(test), no_std)] use quasar_lang::prelude::*; -use quasar_spl::{Token, TokenCpi}; +use quasar_spl::prelude::*; #[cfg(test)] mod tests; @@ -9,12 +9,20 @@ mod tests; declare_id!("22222222222222222222222222222222222222222222"); /// User account storing the Solana authority and linked Ethereum address. -#[account(discriminator = 1)] +#[account(discriminator = 1, set_inner)] pub struct UserAccount { pub authority: Address, pub ethereum_address: [u8; 20], } +/// Marker carrying the seeds for the per-user PDA: just the user account +/// address (no string prefix). Required since PR #195 because inline +/// `seeds = [...]` is gone — derivation now happens through a +/// `#[derive(Seeds)]` type referenced by `address = T::seeds(...)`. +#[derive(Seeds)] +#[seeds(b"", user_account: Address)] +pub struct UserPda; + /// External delegate token master: allows transfers authorised either by /// the Solana authority or by an Ethereum signature (secp256k1). #[program] @@ -67,13 +75,16 @@ pub struct Initialize { pub user_account: Account, #[account(mut)] pub authority: Signer, - pub system_program: Program, + pub system_program: Program, } #[inline(always)] fn handle_initialize(accounts: &mut Initialize) -> Result<(), ProgramError> { accounts.user_account - .set_inner(*accounts.authority.address(), [0u8; 20]); + .set_inner(UserAccountInner { + authority: *accounts.authority.address(), + ethereum_address: [0u8; 20], + }); Ok(()) } @@ -104,9 +115,9 @@ pub struct TransferTokens { #[account(mut)] pub recipient_token_account: Account, /// PDA derived from user_account address. - #[account(seeds = [user_account], bump)] + #[account(address = UserPda::seeds(user_account.address()))] pub user_pda: UncheckedAccount, - pub token_program: Program, + pub token_program: Program, } #[inline(always)] @@ -150,9 +161,9 @@ pub struct AuthorityTransfer { #[account(mut)] pub recipient_token_account: Account, /// PDA derived from user_account address. - #[account(seeds = [user_account], bump)] + #[account(address = UserPda::seeds(user_account.address()))] pub user_pda: UncheckedAccount, - pub token_program: Program, + pub token_program: Program, } #[inline(always)] diff --git a/tokens/nft-minter/quasar/Cargo.toml b/tokens/nft-minter/quasar/Cargo.toml index c6d67aca2..5394e56ca 100644 --- a/tokens/nft-minter/quasar/Cargo.toml +++ b/tokens/nft-minter/quasar/Cargo.toml @@ -22,8 +22,11 @@ client = [] debug = [] [dependencies] -quasar-lang = { git = "https://github.com/blueshift-gg/quasar" } -quasar-spl = { git = "https://github.com/blueshift-gg/quasar", branch = "master", features = ["metadata"] } +# All quasar deps share branch = "master" so trait impls resolve consistently. +quasar-lang = { git = "https://github.com/blueshift-gg/quasar", branch = "master" } +quasar-spl = { git = "https://github.com/blueshift-gg/quasar", branch = "master" } +# Metaplex metadata moved out of quasar-spl into a dedicated crate (PR #196). +quasar-metadata = { git = "https://github.com/blueshift-gg/quasar", branch = "master" } solana-instruction = { version = "3.2.0" } [dev-dependencies] diff --git a/tokens/nft-minter/quasar/Quasar.toml b/tokens/nft-minter/quasar/Quasar.toml new file mode 100644 index 000000000..2ed322d47 --- /dev/null +++ b/tokens/nft-minter/quasar/Quasar.toml @@ -0,0 +1,22 @@ +[project] +name = "quasar_nft_minter" + +[toolchain] +type = "solana" + +[testing] +language = "rust" + +[testing.rust] +framework = "quasar-svm" + +[testing.rust.test] +program = "cargo" +args = [ + "test", + "tests::", +] + +[clients] +path = "target/client" +languages = ["rust"] diff --git a/tokens/nft-minter/quasar/src/lib.rs b/tokens/nft-minter/quasar/src/lib.rs index 9127dcab8..fde20297e 100644 --- a/tokens/nft-minter/quasar/src/lib.rs +++ b/tokens/nft-minter/quasar/src/lib.rs @@ -1,10 +1,8 @@ #![cfg_attr(not(test), no_std)] use quasar_lang::prelude::*; -use quasar_spl::{ - metadata::{MetadataCpi, MetadataProgram}, - Mint, Token, TokenCpi, -}; +use quasar_metadata::prelude::*; +use quasar_spl::prelude::*; #[cfg(test)] mod tests; @@ -17,12 +15,14 @@ declare_id!("22222222222222222222222222222222222222222222"); mod quasar_nft_minter { use super::*; + // Metaplex Token Metadata limits: name ≤ 32, symbol ≤ 10, uri ≤ 200. + // PR #195 made the capacity bound on `String` mandatory. #[instruction(discriminator = 0)] pub fn mint_nft( ctx: Ctx, - nft_name: String, - nft_symbol: String, - nft_uri: String, + nft_name: String<32>, + nft_symbol: String<10>, + nft_uri: String<200>, ) -> Result<(), ProgramError> { handle_mint_nft(&mut ctx.accounts, &nft_name, &nft_symbol, &nft_uri) } @@ -34,25 +34,43 @@ pub struct MintNft { #[account(mut)] pub payer: Signer, - /// Metadata PDA — initialised by the Metaplex program. + /// Metadata PDA — initialised via the Metaplex program by an explicit + /// CPI below; stays an UncheckedAccount because the new + /// `metadata(...)` behaviour only accepts compile-time literals for + /// name / symbol / uri. #[account(mut)] pub metadata_account: UncheckedAccount, - /// Master edition PDA — initialised by the Metaplex program. + /// Master edition PDA — initialised via the Metaplex program below. #[account(mut)] pub edition_account: UncheckedAccount, /// NFT mint (decimals = 0). - #[account(mut, init, payer = payer, mint::decimals = 0, mint::authority = payer, mint::freeze_authority = payer)] + #[account( + mut, + init, + payer = payer, + mint( + decimals = 0, + authority = payer, + freeze_authority = Some(payer), + token_program = token_program, + ), + )] pub mint_account: Account, /// Token account holding the NFT. - #[account(mut, init_if_needed, payer = payer, token::mint = mint_account, token::authority = payer)] + #[account( + mut, + init(idempotent), + payer = payer, + token(mint = mint_account, authority = payer, token_program = token_program), + )] pub associated_token_account: Account, - pub token_program: Program, - pub token_metadata_program: MetadataProgram, - pub system_program: Program, + pub token_program: Program, + pub token_metadata_program: Program, + pub system_program: Program, pub rent: Sysvar, } @@ -91,7 +109,7 @@ fn handle_mint_nft( 0, // seller_fee_basis_points false, // is_mutable true, // update_authority_is_signer - ) + )? .invoke()?; // 3. Create master edition (makes it a verified NFT). diff --git a/tokens/nft-operations/quasar/Cargo.toml b/tokens/nft-operations/quasar/Cargo.toml index 0ea933855..ebf129dcc 100644 --- a/tokens/nft-operations/quasar/Cargo.toml +++ b/tokens/nft-operations/quasar/Cargo.toml @@ -22,8 +22,11 @@ client = [] debug = [] [dependencies] -quasar-lang = { git = "https://github.com/blueshift-gg/quasar" } -quasar-spl = { git = "https://github.com/blueshift-gg/quasar", branch = "master", features = ["metadata"] } +# All quasar deps share branch = "master" so trait impls resolve consistently. +quasar-lang = { git = "https://github.com/blueshift-gg/quasar", branch = "master" } +quasar-spl = { git = "https://github.com/blueshift-gg/quasar", branch = "master" } +# Metaplex metadata moved out of quasar-spl into a dedicated crate (PR #196). +quasar-metadata = { git = "https://github.com/blueshift-gg/quasar", branch = "master" } solana-instruction = { version = "3.2.0" } [dev-dependencies] diff --git a/tokens/nft-operations/quasar/Quasar.toml b/tokens/nft-operations/quasar/Quasar.toml new file mode 100644 index 000000000..b0f534bbf --- /dev/null +++ b/tokens/nft-operations/quasar/Quasar.toml @@ -0,0 +1,22 @@ +[project] +name = "quasar_nft_operations" + +[toolchain] +type = "solana" + +[testing] +language = "rust" + +[testing.rust] +framework = "quasar-svm" + +[testing.rust.test] +program = "cargo" +args = [ + "test", + "tests::", +] + +[clients] +path = "target/client" +languages = ["rust"] diff --git a/tokens/nft-operations/quasar/src/instructions/create_collection.rs b/tokens/nft-operations/quasar/src/instructions/create_collection.rs index e0f2032a7..8ac792cfc 100644 --- a/tokens/nft-operations/quasar/src/instructions/create_collection.rs +++ b/tokens/nft-operations/quasar/src/instructions/create_collection.rs @@ -1,7 +1,8 @@ -use quasar_lang::prelude::*; -use quasar_spl::{ - metadata::{MetadataCpi, MetadataProgram}, - Mint, Token, TokenCpi, +use { + crate::MintAuthorityPda, + quasar_lang::prelude::*, + quasar_metadata::prelude::*, + quasar_spl::prelude::*, }; /// Accounts for creating a collection NFT. @@ -11,10 +12,20 @@ use quasar_spl::{ pub struct CreateCollection { #[account(mut)] pub user: Signer, - #[account(mut, init, payer = user, mint::decimals = 0, mint::authority = mint_authority, mint::freeze_authority = mint_authority)] + #[account( + mut, + init, + payer = user, + mint( + decimals = 0, + authority = mint_authority, + freeze_authority = Some(mint_authority), + token_program = token_program, + ), + )] pub mint: Account, /// PDA used as mint authority and update authority. - #[account(seeds = [b"authority"], bump)] + #[account(address = MintAuthorityPda::seeds())] pub mint_authority: UncheckedAccount, /// Metadata PDA — initialised by the Metaplex program. #[account(mut)] @@ -23,11 +34,16 @@ pub struct CreateCollection { #[account(mut)] pub master_edition: UncheckedAccount, /// Token account to hold the collection NFT. - #[account(mut, init_if_needed, payer = user, token::mint = mint, token::authority = user)] + #[account( + mut, + init(idempotent), + payer = user, + token(mint = mint, authority = user, token_program = token_program), + )] pub destination: Account, - pub system_program: Program, - pub token_program: Program, - pub token_metadata_program: MetadataProgram, + pub system_program: Program, + pub token_program: Program, + pub token_metadata_program: Program, pub rent: Sysvar, } @@ -61,7 +77,7 @@ pub fn handle_create_collection(accounts: &mut CreateCollection, bumps: &CreateC 0, // seller_fee_basis_points true, // is_mutable true, // update_authority_is_signer - ) + )? .invoke_signed(seeds)?; log("Metadata Account created!"); diff --git a/tokens/nft-operations/quasar/src/instructions/mint_nft.rs b/tokens/nft-operations/quasar/src/instructions/mint_nft.rs index b0a16944b..53be3dc3e 100644 --- a/tokens/nft-operations/quasar/src/instructions/mint_nft.rs +++ b/tokens/nft-operations/quasar/src/instructions/mint_nft.rs @@ -1,7 +1,8 @@ -use quasar_lang::prelude::*; -use quasar_spl::{ - metadata::{MetadataCpi, MetadataProgram}, - Mint, Token, TokenCpi, +use { + crate::MintAuthorityPda, + quasar_lang::prelude::*, + quasar_metadata::prelude::*, + quasar_spl::prelude::*, }; /// Accounts for minting an individual NFT with a collection reference. @@ -9,10 +10,25 @@ use quasar_spl::{ pub struct MintNft { #[account(mut)] pub owner: Signer, - #[account(mut, init, payer = owner, mint::decimals = 0, mint::authority = mint_authority, mint::freeze_authority = mint_authority)] + #[account( + mut, + init, + payer = owner, + mint( + decimals = 0, + authority = mint_authority, + freeze_authority = Some(mint_authority), + token_program = token_program, + ), + )] pub mint: Account, /// Token account to hold the NFT. - #[account(mut, init_if_needed, payer = owner, token::mint = mint, token::authority = owner)] + #[account( + mut, + init(idempotent), + payer = owner, + token(mint = mint, authority = owner, token_program = token_program), + )] pub destination: Account, /// Metadata PDA — initialised by the Metaplex program. #[account(mut)] @@ -21,14 +37,14 @@ pub struct MintNft { #[account(mut)] pub master_edition: UncheckedAccount, /// PDA used as mint authority and update authority. - #[account(seeds = [b"authority"], bump)] + #[account(address = MintAuthorityPda::seeds())] pub mint_authority: UncheckedAccount, /// The collection mint (must already exist). #[account(mut)] pub collection_mint: Account, - pub system_program: Program, - pub token_program: Program, - pub token_metadata_program: MetadataProgram, + pub system_program: Program, + pub token_program: Program, + pub token_metadata_program: Program, pub rent: Sysvar, } @@ -64,7 +80,7 @@ pub fn handle_mint_nft(accounts: &mut MintNft, bumps: &MintNftBumps) -> Result<( 0, // seller_fee_basis_points true, // is_mutable true, // update_authority_is_signer - ) + )? .invoke_signed(seeds)?; // Create master edition. diff --git a/tokens/nft-operations/quasar/src/instructions/verify_collection.rs b/tokens/nft-operations/quasar/src/instructions/verify_collection.rs index 0306e5179..031b902a5 100644 --- a/tokens/nft-operations/quasar/src/instructions/verify_collection.rs +++ b/tokens/nft-operations/quasar/src/instructions/verify_collection.rs @@ -1,5 +1,8 @@ -use quasar_lang::prelude::*; -use quasar_spl::metadata::{MetadataCpi, MetadataProgram}; +use { + crate::MintAuthorityPda, + quasar_lang::prelude::*, + quasar_metadata::prelude::*, +}; /// Accounts for verifying an NFT as part of a collection. /// @@ -17,7 +20,7 @@ pub struct VerifyCollectionMint { #[account(mut)] pub metadata: UncheckedAccount, /// PDA used as collection authority. - #[account(seeds = [b"authority"], bump)] + #[account(address = MintAuthorityPda::seeds())] pub mint_authority: UncheckedAccount, /// The collection mint. pub collection_mint: UncheckedAccount, @@ -26,8 +29,8 @@ pub struct VerifyCollectionMint { pub collection_metadata: UncheckedAccount, /// The collection's master edition account. pub collection_master_edition: UncheckedAccount, - pub system_program: Program, - pub token_metadata_program: MetadataProgram, + pub system_program: Program, + pub token_metadata_program: Program, } #[inline(always)] diff --git a/tokens/nft-operations/quasar/src/lib.rs b/tokens/nft-operations/quasar/src/lib.rs index e40c748a8..58185ce98 100644 --- a/tokens/nft-operations/quasar/src/lib.rs +++ b/tokens/nft-operations/quasar/src/lib.rs @@ -9,6 +9,14 @@ mod tests; declare_id!("22222222222222222222222222222222222222222222"); +/// Marker carrying the seeds for the shared PDA mint authority used as +/// both mint and update authority. PR #195 removed inline +/// `seeds = [...]`; derivation now happens through a `#[derive(Seeds)]` +/// type referenced by `address = T::seeds()`. +#[derive(Seeds)] +#[seeds(b"authority")] +pub struct MintAuthorityPda; + /// NFT operations: create a collection, mint NFTs into it, and verify /// collection membership. /// diff --git a/tokens/pda-mint-authority/quasar/Cargo.toml b/tokens/pda-mint-authority/quasar/Cargo.toml index f4bf7ddd9..c1887d667 100644 --- a/tokens/pda-mint-authority/quasar/Cargo.toml +++ b/tokens/pda-mint-authority/quasar/Cargo.toml @@ -21,8 +21,8 @@ client = [] debug = [] [dependencies] -quasar-lang = { git = "https://github.com/blueshift-gg/quasar" } -quasar-spl = { git = "https://github.com/blueshift-gg/quasar" } +quasar-lang = { git = "https://github.com/blueshift-gg/quasar", branch = "master" } +quasar-spl = { git = "https://github.com/blueshift-gg/quasar", branch = "master" } solana-instruction = { version = "3.2.0" } [dev-dependencies] diff --git a/tokens/pda-mint-authority/quasar/src/lib.rs b/tokens/pda-mint-authority/quasar/src/lib.rs index 6a72cb367..c819d5f57 100644 --- a/tokens/pda-mint-authority/quasar/src/lib.rs +++ b/tokens/pda-mint-authority/quasar/src/lib.rs @@ -1,7 +1,7 @@ #![cfg_attr(not(test), no_std)] use quasar_lang::{prelude::*, sysvars::Sysvar}; -use quasar_spl::{initialize_mint2, Mint, Token, TokenCpi}; +use quasar_spl::{initialize_mint2, prelude::*}; #[cfg(test)] mod tests; @@ -11,6 +11,12 @@ declare_id!("22222222222222222222222222222222222222222222"); /// SPL Mint account size in bytes. const MINT_SPACE: usize = 82; +/// Marker for the PDA at seeds = ["mint"]; used by the new +/// `address = MintPda::seeds()` form (post-PR-#195) to derive the mint PDA. +#[derive(Seeds)] +#[seeds(b"mint")] +pub struct MintPda; + /// Demonstrates using a PDA as the mint authority for an SPL token. /// /// The mint account is created at the PDA address derived from `["mint"]`. @@ -34,16 +40,16 @@ mod quasar_pda_mint_authority { } /// Create the mint at a PDA. Manually created and initialized to avoid -/// a borrow conflict from `mint::authority = mint` in the init constraint. +/// a borrow conflict from `mint(authority = mint)` in the init constraint. #[derive(Accounts)] pub struct CreateMint { #[account(mut)] pub payer: Signer, /// The PDA that will become the mint (and its own authority). - #[account(mut, seeds = [b"mint"], bump)] + #[account(mut, address = MintPda::seeds())] pub mint: UncheckedAccount, - pub token_program: Program, - pub system_program: Program, + pub token_program: Program, + pub system_program: Program, } #[inline(always)] @@ -84,12 +90,12 @@ pub struct MintTokens { #[account(mut)] pub payer: Signer, /// The PDA mint whose authority is itself. - #[account(mut, seeds = [b"mint"], bump)] + #[account(mut, address = MintPda::seeds())] pub mint: Account, /// Recipient token account (must already exist). #[account(mut)] pub token_account: Account, - pub token_program: Program, + pub token_program: Program, } #[inline(always)] diff --git a/tokens/spl-token-minter/quasar/Cargo.toml b/tokens/spl-token-minter/quasar/Cargo.toml index c04390da9..0ff88f447 100644 --- a/tokens/spl-token-minter/quasar/Cargo.toml +++ b/tokens/spl-token-minter/quasar/Cargo.toml @@ -22,8 +22,13 @@ client = [] debug = [] [dependencies] -quasar-lang = { git = "https://github.com/blueshift-gg/quasar" } -quasar-spl = { git = "https://github.com/blueshift-gg/quasar", branch = "master", features = ["metadata"] } +# All quasar deps share one source-id (branch = "master") so trait-impls +# resolve consistently — mixing `{ git = ... }` with `{ git = ..., branch = "master" }` +# was treated by Cargo as two distinct sources of the same crate. +quasar-lang = { git = "https://github.com/blueshift-gg/quasar", branch = "master" } +quasar-spl = { git = "https://github.com/blueshift-gg/quasar", branch = "master" } +# Metaplex metadata moved out of quasar-spl into its own crate (PR #196). +quasar-metadata = { git = "https://github.com/blueshift-gg/quasar", branch = "master" } solana-instruction = { version = "3.2.0" } [dev-dependencies] diff --git a/tokens/spl-token-minter/quasar/Quasar.toml b/tokens/spl-token-minter/quasar/Quasar.toml new file mode 100644 index 000000000..508a29c2a --- /dev/null +++ b/tokens/spl-token-minter/quasar/Quasar.toml @@ -0,0 +1,22 @@ +[project] +name = "quasar_spl_token_minter" + +[toolchain] +type = "solana" + +[testing] +language = "rust" + +[testing.rust] +framework = "quasar-svm" + +[testing.rust.test] +program = "cargo" +args = [ + "test", + "tests::", +] + +[clients] +path = "target/client" +languages = ["rust"] diff --git a/tokens/spl-token-minter/quasar/src/instructions/create.rs b/tokens/spl-token-minter/quasar/src/instructions/create.rs index 3291ceb17..86bf735cf 100644 --- a/tokens/spl-token-minter/quasar/src/instructions/create.rs +++ b/tokens/spl-token-minter/quasar/src/instructions/create.rs @@ -1,13 +1,16 @@ -use quasar_lang::prelude::*; -use quasar_spl::{ - metadata::{MetadataCpi, MetadataProgram}, - Mint, Token, +use { + quasar_lang::prelude::*, + quasar_metadata::prelude::*, + quasar_spl::prelude::*, }; /// Accounts for creating a new token mint with Metaplex metadata. /// /// The mint is initialised via Quasar's `#[account(init)]`. The metadata -/// PDA is created by CPI-ing into the Metaplex Token Metadata program. +/// PDA is created by an explicit CPI to the Metaplex Token Metadata program +/// because the new `metadata(...)` derive behaviour only accepts compile-time +/// constants for `name` / `symbol` / `uri`; this instruction takes them at +/// runtime. #[derive(Accounts)] pub struct CreateToken { #[account(mut)] @@ -16,17 +19,20 @@ pub struct CreateToken { mut, init, payer = payer, - mint::decimals = 9, - mint::authority = payer, - mint::freeze_authority = payer, + mint( + decimals = 9, + authority = payer, + freeze_authority = Some(payer), + token_program = token_program, + ), )] pub mint_account: Account, /// The metadata PDA — will be initialised by the Metaplex program. #[account(mut)] pub metadata_account: UncheckedAccount, - pub token_program: Program, - pub token_metadata_program: MetadataProgram, - pub system_program: Program, + pub token_program: Program, + pub token_metadata_program: Program, + pub system_program: Program, pub rent: Sysvar, } @@ -54,7 +60,7 @@ pub fn handle_create_token( 0, // seller_fee_basis_points false, // is_mutable true, // update_authority_is_signer - ) + )? .invoke()?; log("Token created successfully."); diff --git a/tokens/spl-token-minter/quasar/src/instructions/mint.rs b/tokens/spl-token-minter/quasar/src/instructions/mint.rs index 697a658be..029658dd3 100644 --- a/tokens/spl-token-minter/quasar/src/instructions/mint.rs +++ b/tokens/spl-token-minter/quasar/src/instructions/mint.rs @@ -1,5 +1,5 @@ use quasar_lang::prelude::*; -use quasar_spl::{Mint, Token, TokenCpi}; +use quasar_spl::prelude::*; /// Accounts for minting tokens to a recipient's token account. #[derive(Accounts)] @@ -9,10 +9,15 @@ pub struct MintToken { pub recipient: UncheckedAccount, #[account(mut)] pub mint_account: Account, - #[account(mut, init_if_needed, payer = mint_authority, token::mint = mint_account, token::authority = recipient)] + #[account( + mut, + init(idempotent), + payer = mint_authority, + token(mint = mint_account, authority = recipient, token_program = token_program), + )] pub associated_token_account: Account, - pub token_program: Program, - pub system_program: Program, + pub token_program: Program, + pub system_program: Program, } #[inline(always)] diff --git a/tokens/spl-token-minter/quasar/src/lib.rs b/tokens/spl-token-minter/quasar/src/lib.rs index d5701f343..05e40d8b9 100644 --- a/tokens/spl-token-minter/quasar/src/lib.rs +++ b/tokens/spl-token-minter/quasar/src/lib.rs @@ -18,14 +18,22 @@ declare_id!("22222222222222222222222222222222222222222222"); mod quasar_spl_token_minter { use super::*; + // String capacities follow Metaplex Token Metadata limits: + // name ≤ 32, symbol ≤ 10, uri ≤ 200. PodString requires an explicit + // capacity since PR #195 — `String` (no ) is no longer accepted. #[instruction(discriminator = 0)] pub fn create_token( ctx: Ctx, - token_name: String, - token_symbol: String, - token_uri: String, + token_name: String<32>, + token_symbol: String<10>, + token_uri: String<200>, ) -> Result<(), ProgramError> { - instructions::handle_create_token(&mut ctx.accounts, &token_name, &token_symbol, &token_uri) + instructions::handle_create_token( + &mut ctx.accounts, + &token_name, + &token_symbol, + &token_uri, + ) } #[instruction(discriminator = 1)] diff --git a/tokens/token-extensions/default-account-state/quasar/src/lib.rs b/tokens/token-extensions/default-account-state/quasar/src/lib.rs index 28b888d5a..947b71edd 100644 --- a/tokens/token-extensions/default-account-state/quasar/src/lib.rs +++ b/tokens/token-extensions/default-account-state/quasar/src/lib.rs @@ -51,7 +51,7 @@ pub struct Initialize { #[account(mut)] pub mint_account: Signer, pub token_program: Program, - pub system_program: Program, + pub system_program: Program, } #[inline(always)] diff --git a/tokens/token-extensions/immutable-owner/quasar/src/lib.rs b/tokens/token-extensions/immutable-owner/quasar/src/lib.rs index 3e995b9d4..83606f229 100644 --- a/tokens/token-extensions/immutable-owner/quasar/src/lib.rs +++ b/tokens/token-extensions/immutable-owner/quasar/src/lib.rs @@ -39,7 +39,7 @@ pub struct Initialize { pub token_account: Signer, pub mint_account: UncheckedAccount, pub token_program: Program, - pub system_program: Program, + pub system_program: Program, } #[inline(always)] diff --git a/tokens/token-extensions/interest-bearing/quasar/src/lib.rs b/tokens/token-extensions/interest-bearing/quasar/src/lib.rs index 1f10c7dae..b649b59e9 100644 --- a/tokens/token-extensions/interest-bearing/quasar/src/lib.rs +++ b/tokens/token-extensions/interest-bearing/quasar/src/lib.rs @@ -43,7 +43,7 @@ pub struct Initialize { #[account(mut)] pub mint_account: Signer, pub token_program: Program, - pub system_program: Program, + pub system_program: Program, } #[inline(always)] diff --git a/tokens/token-extensions/memo-transfer/quasar/src/lib.rs b/tokens/token-extensions/memo-transfer/quasar/src/lib.rs index 049ec6adc..bead24bb8 100644 --- a/tokens/token-extensions/memo-transfer/quasar/src/lib.rs +++ b/tokens/token-extensions/memo-transfer/quasar/src/lib.rs @@ -44,7 +44,7 @@ pub struct Initialize { pub token_account: Signer, pub mint_account: UncheckedAccount, pub token_program: Program, - pub system_program: Program, + pub system_program: Program, } #[inline(always)] diff --git a/tokens/token-extensions/mint-close-authority/quasar/src/lib.rs b/tokens/token-extensions/mint-close-authority/quasar/src/lib.rs index 9a7986663..3c9eae460 100644 --- a/tokens/token-extensions/mint-close-authority/quasar/src/lib.rs +++ b/tokens/token-extensions/mint-close-authority/quasar/src/lib.rs @@ -45,7 +45,7 @@ pub struct Initialize { #[account(mut)] pub mint_account: Signer, pub token_program: Program, - pub system_program: Program, + pub system_program: Program, } #[inline(always)] diff --git a/tokens/token-extensions/non-transferable/quasar/src/lib.rs b/tokens/token-extensions/non-transferable/quasar/src/lib.rs index f4ed62ad6..1e66dba59 100644 --- a/tokens/token-extensions/non-transferable/quasar/src/lib.rs +++ b/tokens/token-extensions/non-transferable/quasar/src/lib.rs @@ -38,7 +38,7 @@ pub struct Initialize { #[account(mut)] pub mint_account: Signer, pub token_program: Program, - pub system_program: Program, + pub system_program: Program, } #[inline(always)] diff --git a/tokens/token-extensions/permanent-delegate/quasar/src/lib.rs b/tokens/token-extensions/permanent-delegate/quasar/src/lib.rs index c5085ed59..a57b3b1dd 100644 --- a/tokens/token-extensions/permanent-delegate/quasar/src/lib.rs +++ b/tokens/token-extensions/permanent-delegate/quasar/src/lib.rs @@ -38,7 +38,7 @@ pub struct Initialize { #[account(mut)] pub mint_account: Signer, pub token_program: Program, - pub system_program: Program, + pub system_program: Program, } #[inline(always)] diff --git a/tokens/token-extensions/transfer-fee/quasar/src/lib.rs b/tokens/token-extensions/transfer-fee/quasar/src/lib.rs index 82aa73350..4307fd383 100644 --- a/tokens/token-extensions/transfer-fee/quasar/src/lib.rs +++ b/tokens/token-extensions/transfer-fee/quasar/src/lib.rs @@ -65,7 +65,7 @@ pub struct Initialize { #[account(mut)] pub mint_account: Signer, pub token_program: Program, - pub system_program: Program, + pub system_program: Program, } #[inline(always)] diff --git a/tokens/token-extensions/transfer-hook/account-data-as-seed/quasar/src/lib.rs b/tokens/token-extensions/transfer-hook/account-data-as-seed/quasar/src/lib.rs index ea3808630..ade357024 100644 --- a/tokens/token-extensions/transfer-hook/account-data-as-seed/quasar/src/lib.rs +++ b/tokens/token-extensions/transfer-hook/account-data-as-seed/quasar/src/lib.rs @@ -56,7 +56,7 @@ pub struct InitializeExtraAccountMetaList { /// Counter PDA: ["counter", payer_key] #[account(mut)] pub counter_account: UncheckedAccount, - pub system_program: Program, + pub system_program: Program, } #[inline(always)] diff --git a/tokens/token-extensions/transfer-hook/allow-block-list-token/quasar/src/instructions/attach_to_mint.rs b/tokens/token-extensions/transfer-hook/allow-block-list-token/quasar/src/instructions/attach_to_mint.rs index 962c9df31..b65b139a6 100644 --- a/tokens/token-extensions/transfer-hook/allow-block-list-token/quasar/src/instructions/attach_to_mint.rs +++ b/tokens/token-extensions/transfer-hook/allow-block-list-token/quasar/src/instructions/attach_to_mint.rs @@ -13,7 +13,7 @@ pub struct AttachToMint { pub mint: UncheckedAccount, #[account(mut)] pub extra_metas_account: UncheckedAccount, - pub system_program: Program, + pub system_program: Program, pub token_program: Program, } diff --git a/tokens/token-extensions/transfer-hook/allow-block-list-token/quasar/src/instructions/change_mode.rs b/tokens/token-extensions/transfer-hook/allow-block-list-token/quasar/src/instructions/change_mode.rs index 3d6b342ff..01b980a36 100644 --- a/tokens/token-extensions/transfer-hook/allow-block-list-token/quasar/src/instructions/change_mode.rs +++ b/tokens/token-extensions/transfer-hook/allow-block-list-token/quasar/src/instructions/change_mode.rs @@ -1,4 +1,4 @@ -use quasar_lang::cpi::DynCpiCall; +use quasar_lang::cpi::CpiDynamic; use quasar_lang::prelude::*; use quasar_lang::sysvars::Sysvar; @@ -13,7 +13,7 @@ pub struct ChangeMode { #[account(mut)] pub mint: UncheckedAccount, pub token_program: Program, - pub system_program: Program, + pub system_program: Program, } #[inline(always)] @@ -87,7 +87,7 @@ fn emit_update_field( pos += value.len(); let _ = (mint_key, auth_key); - let mut cpi = DynCpiCall::<2, MAX_META_IX>::new(token_prog); + let mut cpi = CpiDynamic::<2, MAX_META_IX>::new(token_prog); // mint: writable, not signer cpi.push_account(ctx.mint.to_account_view(), false, true)?; // authority: signer, not writable diff --git a/tokens/token-extensions/transfer-hook/allow-block-list-token/quasar/src/instructions/init_config.rs b/tokens/token-extensions/transfer-hook/allow-block-list-token/quasar/src/instructions/init_config.rs index 17676b3a3..32b730a9f 100644 --- a/tokens/token-extensions/transfer-hook/allow-block-list-token/quasar/src/instructions/init_config.rs +++ b/tokens/token-extensions/transfer-hook/allow-block-list-token/quasar/src/instructions/init_config.rs @@ -11,7 +11,7 @@ pub struct InitConfig { pub payer: Signer, #[account(mut)] pub config: UncheckedAccount, - pub system_program: Program, + pub system_program: Program, } #[inline(always)] diff --git a/tokens/token-extensions/transfer-hook/allow-block-list-token/quasar/src/instructions/init_mint.rs b/tokens/token-extensions/transfer-hook/allow-block-list-token/quasar/src/instructions/init_mint.rs index da948f145..ae5b2f381 100644 --- a/tokens/token-extensions/transfer-hook/allow-block-list-token/quasar/src/instructions/init_mint.rs +++ b/tokens/token-extensions/transfer-hook/allow-block-list-token/quasar/src/instructions/init_mint.rs @@ -1,4 +1,4 @@ -use quasar_lang::cpi::{CpiCall, DynCpiCall, InstructionAccount, Seed}; +use quasar_lang::cpi::{CpiCall, CpiDynamic, InstructionAccount, Seed}; use quasar_lang::prelude::*; use quasar_lang::sysvars::Sysvar; @@ -24,7 +24,7 @@ pub struct InitMint { /// ExtraAccountMetaList PDA: ["extra-account-metas", mint] #[account(mut)] pub extra_metas_account: UncheckedAccount, - pub system_program: Program, + pub system_program: Program, pub token_program: Program, } @@ -159,7 +159,7 @@ pub fn handle_init_mint( pos += uri.len(); { - let mut cpi = DynCpiCall::<3, MAX_META_IX>::new(token_prog); + let mut cpi = CpiDynamic::<3, MAX_META_IX>::new(token_prog); cpi.push_account(accounts.mint.to_account_view(), false, true)?; cpi.push_account(accounts.payer.to_account_view(), true, false)?; cpi.push_account(accounts.payer.to_account_view(), true, false)?; @@ -216,7 +216,7 @@ fn emit_update_field_cpi(ctx: &InitMint, key: &[u8], value: &[u8]) -> Result<(), pos += value.len(); let _ = (mint_key, payer_key); - let mut cpi = DynCpiCall::<2, MAX_META_IX>::new(token_prog); + let mut cpi = CpiDynamic::<2, MAX_META_IX>::new(token_prog); cpi.push_account(ctx.mint.to_account_view(), false, true)?; cpi.push_account(ctx.payer.to_account_view(), true, false)?; cpi.set_data(&buf[..pos])?; diff --git a/tokens/token-extensions/transfer-hook/allow-block-list-token/quasar/src/instructions/init_wallet.rs b/tokens/token-extensions/transfer-hook/allow-block-list-token/quasar/src/instructions/init_wallet.rs index e3af0187c..48b56d9e8 100644 --- a/tokens/token-extensions/transfer-hook/allow-block-list-token/quasar/src/instructions/init_wallet.rs +++ b/tokens/token-extensions/transfer-hook/allow-block-list-token/quasar/src/instructions/init_wallet.rs @@ -14,7 +14,7 @@ pub struct InitWallet { pub wallet: UncheckedAccount, #[account(mut)] pub ab_wallet: UncheckedAccount, - pub system_program: Program, + pub system_program: Program, } #[inline(always)] diff --git a/tokens/token-extensions/transfer-hook/counter/quasar/src/lib.rs b/tokens/token-extensions/transfer-hook/counter/quasar/src/lib.rs index 00bc481c5..225a873bb 100644 --- a/tokens/token-extensions/transfer-hook/counter/quasar/src/lib.rs +++ b/tokens/token-extensions/transfer-hook/counter/quasar/src/lib.rs @@ -55,7 +55,7 @@ pub struct InitializeExtraAccountMetaList { /// Counter PDA: ["counter"] #[account(mut)] pub counter_account: UncheckedAccount, - pub system_program: Program, + pub system_program: Program, } #[inline(always)] diff --git a/tokens/token-extensions/transfer-hook/hello-world/quasar/src/lib.rs b/tokens/token-extensions/transfer-hook/hello-world/quasar/src/lib.rs index 387afb332..f2c366e39 100644 --- a/tokens/token-extensions/transfer-hook/hello-world/quasar/src/lib.rs +++ b/tokens/token-extensions/transfer-hook/hello-world/quasar/src/lib.rs @@ -68,7 +68,7 @@ pub struct Initialize { #[account(mut)] pub mint_account: Signer, pub token_program: Program, - pub system_program: Program, + pub system_program: Program, } #[inline(always)] @@ -139,7 +139,7 @@ pub struct InitializeExtraAccountMetaList { #[account(mut)] pub extra_account_meta_list: UncheckedAccount, pub mint: UncheckedAccount, - pub system_program: Program, + pub system_program: Program, } #[inline(always)] diff --git a/tokens/token-extensions/transfer-hook/transfer-cost/quasar/src/lib.rs b/tokens/token-extensions/transfer-hook/transfer-cost/quasar/src/lib.rs index 0fd5b9400..024ca33c8 100644 --- a/tokens/token-extensions/transfer-hook/transfer-cost/quasar/src/lib.rs +++ b/tokens/token-extensions/transfer-hook/transfer-cost/quasar/src/lib.rs @@ -58,7 +58,7 @@ pub struct InitializeExtraAccountMetaList { pub mint: UncheckedAccount, #[account(mut)] pub counter_account: UncheckedAccount, - pub system_program: Program, + pub system_program: Program, } #[inline(always)] diff --git a/tokens/token-extensions/transfer-hook/transfer-switch/quasar/src/lib.rs b/tokens/token-extensions/transfer-hook/transfer-switch/quasar/src/lib.rs index 58861212c..250156ea0 100644 --- a/tokens/token-extensions/transfer-hook/transfer-switch/quasar/src/lib.rs +++ b/tokens/token-extensions/transfer-hook/transfer-switch/quasar/src/lib.rs @@ -67,7 +67,7 @@ pub struct ConfigureAdmin { pub new_admin: UncheckedAccount, #[account(mut)] pub admin_config: UncheckedAccount, - pub system_program: Program, + pub system_program: Program, } #[inline(always)] @@ -131,7 +131,7 @@ pub struct InitializeExtraAccountMetas { pub token_mint: UncheckedAccount, #[account(mut)] pub extra_account_metas_list: UncheckedAccount, - pub system_program: Program, + pub system_program: Program, } #[inline(always)] @@ -196,7 +196,7 @@ pub struct Switch { pub admin_config: UncheckedAccount, #[account(mut)] pub wallet_switch: UncheckedAccount, - pub system_program: Program, + pub system_program: Program, } #[inline(always)] diff --git a/tokens/token-extensions/transfer-hook/whitelist/quasar/src/lib.rs b/tokens/token-extensions/transfer-hook/whitelist/quasar/src/lib.rs index dc3afc0da..690ff1857 100644 --- a/tokens/token-extensions/transfer-hook/whitelist/quasar/src/lib.rs +++ b/tokens/token-extensions/transfer-hook/whitelist/quasar/src/lib.rs @@ -58,7 +58,7 @@ pub struct InitializeExtraAccountMetaList { /// Whitelist PDA: ["white_list"] #[account(mut)] pub white_list: UncheckedAccount, - pub system_program: Program, + pub system_program: Program, } #[inline(always)] diff --git a/tokens/token-fundraiser/quasar/Cargo.toml b/tokens/token-fundraiser/quasar/Cargo.toml index b8bee4098..0b31fe198 100644 --- a/tokens/token-fundraiser/quasar/Cargo.toml +++ b/tokens/token-fundraiser/quasar/Cargo.toml @@ -21,8 +21,8 @@ client = [] debug = [] [dependencies] -quasar-lang = { git = "https://github.com/blueshift-gg/quasar" } -quasar-spl = { git = "https://github.com/blueshift-gg/quasar" } +quasar-lang = { git = "https://github.com/blueshift-gg/quasar", branch = "master" } +quasar-spl = { git = "https://github.com/blueshift-gg/quasar", branch = "master" } solana-instruction = { version = "3.2.0" } [dev-dependencies] diff --git a/tokens/token-fundraiser/quasar/src/instructions/check_contributions.rs b/tokens/token-fundraiser/quasar/src/instructions/check_contributions.rs index 5731db714..61e1bee71 100644 --- a/tokens/token-fundraiser/quasar/src/instructions/check_contributions.rs +++ b/tokens/token-fundraiser/quasar/src/instructions/check_contributions.rs @@ -1,7 +1,7 @@ use { crate::state::Fundraiser, quasar_lang::prelude::*, - quasar_spl::{Token, TokenCpi}, + quasar_spl::prelude::*, }; #[derive(Accounts)] @@ -10,17 +10,16 @@ pub struct CheckContributions { pub maker: Signer, #[account( mut, - has_one = maker, - close = maker, - seeds = Fundraiser::seeds(maker), - bump = fundraiser.bump + has_one(maker), + close(dest = maker), + address = Fundraiser::seeds(maker.address()), )] pub fundraiser: Account, #[account(mut)] pub vault: Account, #[account(mut)] pub maker_ta: Account, - pub token_program: Program, + pub token_program: Program, } #[inline(always)] @@ -31,7 +30,15 @@ pub fn handle_check_contributions(accounts: &mut CheckContributions, bumps: &Che ProgramError::Custom(0) // TargetNotMet ); - let seeds = accounts.fundraiser_seeds(bumps); + // Build PDA signer seeds for the fundraiser: + // ["fundraiser", maker, bump]. Inline rather than via a helper because + // post-PR-#195 the derive no longer emits a `_seeds()` method. + let bump = [bumps.fundraiser]; + let seeds = [ + Seed::from(b"fundraiser" as &[u8]), + Seed::from(accounts.maker.address().as_ref()), + Seed::from(bump.as_ref()), + ]; // Transfer all vault funds to the maker let vault_amount = accounts.vault.amount(); diff --git a/tokens/token-fundraiser/quasar/src/instructions/contribute.rs b/tokens/token-fundraiser/quasar/src/instructions/contribute.rs index fa5d06c29..8fcc02189 100644 --- a/tokens/token-fundraiser/quasar/src/instructions/contribute.rs +++ b/tokens/token-fundraiser/quasar/src/instructions/contribute.rs @@ -1,7 +1,7 @@ use { crate::state::{Contributor, Fundraiser}, quasar_lang::prelude::*, - quasar_spl::{Token, TokenCpi}, + quasar_spl::prelude::*, }; #[derive(Accounts)] @@ -16,7 +16,7 @@ pub struct Contribute { pub contributor_ta: Account, #[account(mut)] pub vault: Account, - pub token_program: Program, + pub token_program: Program, } #[inline(always)] diff --git a/tokens/token-fundraiser/quasar/src/instructions/initialize.rs b/tokens/token-fundraiser/quasar/src/instructions/initialize.rs index 6fa0e4d39..4c7d0bc4d 100644 --- a/tokens/token-fundraiser/quasar/src/instructions/initialize.rs +++ b/tokens/token-fundraiser/quasar/src/instructions/initialize.rs @@ -1,7 +1,7 @@ use { crate::state::{Fundraiser, FundraiserInner}, quasar_lang::prelude::*, - quasar_spl::{Mint, Token}, + quasar_spl::prelude::*, }; #[derive(Accounts)] @@ -9,13 +9,18 @@ pub struct Initialize { #[account(mut)] pub maker: Signer, pub mint_to_raise: Account, - #[account(mut, init, payer = maker, seeds = Fundraiser::seeds(maker), bump)] + #[account(mut, init, payer = maker, address = Fundraiser::seeds(maker.address()))] pub fundraiser: Account, - #[account(mut, init_if_needed, payer = maker, token::mint = mint_to_raise, token::authority = fundraiser)] + #[account( + mut, + init(idempotent), + payer = maker, + token(mint = mint_to_raise, authority = fundraiser, token_program = token_program), + )] pub vault: Account, pub rent: Sysvar, - pub token_program: Program, - pub system_program: Program, + pub token_program: Program, + pub system_program: Program, } #[inline(always)] diff --git a/tokens/token-fundraiser/quasar/src/instructions/refund.rs b/tokens/token-fundraiser/quasar/src/instructions/refund.rs index aadbe0bb7..c6e000ad1 100644 --- a/tokens/token-fundraiser/quasar/src/instructions/refund.rs +++ b/tokens/token-fundraiser/quasar/src/instructions/refund.rs @@ -1,7 +1,7 @@ use { crate::state::{Contributor, ContributorInner, Fundraiser}, quasar_lang::prelude::*, - quasar_spl::{Token, TokenCpi}, + quasar_spl::prelude::*, }; #[derive(Accounts)] @@ -11,9 +11,8 @@ pub struct Refund { pub maker: UncheckedAccount, #[account( mut, - has_one = maker, - seeds = Fundraiser::seeds(maker), - bump = fundraiser.bump + has_one(maker), + address = Fundraiser::seeds(maker.address()), )] pub fundraiser: Account, #[account(mut)] @@ -22,14 +21,21 @@ pub struct Refund { pub contributor_ta: Account, #[account(mut)] pub vault: Account, - pub token_program: Program, + pub token_program: Program, } #[inline(always)] pub fn handle_refund(accounts: &mut Refund, bumps: &RefundBumps) -> Result<(), ProgramError> { let refund_amount = accounts.contributor_account.amount; - let seeds = accounts.fundraiser_seeds(bumps); + // Build PDA signer seeds inline; see comment in check_contributions.rs + // for why we no longer use a struct helper method. + let bump = [bumps.fundraiser]; + let seeds = [ + Seed::from(b"fundraiser" as &[u8]), + Seed::from(accounts.maker.address().as_ref()), + Seed::from(bump.as_ref()), + ]; // Transfer contributor's tokens back from vault accounts.token_program diff --git a/tokens/token-swap/quasar/Cargo.toml b/tokens/token-swap/quasar/Cargo.toml index fc8297ff8..30720fc0e 100644 --- a/tokens/token-swap/quasar/Cargo.toml +++ b/tokens/token-swap/quasar/Cargo.toml @@ -22,8 +22,9 @@ client = [] debug = [] [dependencies] -quasar-lang = { git = "https://github.com/blueshift-gg/quasar" } -quasar-spl = { git = "https://github.com/blueshift-gg/quasar" } +# Pin both quasar deps to branch = "master" so trait impls resolve consistently. +quasar-lang = { git = "https://github.com/blueshift-gg/quasar", branch = "master" } +quasar-spl = { git = "https://github.com/blueshift-gg/quasar", branch = "master" } solana-instruction = { version = "3.2.0" } [dev-dependencies] diff --git a/tokens/token-swap/quasar/Quasar.toml b/tokens/token-swap/quasar/Quasar.toml new file mode 100644 index 000000000..f378bd69e --- /dev/null +++ b/tokens/token-swap/quasar/Quasar.toml @@ -0,0 +1,22 @@ +[project] +name = "quasar_token_swap" + +[toolchain] +type = "solana" + +[testing] +language = "rust" + +[testing.rust] +framework = "quasar-svm" + +[testing.rust.test] +program = "cargo" +args = [ + "test", + "tests::", +] + +[clients] +path = "target/client" +languages = ["rust"] diff --git a/tokens/token-swap/quasar/src/instructions/create_amm.rs b/tokens/token-swap/quasar/src/instructions/create_amm.rs index 2f2cd6be4..5b797a3ea 100644 --- a/tokens/token-swap/quasar/src/instructions/create_amm.rs +++ b/tokens/token-swap/quasar/src/instructions/create_amm.rs @@ -1,4 +1,7 @@ -use {crate::state::Amm, quasar_lang::prelude::*}; +use { + crate::{state::{Amm, AmmInner}, AmmPda}, + quasar_lang::prelude::*, +}; /// Accounts for creating a new AMM. /// @@ -7,13 +10,13 @@ use {crate::state::Amm, quasar_lang::prelude::*}; /// macro seeds reference account addresses, not instruction data. #[derive(Accounts)] pub struct CreateAmm { - #[account(mut, init, payer = payer, seeds = [b"amm"], bump)] + #[account(mut, init, payer = payer, address = AmmPda::seeds())] pub amm: Account, /// Admin authority for the AMM. pub admin: UncheckedAccount, #[account(mut)] pub payer: Signer, - pub system_program: Program, + pub system_program: Program, } #[inline(always)] @@ -21,6 +24,10 @@ pub fn handle_create_amm(accounts: &mut CreateAmm, id: Address, fee: u16) -> Res if fee >= 10000 { return Err(ProgramError::InvalidArgument); } - accounts.amm.set_inner(id, *accounts.admin.address(), fee); + accounts.amm.set_inner(AmmInner { + id, + admin: *accounts.admin.address(), + fee: fee.into(), + }); Ok(()) } diff --git a/tokens/token-swap/quasar/src/instructions/create_pool.rs b/tokens/token-swap/quasar/src/instructions/create_pool.rs index c75e01b41..c7ec5e678 100644 --- a/tokens/token-swap/quasar/src/instructions/create_pool.rs +++ b/tokens/token-swap/quasar/src/instructions/create_pool.rs @@ -1,53 +1,78 @@ use { - crate::state::{Amm, Pool}, + crate::{ + state::{Amm, Pool, PoolInner}, + AmmPda, LiquidityMintPda, PoolAuthorityPda, PoolPda, + }, quasar_lang::prelude::*, - quasar_spl::{Mint, Token}, + quasar_spl::prelude::*, }; /// Accounts for creating a new liquidity pool. /// /// Seeds are based on account addresses: pool = [amm, mint_a, mint_b], -/// pool_authority = [amm, mint_a, mint_b, "authority"], -/// mint_liquidity = [amm, mint_a, mint_b, "liquidity"]. +/// pool_authority = [b"authority", amm, mint_a, mint_b], +/// mint_liquidity = [b"liquidity", amm, mint_a, mint_b]. +/// +/// Note: post-PR-#195 the seed prefix is always emitted first by +/// `#[derive(Seeds)]`, so pool_authority/mint_liquidity now derive with +/// the literal prefix in front (different on-chain addresses than the +/// Anchor sibling, but internally consistent within this program). #[derive(Accounts)] pub struct CreatePool { - #[account(seeds = [b"amm"], bump)] + #[account(address = AmmPda::seeds())] pub amm: Account, - #[account(mut, init, payer = payer, seeds = [amm, mint_a, mint_b], bump)] + #[account( + mut, + init, + payer = payer, + address = PoolPda::seeds(amm.address(), mint_a.address(), mint_b.address()), + )] pub pool: Account, /// Pool authority PDA — signs for pool token operations. - #[account(seeds = [amm, mint_a, mint_b, crate::AUTHORITY_SEED], bump)] + #[account( + address = PoolAuthorityPda::seeds(amm.address(), mint_a.address(), mint_b.address()), + )] pub pool_authority: UncheckedAccount, /// Liquidity token mint — created at a PDA. #[account( mut, init, payer = payer, - seeds = [amm, mint_a, mint_b, crate::LIQUIDITY_SEED], - bump, - mint::decimals = 6, - mint::authority = pool_authority, + address = LiquidityMintPda::seeds(amm.address(), mint_a.address(), mint_b.address()), + mint(decimals = 6, authority = pool_authority, freeze_authority = None, token_program = token_program), )] pub mint_liquidity: Account, pub mint_a: Account, pub mint_b: Account, /// Pool's token A account. - #[account(mut, init_if_needed, payer = payer, token::mint = mint_a, token::authority = pool_authority)] + #[account( + mut, + init(idempotent), + payer = payer, + token(mint = mint_a, authority = pool_authority, token_program = token_program), + )] pub pool_account_a: Account, /// Pool's token B account. - #[account(mut, init_if_needed, payer = payer, token::mint = mint_b, token::authority = pool_authority)] + #[account( + mut, + init(idempotent), + payer = payer, + token(mint = mint_b, authority = pool_authority, token_program = token_program), + )] pub pool_account_b: Account, #[account(mut)] pub payer: Signer, - pub token_program: Program, - pub system_program: Program, + pub token_program: Program, + pub system_program: Program, pub rent: Sysvar, } #[inline(always)] pub fn handle_create_pool(accounts: &mut CreatePool) -> Result<(), ProgramError> { - accounts.pool.amm = *accounts.amm.address(); - accounts.pool.mint_a = *accounts.mint_a.address(); - accounts.pool.mint_b = *accounts.mint_b.address(); + accounts.pool.set_inner(PoolInner { + amm: *accounts.amm.address(), + mint_a: *accounts.mint_a.address(), + mint_b: *accounts.mint_b.address(), + }); Ok(()) } diff --git a/tokens/token-swap/quasar/src/instructions/deposit_liquidity.rs b/tokens/token-swap/quasar/src/instructions/deposit_liquidity.rs index a8ec95cb0..5abbc4c92 100644 --- a/tokens/token-swap/quasar/src/instructions/deposit_liquidity.rs +++ b/tokens/token-swap/quasar/src/instructions/deposit_liquidity.rs @@ -1,7 +1,10 @@ use { - crate::state::{Amm, Pool}, + crate::{ + state::{Amm, Pool}, + AmmPda, LiquidityMintPda, PoolAuthorityPda, PoolPda, + }, quasar_lang::prelude::*, - quasar_spl::{Mint, Token, TokenCpi}, + quasar_spl::prelude::*, }; /// Accounts for depositing liquidity into a pool. @@ -10,16 +13,16 @@ use { /// must be provided as separate account inputs. #[derive(Accounts)] pub struct DepositLiquidity { - #[account(seeds = [b"amm"], bump)] + #[account(address = AmmPda::seeds())] pub amm: Account, - #[account(seeds = [amm, mint_a, mint_b], bump)] + #[account(address = PoolPda::seeds(amm.address(), mint_a.address(), mint_b.address()))] pub pool: Account, /// Pool authority PDA. - #[account(seeds = [amm, mint_a, mint_b, crate::AUTHORITY_SEED], bump)] + #[account(address = PoolAuthorityPda::seeds(amm.address(), mint_a.address(), mint_b.address()))] pub pool_authority: UncheckedAccount, /// Depositor (must be signer to authorise transfers). pub depositor: Signer, - #[account(mut, seeds = [amm, mint_a, mint_b, crate::LIQUIDITY_SEED], bump)] + #[account(mut, address = LiquidityMintPda::seeds(amm.address(), mint_a.address(), mint_b.address()))] pub mint_liquidity: Account, pub mint_a: Account, pub mint_b: Account, @@ -30,7 +33,12 @@ pub struct DepositLiquidity { #[account(mut)] pub pool_account_b: Account, /// Depositor's LP token account. - #[account(mut, init_if_needed, payer = payer, token::mint = mint_liquidity, token::authority = depositor)] + #[account( + mut, + init(idempotent), + payer = payer, + token(mint = mint_liquidity, authority = depositor, token_program = token_program), + )] pub depositor_account_liquidity: Account, /// Depositor's token A account. #[account(mut)] @@ -40,8 +48,8 @@ pub struct DepositLiquidity { pub depositor_account_b: Account, #[account(mut)] pub payer: Signer, - pub token_program: Program, - pub system_program: Program, + pub token_program: Program, + pub system_program: Program, } /// Integer square root via Newton's method. @@ -117,12 +125,13 @@ pub fn handle_deposit_liquidity( .invoke()?; // Mint LP tokens to the depositor (signed by pool authority). + // Seed order matches PoolAuthorityPda: [b"authority", amm, mint_a, mint_b, bump]. let bump = [bumps.pool_authority]; let seeds: &[Seed] = &[ + Seed::from(crate::AUTHORITY_SEED), Seed::from(accounts.amm.address().as_ref()), Seed::from(accounts.mint_a.address().as_ref()), Seed::from(accounts.mint_b.address().as_ref()), - Seed::from(crate::AUTHORITY_SEED), Seed::from(&bump as &[u8]), ]; diff --git a/tokens/token-swap/quasar/src/instructions/swap_exact_tokens_for_tokens.rs b/tokens/token-swap/quasar/src/instructions/swap_exact_tokens_for_tokens.rs index 92cdc9118..220f50b18 100644 --- a/tokens/token-swap/quasar/src/instructions/swap_exact_tokens_for_tokens.rs +++ b/tokens/token-swap/quasar/src/instructions/swap_exact_tokens_for_tokens.rs @@ -1,18 +1,21 @@ use { - crate::state::{Amm, Pool}, + crate::{ + state::{Amm, Pool}, + AmmPda, PoolAuthorityPda, PoolPda, + }, quasar_lang::prelude::*, - quasar_spl::{Mint, Token, TokenCpi}, + quasar_spl::prelude::*, }; /// Accounts for swapping tokens using the constant-product formula. #[derive(Accounts)] pub struct SwapExactTokensForTokens { - #[account(seeds = [b"amm"], bump)] + #[account(address = AmmPda::seeds())] pub amm: Account, - #[account(seeds = [amm, mint_a, mint_b], bump)] + #[account(address = PoolPda::seeds(amm.address(), mint_a.address(), mint_b.address()))] pub pool: Account, /// Pool authority PDA. - #[account(seeds = [amm, mint_a, mint_b, crate::AUTHORITY_SEED], bump)] + #[account(address = PoolAuthorityPda::seeds(amm.address(), mint_a.address(), mint_b.address()))] pub pool_authority: UncheckedAccount, pub trader: Signer, pub mint_a: Account, @@ -21,14 +24,24 @@ pub struct SwapExactTokensForTokens { pub pool_account_a: Account, #[account(mut)] pub pool_account_b: Account, - #[account(mut, init_if_needed, payer = payer, token::mint = mint_a, token::authority = trader)] + #[account( + mut, + init(idempotent), + payer = payer, + token(mint = mint_a, authority = trader, token_program = token_program), + )] pub trader_account_a: Account, - #[account(mut, init_if_needed, payer = payer, token::mint = mint_b, token::authority = trader)] + #[account( + mut, + init(idempotent), + payer = payer, + token(mint = mint_b, authority = trader, token_program = token_program), + )] pub trader_account_b: Account, #[account(mut)] pub payer: Signer, - pub token_program: Program, - pub system_program: Program, + pub token_program: Program, + pub system_program: Program, } #[inline(always)] @@ -88,12 +101,13 @@ pub fn handle_swap_exact_tokens_for_tokens( .ok_or(ProgramError::ArithmeticOverflow)?; // Build authority signer seeds. + // Seed order matches PoolAuthorityPda: [b"authority", amm, mint_a, mint_b, bump]. let bump = [bumps.pool_authority]; let seeds: &[Seed] = &[ + Seed::from(crate::AUTHORITY_SEED), Seed::from(accounts.amm.address().as_ref()), Seed::from(accounts.mint_a.address().as_ref()), Seed::from(accounts.mint_b.address().as_ref()), - Seed::from(crate::AUTHORITY_SEED), Seed::from(&bump as &[u8]), ]; diff --git a/tokens/token-swap/quasar/src/instructions/withdraw_liquidity.rs b/tokens/token-swap/quasar/src/instructions/withdraw_liquidity.rs index 6fc9ecf69..d9cdff0a3 100644 --- a/tokens/token-swap/quasar/src/instructions/withdraw_liquidity.rs +++ b/tokens/token-swap/quasar/src/instructions/withdraw_liquidity.rs @@ -1,21 +1,24 @@ use { - crate::state::{Amm, Pool}, + crate::{ + state::{Amm, Pool}, + AmmPda, LiquidityMintPda, PoolAuthorityPda, PoolPda, + }, quasar_lang::prelude::*, - quasar_spl::{Mint, Token, TokenCpi}, + quasar_spl::prelude::*, }; /// Accounts for withdrawing liquidity from a pool. #[derive(Accounts)] pub struct WithdrawLiquidity { - #[account(seeds = [b"amm"], bump)] + #[account(address = AmmPda::seeds())] pub amm: Account, - #[account(seeds = [amm, mint_a, mint_b], bump)] + #[account(address = PoolPda::seeds(amm.address(), mint_a.address(), mint_b.address()))] pub pool: Account, /// Pool authority PDA. - #[account(seeds = [amm, mint_a, mint_b, crate::AUTHORITY_SEED], bump)] + #[account(address = PoolAuthorityPda::seeds(amm.address(), mint_a.address(), mint_b.address()))] pub pool_authority: UncheckedAccount, pub depositor: Signer, - #[account(mut, seeds = [amm, mint_a, mint_b, crate::LIQUIDITY_SEED], bump)] + #[account(mut, address = LiquidityMintPda::seeds(amm.address(), mint_a.address(), mint_b.address()))] pub mint_liquidity: Account, #[account(mut)] pub mint_a: Account, @@ -27,14 +30,24 @@ pub struct WithdrawLiquidity { pub pool_account_b: Account, #[account(mut)] pub depositor_account_liquidity: Account, - #[account(mut, init_if_needed, payer = payer, token::mint = mint_a, token::authority = depositor)] + #[account( + mut, + init(idempotent), + payer = payer, + token(mint = mint_a, authority = depositor, token_program = token_program), + )] pub depositor_account_a: Account, - #[account(mut, init_if_needed, payer = payer, token::mint = mint_b, token::authority = depositor)] + #[account( + mut, + init(idempotent), + payer = payer, + token(mint = mint_b, authority = depositor, token_program = token_program), + )] pub depositor_account_b: Account, #[account(mut)] pub payer: Signer, - pub token_program: Program, - pub system_program: Program, + pub token_program: Program, + pub system_program: Program, } #[inline(always)] @@ -43,12 +56,13 @@ pub fn handle_withdraw_liquidity( amount: u64, bumps: &WithdrawLiquidityBumps, ) -> Result<(), ProgramError> { + // Seed order matches PoolAuthorityPda: [b"authority", amm, mint_a, mint_b, bump]. let bump = [bumps.pool_authority]; let seeds: &[Seed] = &[ + Seed::from(crate::AUTHORITY_SEED), Seed::from(accounts.amm.address().as_ref()), Seed::from(accounts.mint_a.address().as_ref()), Seed::from(accounts.mint_b.address().as_ref()), - Seed::from(crate::AUTHORITY_SEED), Seed::from(&bump as &[u8]), ]; diff --git a/tokens/token-swap/quasar/src/lib.rs b/tokens/token-swap/quasar/src/lib.rs index 21ecd409c..af9116272 100644 --- a/tokens/token-swap/quasar/src/lib.rs +++ b/tokens/token-swap/quasar/src/lib.rs @@ -17,6 +17,37 @@ pub const AUTHORITY_SEED: &[u8] = b"authority"; /// Seed for the liquidity mint PDA. pub const LIQUIDITY_SEED: &[u8] = b"liquidity"; +// PDA seed markers required since PR #195 (inline `seeds = [...]` is gone). +// Each marker captures the prefix and Address args; `address = T::seeds(...)` +// drives derivation in the `#[account]` constraint. + +/// AMM PDA at seeds = [b"amm"]. +#[derive(Seeds)] +#[seeds(b"amm")] +pub struct AmmPda; + +/// Pool PDA at seeds = [amm, mint_a, mint_b] — no string prefix. +#[derive(Seeds)] +#[seeds(b"", amm: Address, mint_a: Address, mint_b: Address)] +pub struct PoolPda; + +/// Pool-authority PDA at seeds = [amm, mint_a, mint_b, b"authority"]. +/// Modelled with prefix b"authority" + the three Address args; the +/// rendered slice list ends up [amm, mint_a, mint_b, b"authority"] when +/// you use `with_bump`. Note: the new \`#[seeds]\` puts the literal +/// prefix first, so the on-chain derivation order is +/// [b"authority", amm, mint_a, mint_b] — different from the original +/// Anchor scheme. Programs are independent so this is consistent and +/// correct on its own; the addresses just won't match the Anchor copy. +#[derive(Seeds)] +#[seeds(b"authority", amm: Address, mint_a: Address, mint_b: Address)] +pub struct PoolAuthorityPda; + +/// Liquidity-mint PDA at seeds = [b"liquidity", amm, mint_a, mint_b]. +#[derive(Seeds)] +#[seeds(b"liquidity", amm: Address, mint_a: Address, mint_b: Address)] +pub struct LiquidityMintPda; + /// Simple constant-product AMM (token swap). /// /// Five instructions: diff --git a/tokens/token-swap/quasar/src/state.rs b/tokens/token-swap/quasar/src/state.rs index 15154eba6..1e8808755 100644 --- a/tokens/token-swap/quasar/src/state.rs +++ b/tokens/token-swap/quasar/src/state.rs @@ -3,7 +3,7 @@ use quasar_lang::prelude::*; /// Automated Market Maker configuration. /// /// Stores the AMM identifier, admin, and fee (in basis points). -#[account(discriminator = 100)] +#[account(discriminator = 100, set_inner)] pub struct Amm { /// Unique identifier for this AMM. pub id: Address, @@ -14,7 +14,7 @@ pub struct Amm { } /// Liquidity pool linking an AMM to a pair of token mints. -#[account(discriminator = 101)] +#[account(discriminator = 101, set_inner)] pub struct Pool { /// The AMM this pool belongs to. pub amm: Address, diff --git a/tokens/transfer-tokens/quasar/Cargo.toml b/tokens/transfer-tokens/quasar/Cargo.toml index b7c4aace9..7dbac6150 100644 --- a/tokens/transfer-tokens/quasar/Cargo.toml +++ b/tokens/transfer-tokens/quasar/Cargo.toml @@ -22,8 +22,8 @@ client = [] debug = [] [dependencies] -quasar-lang = { git = "https://github.com/blueshift-gg/quasar" } -quasar-spl = { git = "https://github.com/blueshift-gg/quasar" } +quasar-lang = { git = "https://github.com/blueshift-gg/quasar", branch = "master" } +quasar-spl = { git = "https://github.com/blueshift-gg/quasar", branch = "master" } solana-instruction = { version = "3.2.0" } [dev-dependencies] diff --git a/tokens/transfer-tokens/quasar/src/lib.rs b/tokens/transfer-tokens/quasar/src/lib.rs index 3f148405d..bec0f28c8 100644 --- a/tokens/transfer-tokens/quasar/src/lib.rs +++ b/tokens/transfer-tokens/quasar/src/lib.rs @@ -1,7 +1,7 @@ #![cfg_attr(not(test), no_std)] use quasar_lang::prelude::*; -use quasar_spl::{Mint, Token, TokenCpi}; +use quasar_spl::prelude::*; #[cfg(test)] mod tests; @@ -40,7 +40,7 @@ pub struct MintTokens { /// The recipient's token account. Must already exist. #[account(mut)] pub recipient_token_account: Account, - pub token_program: Program, + pub token_program: Program, } #[inline(always)] @@ -59,7 +59,7 @@ pub struct TransferTokens { pub sender_token_account: Account, #[account(mut)] pub recipient_token_account: Account, - pub token_program: Program, + pub token_program: Program, } #[inline(always)]