diff --git a/Anchor.toml b/Anchor.toml index 2fc8db5..850f331 100644 --- a/Anchor.toml +++ b/Anchor.toml @@ -5,8 +5,8 @@ resolution = true skip-lint = false [programs.localnet] -libreplex_editions = "GHVmd43GebD2SSedqG1AAh76izf5CPAhz6KotkZyRzUD" -libreplex_editions_controls = "CCWfNBFcrjbKSjKes9DqgiQYsnmCFgCVKx21mmV2xWgN" +libreplex_editions = "A927QYSgP2fJWWDJn1gZknSfsMXyyKnJvMf2kJoY5yeQ" +libreplex_editions_controls = "5GSxbLSQms8VoBmNPEsPPyr8TtSApX19cP8jAg4isJ3K" [registry] url = "https://api.apr.dev" @@ -14,7 +14,7 @@ url = "https://api.apr.dev" [provider] cluster = "Localnet" ### @dev testing wallet -# wallet = "~/.config/solana/id.json" +### wallet = "~/.config/solana/id.json" wallet = "usb://ledger" [scripts] @@ -27,8 +27,8 @@ upgradeable = false [test.validator] bind_address = "0.0.0.0" -### @dev: Utilize the testnet cluster for running the testsuite -# url = "https://api.testnet.solana.com" +### @dev: Utilize the testnet cluster for running test-suite with anchor test +### url = "https://api.testnet.solana.com" url = "https://api.mainnet-beta.solana.com" ledger = ".anchor/test-ledger" rpc_port = 8899 @@ -47,4 +47,3 @@ address = "metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s" [[test.validator.clone]] address = "5hx15GaPPqsYA61v6QpcGPpo125v7rfvEfZQ4dJErG5V" - diff --git a/programs/libreplex_editions/src/lib.rs b/programs/libreplex_editions/src/lib.rs index 6864fcd..5698221 100644 --- a/programs/libreplex_editions/src/lib.rs +++ b/programs/libreplex_editions/src/lib.rs @@ -2,7 +2,8 @@ use anchor_lang::prelude::*; pub mod instructions; pub use instructions::*; -declare_id!("GHVmd43GebD2SSedqG1AAh76izf5CPAhz6KotkZyRzUD"); + +declare_id!("A927QYSgP2fJWWDJn1gZknSfsMXyyKnJvMf2kJoY5yeQ"); pub mod errors; pub mod state; diff --git a/programs/libreplex_editions_controls/src/instructions/add_phase.rs b/programs/libreplex_editions_controls/src/instructions/add_phase.rs index 54569e8..4430c2b 100644 --- a/programs/libreplex_editions_controls/src/instructions/add_phase.rs +++ b/programs/libreplex_editions_controls/src/instructions/add_phase.rs @@ -48,6 +48,11 @@ pub fn add_phase(ctx: Context, input: InitialisePhaseInput) -> Resu if !input.price_token.eq(&wrapped_sol::ID) { panic!("Only native price currently supported") } + + if input.is_private && input.merkle_root.is_none() { + panic!("Merkle root must be provided for private phases"); + } + let editions_controls = &mut ctx.accounts.editions_controls; editions_controls.phases.push(Phase{ diff --git a/programs/libreplex_editions_controls/src/lib.rs b/programs/libreplex_editions_controls/src/lib.rs index c8dd037..979c594 100644 --- a/programs/libreplex_editions_controls/src/lib.rs +++ b/programs/libreplex_editions_controls/src/lib.rs @@ -5,7 +5,7 @@ pub use logic::*; pub mod instructions; pub use instructions::*; -declare_id!("CCWfNBFcrjbKSjKes9DqgiQYsnmCFgCVKx21mmV2xWgN"); +declare_id!("5GSxbLSQms8VoBmNPEsPPyr8TtSApX19cP8jAg4isJ3K"); pub mod errors; pub mod state; diff --git a/target/types/libreplex_editions.ts b/target/types/libreplex_editions.ts index c40adca..8da7bf3 100644 --- a/target/types/libreplex_editions.ts +++ b/target/types/libreplex_editions.ts @@ -5,7 +5,7 @@ * IDL can be found at `target/idl/libreplex_editions.json`. */ export type LibreplexEditions = { - "address": "5hx15GaPPqsYA61v6QpcGPpo125v7rfvEfZQ4dJErG5V", + "address": "A927QYSgP2fJWWDJn1gZknSfsMXyyKnJvMf2kJoY5yeQ", "metadata": { "name": "libreplexEditions", "version": "0.2.1", diff --git a/target/types/libreplex_editions_controls.ts b/target/types/libreplex_editions_controls.ts index 758cdd3..354c43a 100644 --- a/target/types/libreplex_editions_controls.ts +++ b/target/types/libreplex_editions_controls.ts @@ -5,7 +5,7 @@ * IDL can be found at `target/idl/libreplex_editions_controls.json`. */ export type LibreplexEditionsControls = { - "address": "CCWfNBFcrjbKSjKes9DqgiQYsnmCFgCVKx21mmV2xWgN", + "address": "5GSxbLSQms8VoBmNPEsPPyr8TtSApX19cP8jAg4isJ3K", "metadata": { "name": "libreplexEditionsControls", "version": "0.2.1", @@ -51,7 +51,7 @@ export type LibreplexEditionsControls = { }, { "name": "libreplexEditionsProgram", - "address": "GHVmd43GebD2SSedqG1AAh76izf5CPAhz6KotkZyRzUD" + "address": "A927QYSgP2fJWWDJn1gZknSfsMXyyKnJvMf2kJoY5yeQ" } ], "args": [ @@ -152,7 +152,7 @@ export type LibreplexEditionsControls = { }, { "name": "libreplexEditionsProgram", - "address": "GHVmd43GebD2SSedqG1AAh76izf5CPAhz6KotkZyRzUD" + "address": "A927QYSgP2fJWWDJn1gZknSfsMXyyKnJvMf2kJoY5yeQ" } ], "args": [ @@ -365,7 +365,7 @@ export type LibreplexEditionsControls = { }, { "name": "libreplexEditionsProgram", - "address": "GHVmd43GebD2SSedqG1AAh76izf5CPAhz6KotkZyRzUD" + "address": "A927QYSgP2fJWWDJn1gZknSfsMXyyKnJvMf2kJoY5yeQ" } ], "args": [ @@ -595,7 +595,7 @@ export type LibreplexEditionsControls = { }, { "name": "libreplexEditionsProgram", - "address": "GHVmd43GebD2SSedqG1AAh76izf5CPAhz6KotkZyRzUD" + "address": "A927QYSgP2fJWWDJn1gZknSfsMXyyKnJvMf2kJoY5yeQ" } ], "args": [ diff --git a/test/tests/editions_controls.test.ts b/test/tests/editions_controls.test.ts index 903fc02..38e558c 100644 --- a/test/tests/editions_controls.test.ts +++ b/test/tests/editions_controls.test.ts @@ -510,6 +510,47 @@ describe('Editions Controls Test Suite', () => { // verify state expect(editionsControlsDecoded.data.phases.length).to.equal(6); }); + + it('Should fail to add a private phase without providing the merkle root', async () => { + const invalidPhaseConfig = { + maxMintsPerWallet: new anchor.BN(100), + maxMintsTotal: new anchor.BN(1000), + priceAmount: new anchor.BN(500000), // 0.05 SOL + startTime: new anchor.BN(new Date().getTime() / 1000), + endTime: new anchor.BN(new Date().getTime() / 1000 + 60 * 60 * 24), // 1 day from now + priceToken: new PublicKey('So11111111111111111111111111111111111111112'), + isPrivate: true, + merkleRoot: null, // Invalid: null merkle root for private phase + }; + + const phaseIx = await editionsControlsProgram.methods + .addPhase(invalidPhaseConfig) + .accountsStrict({ + editionsControls: editionsControlsPda, + creator: payer.publicKey, + payer: payer.publicKey, + systemProgram: SystemProgram.programId, + tokenProgram: TOKEN_2022_PROGRAM_ID, + libreplexEditionsProgram: editionsProgram.programId, + }) + .signers([]) + .instruction(); + + const transaction = new Transaction().add(phaseIx); + + try { + await provider.sendAndConfirm(transaction, [payer]); + // If we reach this point, the test should fail + expect.fail('Transaction should have failed'); + } catch (error) { + const errorString = JSON.stringify(error); + expect(errorString).to.include('Merkle root must be provided for private phases'); + } + + // Verify state hasn't changed + const editionsControlsDecoded = await getEditionsControls(provider.connection, editionsControlsPda, editionsControlsProgram); + expect(editionsControlsDecoded.data.phases.length).to.equal(6); // Should still be 6 phases + }) }); describe('Minting', () => {