diff --git a/README.md b/README.md index cb89fd5..73f96bd 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # Metaplex Candy Machine -# Docs/readmes inside this repo are not up to date, check the tests for usage examples +# Docs/readmes inside this repo are not up to date, for glass chewers check the tests for usage examples The Metaplex Protocol Candy Machine is the leading minting and distribution program for fair NFT collection launches on Solana. It allows creators to bring their digital assets on-chain in a secure and customisable way. diff --git a/clients/js/package.json b/clients/js/package.json index d371f15..418d6db 100644 --- a/clients/js/package.json +++ b/clients/js/package.json @@ -26,7 +26,7 @@ "license": "Apache-2.0", "peerDependencies": { "@metaplex-foundation/umi": ">= 0.8.2 < 1", - "@metaplex-foundation/mpl-core": "^0.1.0" + "@metaplex-foundation/mpl-core": "^0.3.0" }, "dependencies": { "@metaplex-foundation/mpl-token-metadata": "3.0.0-alpha.27", diff --git a/clients/js/pnpm-lock.yaml b/clients/js/pnpm-lock.yaml index b330dee..e1ff65e 100644 --- a/clients/js/pnpm-lock.yaml +++ b/clients/js/pnpm-lock.yaml @@ -1,6 +1,9 @@ lockfileVersion: '6.0' dependencies: + '@metaplex-foundation/mpl-core': + specifier: ^0.3.0 + version: 0.3.0(@metaplex-foundation/mpl-toolbox@0.9.0)(@metaplex-foundation/umi@0.8.2)(@noble/hashes@1.2.0) '@metaplex-foundation/mpl-token-metadata': specifier: 3.0.0-alpha.27 version: 3.0.0-alpha.27(@metaplex-foundation/umi@0.8.2) @@ -10,9 +13,6 @@ dependencies: '@noble/hashes': specifier: ^1.2.0 version: 1.2.0 - core-preview: - specifier: ^0.1.1 - version: 0.1.1(@metaplex-foundation/mpl-toolbox@0.9.0)(@metaplex-foundation/umi@0.8.2)(@noble/hashes@1.2.0) merkletreejs: specifier: ^0.3.9 version: 0.3.9 @@ -1944,6 +1944,18 @@ packages: resolution: {integrity: sha512-S9RulC2fFCFOQraz61bij+5YCHhSO9llJegK8c8Y6731fSi6snUSQJdCUqYS8AIgR0TKbQvdvgSyIIdbDFZbBA==} dev: true + /@metaplex-foundation/mpl-core@0.3.0(@metaplex-foundation/mpl-toolbox@0.9.0)(@metaplex-foundation/umi@0.8.2)(@noble/hashes@1.2.0): + resolution: {integrity: sha512-ZGK4sVSlRWLkZQpYzctEF978lCOXKTy73Jr7IKIFXK3C2xGLEg4GRuN/SBtByQA5u/vxqkAp04ZiVXhoVWtJSQ==} + peerDependencies: + '@metaplex-foundation/mpl-toolbox': ^0.8.0 + '@metaplex-foundation/umi': ^0.8.2 + '@noble/hashes': ^1.3.1 + dependencies: + '@metaplex-foundation/mpl-toolbox': 0.9.0(@metaplex-foundation/umi@0.8.2) + '@metaplex-foundation/umi': 0.8.2 + '@noble/hashes': 1.2.0 + dev: false + /@metaplex-foundation/mpl-token-auth-rules@1.2.0: resolution: {integrity: sha512-UkfBkYEdenefIKxE2L15j9ZHUJYYRQoDqNqDawh5DxdemmVV3GLnIlbMilr/HLXyXb2eMAOUdl5XgZFwKYN5EA==} dependencies: @@ -3853,18 +3865,6 @@ packages: browserslist: 4.21.9 dev: true - /core-preview@0.1.1(@metaplex-foundation/mpl-toolbox@0.9.0)(@metaplex-foundation/umi@0.8.2)(@noble/hashes@1.2.0): - resolution: {integrity: sha512-f/l7q6GQioQ561WukRNBmBPFXPfOxLvM9Ri7wXfFqxBMH8EgnB18pMURT3NxImpRYdlVB5Qxo6ic42d4w2vLuA==} - peerDependencies: - '@metaplex-foundation/mpl-toolbox': ^0.8.0 - '@metaplex-foundation/umi': ^0.8.2 - '@noble/hashes': ^1.3.1 - dependencies: - '@metaplex-foundation/mpl-toolbox': 0.9.0(@metaplex-foundation/umi@0.8.2) - '@metaplex-foundation/umi': 0.8.2 - '@noble/hashes': 1.2.0 - dev: false - /core-util-is@1.0.3: resolution: {integrity: sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==} dev: true diff --git a/clients/js/src/createCandyMachineV2.ts b/clients/js/src/createCandyMachineV2.ts index 57fff51..84eaa5d 100644 --- a/clients/js/src/createCandyMachineV2.ts +++ b/clients/js/src/createCandyMachineV2.ts @@ -23,7 +23,7 @@ export const createCandyMachineV2 = async ( ): Promise => { const space = getCandyMachineSize( input.itemsAvailable, - input.configLineSettings ?? none(), + input.configLineSettings ?? none() ); const lamports = await context.rpc.getRent(space); return transactionBuilder() diff --git a/clients/js/src/createLutForCandyMachine.ts b/clients/js/src/createLutForCandyMachine.ts index 74a1aa7..902a384 100644 --- a/clients/js/src/createLutForCandyMachine.ts +++ b/clients/js/src/createLutForCandyMachine.ts @@ -1,6 +1,4 @@ -import { - getMplTokenMetadataProgramId, -} from '@metaplex-foundation/mpl-token-metadata'; +import { getMplTokenMetadataProgramId } from '@metaplex-foundation/mpl-token-metadata'; import { createLut, getSysvar, diff --git a/clients/js/src/defaultGuards/freezeSolPayment.ts b/clients/js/src/defaultGuards/freezeSolPayment.ts index 757e8d1..a8b0432 100644 --- a/clients/js/src/defaultGuards/freezeSolPayment.ts +++ b/clients/js/src/defaultGuards/freezeSolPayment.ts @@ -1,6 +1,4 @@ -import { - getSplSystemProgramId, -} from '@metaplex-foundation/mpl-toolbox'; +import { getSplSystemProgramId } from '@metaplex-foundation/mpl-toolbox'; import { PublicKey, Signer } from '@metaplex-foundation/umi'; import { tuple, u64 } from '@metaplex-foundation/umi/serializers'; import { getMplCoreProgramId } from '@metaplex-foundation/mpl-core'; @@ -44,9 +42,7 @@ export const freezeSolPaymentGuardManifest: GuardManifest< return { data: new Uint8Array(), - remainingAccounts: [ - { publicKey: freezeEscrow, isWritable: true }, - ], + remainingAccounts: [{ publicKey: freezeEscrow, isWritable: true }], }; }, routeParser: (context, routeContext, args) => { @@ -70,8 +66,7 @@ export const freezeSolPaymentGuardManifest: GuardManifest< export type FreezeSolPaymentMintArgs = Omit< FreezeSolPaymentArgs, 'lamports' -> & { -}; +> & {}; /** * The settings for the freezeSolPayment guard that should be provided diff --git a/clients/js/src/defaultGuards/freezeTokenPayment.ts b/clients/js/src/defaultGuards/freezeTokenPayment.ts index a3e8199..c4b7f17 100644 --- a/clients/js/src/defaultGuards/freezeTokenPayment.ts +++ b/clients/js/src/defaultGuards/freezeTokenPayment.ts @@ -59,7 +59,7 @@ export const freezeTokenPaymentGuardManifest: GuardManifest< { publicKey: freezeEscrow, isWritable: true }, { publicKey: tokenAddress, isWritable: true }, { publicKey: freezeAta, isWritable: true }, - { publicKey: getSplTokenProgramId(context), isWritable: false} + { publicKey: getSplTokenProgramId(context), isWritable: false }, ], }; }, @@ -84,8 +84,7 @@ export const freezeTokenPaymentGuardManifest: GuardManifest< export type FreezeTokenPaymentMintArgs = Omit< FreezeTokenPaymentArgs, 'amount' -> & { -}; +> & {}; /** * The settings for the freezeTokenPayment guard that should be provided diff --git a/clients/js/src/defaultGuards/nftBurn.ts b/clients/js/src/defaultGuards/nftBurn.ts index 187c655..3baca42 100644 --- a/clients/js/src/defaultGuards/nftBurn.ts +++ b/clients/js/src/defaultGuards/nftBurn.ts @@ -1,4 +1,7 @@ -import { findAssociatedTokenPda, getSplTokenProgramId } from '@metaplex-foundation/mpl-toolbox'; +import { + findAssociatedTokenPda, + getSplTokenProgramId, +} from '@metaplex-foundation/mpl-toolbox'; import { findMasterEditionPda, findMetadataPda, diff --git a/clients/js/src/defaultGuards/nftPayment.ts b/clients/js/src/defaultGuards/nftPayment.ts index 12bf931..7d4bb28 100644 --- a/clients/js/src/defaultGuards/nftPayment.ts +++ b/clients/js/src/defaultGuards/nftPayment.ts @@ -67,7 +67,7 @@ export const nftPaymentGuardManifest: GuardManifest< { publicKey: getMplTokenMetadataProgramId(context), isWritable: false, - } + }, ]; if (isProgrammable(args.tokenStandard)) { diff --git a/clients/js/src/defaultGuards/tokenBurn.ts b/clients/js/src/defaultGuards/tokenBurn.ts index bc1d82b..c15a62f 100644 --- a/clients/js/src/defaultGuards/tokenBurn.ts +++ b/clients/js/src/defaultGuards/tokenBurn.ts @@ -1,4 +1,7 @@ -import { findAssociatedTokenPda, getSplTokenProgramId } from '@metaplex-foundation/mpl-toolbox'; +import { + findAssociatedTokenPda, + getSplTokenProgramId, +} from '@metaplex-foundation/mpl-toolbox'; import { getTokenBurnSerializer, TokenBurn, TokenBurnArgs } from '../generated'; import { GuardManifest, noopParser } from '../guards'; diff --git a/clients/js/src/defaultGuards/tokenPayment.ts b/clients/js/src/defaultGuards/tokenPayment.ts index 64b0a32..deaed9f 100644 --- a/clients/js/src/defaultGuards/tokenPayment.ts +++ b/clients/js/src/defaultGuards/tokenPayment.ts @@ -1,4 +1,7 @@ -import { findAssociatedTokenPda, getSplTokenProgramId } from '@metaplex-foundation/mpl-toolbox'; +import { + findAssociatedTokenPda, + getSplTokenProgramId, +} from '@metaplex-foundation/mpl-toolbox'; import { getTokenPaymentSerializer, TokenPayment, diff --git a/clients/js/src/hooked/candyMachineAccountData.ts b/clients/js/src/hooked/candyMachineAccountData.ts index 7ff93b5..ba72c44 100644 --- a/clients/js/src/hooked/candyMachineAccountData.ts +++ b/clients/js/src/hooked/candyMachineAccountData.ts @@ -97,8 +97,7 @@ export function getCandyMachineAccountDataSerializer(): Serializer< ['itemsLeftToMint', array(u32(), { size: itemsAvailable })], ]); - const [hiddenSection] = - hiddenSectionSerializer.deserialize(slice); + const [hiddenSection] = hiddenSectionSerializer.deserialize(slice); const itemsLeftToMint = hiddenSection.itemsLeftToMint.slice( 0, diff --git a/clients/js/src/plugin.ts b/clients/js/src/plugin.ts index 787b5cb..afbb248 100644 --- a/clients/js/src/plugin.ts +++ b/clients/js/src/plugin.ts @@ -81,7 +81,7 @@ export const mplCandyMachine = (): UmiPlugin => ({ allocationGuardManifest, token2022PaymentGuardManifest, solFixedFeeGuardManifest, - nftMintLimitGuardManifest, + nftMintLimitGuardManifest ); }, }); diff --git a/clients/js/test/_setup.ts b/clients/js/test/_setup.ts index 0aaed6a..78db0fe 100644 --- a/clients/js/test/_setup.ts +++ b/clients/js/test/_setup.ts @@ -7,11 +7,11 @@ import { findMetadataPda, verifyCollectionV1, } from '@metaplex-foundation/mpl-token-metadata'; -import { +import { AssetV1, fetchAssetV1, createCollectionV1 as baseCreateCollection, -} from '@metaplex-foundation/mpl-core' +} from '@metaplex-foundation/mpl-core'; import { createAssociatedToken, createMint, @@ -98,7 +98,7 @@ export const createCollection = async ( }).sendAndConfirm(umi); return mint; -} +}; export const createCollectionNft = async ( umi: Umi, @@ -246,7 +246,7 @@ export const defaultAssetData = () => ({ name: 'My Asset', sellerFeeBasisPoints: percentAmount(10, 2), uri: 'https://example.com/my-asset.json', - plugins: [] + plugins: [], }); export const defaultCandyMachineData = ( @@ -303,21 +303,17 @@ export const assertSuccessfulMint = async ( ) => { const mint = publicKey(input.mint); const owner = publicKey(input.owner); - const { - name, - uri, - } = input; + const { name, uri } = input; // Nft. - const nft = await fetchAssetV1(umi, mint) + const nft = await fetchAssetV1(umi, mint); t.like(nft, { publicKey: publicKey(mint), - owner + owner, }); - // Name. if (typeof name === 'string') t.is(nft.name, name); else if (name !== undefined) t.regex(nft.name, name); @@ -372,4 +368,5 @@ export const yesterday = (): DateTime => now() - 3600n * 24n; export const tomorrow = (): DateTime => now() + 3600n * 24n; // TODO move to mpl-core -export const isFrozen = (asset: AssetV1): boolean => asset.freezeDelegate?.frozen || false; +export const isFrozen = (asset: AssetV1): boolean => + asset.freezeDelegate?.frozen || false; diff --git a/clients/js/test/create.test.ts b/clients/js/test/create.test.ts index d15c8f2..e4ccc9d 100644 --- a/clients/js/test/create.test.ts +++ b/clients/js/test/create.test.ts @@ -17,11 +17,7 @@ import { GuardGroup, GuardSet, } from '../src'; -import { - createCollection, - createUmi, - defaultCandyMachineData, -} from './_setup'; +import { createCollection, createUmi, defaultCandyMachineData } from './_setup'; test('it can create a candy machine with an associated candy guard', async (t) => { // Given an existing collection NFT. diff --git a/clients/js/test/createCandyMachineV2.test.ts b/clients/js/test/createCandyMachineV2.test.ts index 28bfd2f..51828dd 100644 --- a/clients/js/test/createCandyMachineV2.test.ts +++ b/clients/js/test/createCandyMachineV2.test.ts @@ -14,11 +14,7 @@ import { Creator, fetchCandyMachine, } from '../src'; -import { - createCollection, - createUmi, - defaultCandyMachineData, -} from './_setup'; +import { createCollection, createUmi, defaultCandyMachineData } from './_setup'; test('it can create a candy machine using config line settings', async (t) => { // Given an existing collection NFT. @@ -230,4 +226,3 @@ test("it can create a candy machine that's bigger than 10Kb", async (t) => { data: { itemsAvailable: 20000n }, }); }); - diff --git a/clients/js/test/createLutForCandyMachine.test.ts b/clients/js/test/createLutForCandyMachine.test.ts index 265d71e..17f0fdb 100644 --- a/clients/js/test/createLutForCandyMachine.test.ts +++ b/clients/js/test/createLutForCandyMachine.test.ts @@ -1,7 +1,5 @@ /* eslint-disable no-promise-executor-return */ -import { - getMplTokenMetadataProgramId, -} from '@metaplex-foundation/mpl-token-metadata'; +import { getMplTokenMetadataProgramId } from '@metaplex-foundation/mpl-token-metadata'; import { getSplAssociatedTokenProgramId, getSplTokenProgramId, @@ -81,7 +79,7 @@ test('it can create a LUT for a candy machine v2', async (t) => { // And we expect the mint builder to be smaller with the LUT. const builderWithLut = builderWithoutLut.setAddressLookupTables([lut]); - + // TODO actually compare real tx size // const transactionSizeDifference = // builderWithoutLut.getTransactionSize(umi) - diff --git a/clients/js/test/defaultGuards/freezeSolPayment.test.ts b/clients/js/test/defaultGuards/freezeSolPayment.test.ts index 8866807..fccf24c 100644 --- a/clients/js/test/defaultGuards/freezeSolPayment.test.ts +++ b/clients/js/test/defaultGuards/freezeSolPayment.test.ts @@ -93,7 +93,13 @@ test('it transfers SOL to an escrow account and freezes the NFT', async (t) => { t.is(isFrozen(asset), true, 'NFT is frozen'); // And cannot be thawed since not all NFTs have been minted. - const promise = thawNft(umi, candyMachine, destination, mint.publicKey, collection); + const promise = thawNft( + umi, + candyMachine, + destination, + mint.publicKey, + collection + ); await t.throwsAsync(promise, { message: /ThawNotEnabled/ }); // And the treasury escrow received SOLs. @@ -379,10 +385,9 @@ test('it can have multiple freeze escrow and reuse the same ones', async (t) => // Then all NFTs except for group D have been frozen. const [tokenA, tokenB, tokenC, tokenD] = await Promise.all( [mintA, mintB, mintC, mintD].map( - ({ publicKey: mint }): Promise => - fetchAssetV1(umi, mint) + ({ publicKey: mint }): Promise => fetchAssetV1(umi, mint) ) - ); + ); t.is(isFrozen(tokenA), true, 'NFT A is frozen'); t.is(isFrozen(tokenB), true, 'NFT B is frozen'); @@ -628,7 +633,13 @@ test('it transfers SOL to an escrow account and locks the Programmable NFT', asy t.is(isFrozen(asset), true); // And cannot be thawed since not all NFTs have been minted. - const promise = thawNft(umi, candyMachine, destination, mint.publicKey, collection); + const promise = thawNft( + umi, + candyMachine, + destination, + mint.publicKey, + collection + ); await t.throwsAsync(promise, { message: /ThawNotEnabled/ }); // And the treasury escrow received SOLs. @@ -817,20 +828,24 @@ const thawNft = async ( destination: PublicKey, asset: PublicKey, collection: PublicKey, - group?: string, -) => { - await route(umi, { - candyMachine, - guard: 'freezeSolPayment', - group: group ? some(group) : none(), - routeArgs: { - path: 'thaw', - asset, - collection, - destination, - }, - }).sendAndConfirm(umi); -}; + group?: string +) => + transactionBuilder() + .add(setComputeUnitLimit(umi, { units: 600_000 })) + .add( + route(umi, { + candyMachine, + guard: 'freezeSolPayment', + group: group ? some(group) : none(), + routeArgs: { + path: 'thaw', + asset, + collection, + destination, + }, + }) + ) + .sendAndConfirm(umi); const unlockFunds = async ( umi: Umi, diff --git a/clients/js/test/defaultGuards/freezeTokenPayment.test.ts b/clients/js/test/defaultGuards/freezeTokenPayment.test.ts index 19516e2..e051551 100644 --- a/clients/js/test/defaultGuards/freezeTokenPayment.test.ts +++ b/clients/js/test/defaultGuards/freezeTokenPayment.test.ts @@ -111,7 +111,14 @@ test('it transfers tokens to an escrow account and freezes the NFT', async (t) = // And cannot be thawed since not all NFTs have been minted. const cm = candyMachine; - const promise = thawNft(umi, cm, tokenMint, destinationAta, mint.publicKey, collection); + const promise = thawNft( + umi, + cm, + tokenMint, + destinationAta, + mint.publicKey, + collection + ); await t.throwsAsync(promise, { message: /ThawNotEnabled/ }); // And the treasury escrow received tokens. @@ -231,7 +238,14 @@ test('it can thaw an NFT once all NFTs are minted', async (t) => { t.is(isFrozen(asset), true); // When we thaw the NFT. - await thawNft(umi, candyMachine, tokenMint, destinationAta, mint.publicKey, collection); + await thawNft( + umi, + candyMachine, + tokenMint, + destinationAta, + mint.publicKey, + collection + ); // Then the NFT is thawed. asset = await fetchAssetV1(umi, mint.publicKey); @@ -272,7 +286,14 @@ test('it can unlock funds once all NFTs have been thawed', async (t) => { destinationAta, collection ); - await thawNft(umi, candyMachine, tokenMint, destinationAta, mint.publicKey, collection); + await thawNft( + umi, + candyMachine, + tokenMint, + destinationAta, + mint.publicKey, + collection + ); // When the authority unlocks the funds. await transactionBuilder() @@ -493,11 +514,10 @@ test('it can have multiple freeze escrow and reuse the same ones', async (t) => // Then all NFTs except for group D have been frozen. const [tokenA, tokenB, tokenC, tokenD] = await Promise.all( [nftA, nftB, nftC, nftD].map( - ({ publicKey: mint }): Promise => - fetchAssetV1(umi, mint) + ({ publicKey: mint }): Promise => fetchAssetV1(umi, mint) ) ); - + t.is(isFrozen(tokenA), true, 'NFT A is frozen'); t.is(isFrozen(tokenB), true, 'NFT B is frozen'); t.is(isFrozen(tokenC), true, 'NFT C is frozen'); @@ -527,15 +547,55 @@ test('it can have multiple freeze escrow and reuse the same ones', async (t) => ]); }; await assertFrozenCounts(2, 1); - await thawNft(umi, cm, mintAB, destinationAtaAB, nftD.publicKey, collection, 'GROUPA'); // Not frozen. + await thawNft( + umi, + cm, + mintAB, + destinationAtaAB, + nftD.publicKey, + collection, + 'GROUPA' + ); // Not frozen. await assertFrozenCounts(2, 1); // No change. - await thawNft(umi, cm, mintAB, destinationAtaAB, nftA.publicKey, collection, 'GROUPA'); + await thawNft( + umi, + cm, + mintAB, + destinationAtaAB, + nftA.publicKey, + collection, + 'GROUPA' + ); await assertFrozenCounts(1, 1); // AB decreased. - await thawNft(umi, cm, mintAB, destinationAtaAB, nftA.publicKey, collection, 'GROUPA'); // Already thawed. + await thawNft( + umi, + cm, + mintAB, + destinationAtaAB, + nftA.publicKey, + collection, + 'GROUPA' + ); // Already thawed. await assertFrozenCounts(1, 1); // No change. - await thawNft(umi, cm, mintAB, destinationAtaAB, nftB.publicKey, collection, 'GROUPB'); + await thawNft( + umi, + cm, + mintAB, + destinationAtaAB, + nftB.publicKey, + collection, + 'GROUPB' + ); await assertFrozenCounts(0, 1); // AB decreased. - await thawNft(umi, cm, mintC, destinationAtaC, nftC.publicKey, collection, 'GROUPC'); + await thawNft( + umi, + cm, + mintC, + destinationAtaC, + nftC.publicKey, + collection, + 'GROUPC' + ); await assertFrozenCounts(0, 0); // C decreased. // And when the authority unlocks the funds of both freeze escrows. @@ -1019,21 +1079,25 @@ const thawNft = async ( destinationAta: PublicKey, asset: PublicKey, collection: PublicKey, - group?: string, -) => { - await route(umi, { - candyMachine, - guard: 'freezeTokenPayment', - group: group ? some(group) : none(), - routeArgs: { - path: 'thaw', - asset, - collection, - mint: publicKey(tokenMint), - destinationAta, - }, - }).sendAndConfirm(umi); -}; + group?: string +) => + transactionBuilder() + .add(setComputeUnitLimit(umi, { units: 600_000 })) + .add( + await route(umi, { + candyMachine, + guard: 'freezeTokenPayment', + group: group ? some(group) : none(), + routeArgs: { + path: 'thaw', + asset, + collection, + mint: publicKey(tokenMint), + destinationAta, + }, + }) + ) + .sendAndConfirm(umi); const unlockFunds = async ( umi: Umi, diff --git a/clients/js/test/mintAssetFromCandyMachine.test.ts b/clients/js/test/mintAssetFromCandyMachine.test.ts index f2a604e..d6f6ca9 100644 --- a/clients/js/test/mintAssetFromCandyMachine.test.ts +++ b/clients/js/test/mintAssetFromCandyMachine.test.ts @@ -7,7 +7,7 @@ import test from 'ava'; import { CandyMachine, fetchCandyMachine, - mintAssetFromCandyMachine + mintAssetFromCandyMachine, } from '../src'; import { assertSuccessfulMint, @@ -58,7 +58,7 @@ test('it cannot mint directly from a candy machine if we are not the mint author const umi = await createUmi(); const mintAuthorityA = generateSigner(umi); const collection = await createCollection(umi, { - updateAuthority: mintAuthorityA.publicKey + updateAuthority: mintAuthorityA.publicKey, }); const candyMachineSigner = await createV2(umi, { authority: mintAuthorityA.publicKey, @@ -97,4 +97,3 @@ test('it cannot mint directly from a candy machine if we are not the mint author const candyMachineAccount = await fetchCandyMachine(umi, candyMachine); t.like(candyMachineAccount, { itemsRedeemed: 0n }); }); - diff --git a/clients/js/test/mintV2.test.ts b/clients/js/test/mintV2.test.ts index 05d14f1..d31329a 100644 --- a/clients/js/test/mintV2.test.ts +++ b/clients/js/test/mintV2.test.ts @@ -1,7 +1,5 @@ /* eslint-disable no-await-in-loop */ -import { - setComputeUnitLimit, -} from '@metaplex-foundation/mpl-toolbox'; +import { setComputeUnitLimit } from '@metaplex-foundation/mpl-toolbox'; import { PublicKey, Umi, @@ -14,11 +12,7 @@ import { import { generateSignerWithSol } from '@metaplex-foundation/umi-bundle-tests'; import test from 'ava'; import { fetchAssetV1 } from '@metaplex-foundation/mpl-core'; -import { - CandyMachine, - fetchCandyMachine, - mintV2, -} from '../src'; +import { CandyMachine, fetchCandyMachine, mintV2 } from '../src'; import { assertSuccessfulMint, createCollection, diff --git a/clients/js/test/route.test.ts b/clients/js/test/route.test.ts index 494ea15..0ff66b4 100644 --- a/clients/js/test/route.test.ts +++ b/clients/js/test/route.test.ts @@ -181,4 +181,3 @@ test('it must not provide a group label if the candy guard does not have groups' // Then we expect a program error. await t.throwsAsync(promise, { message: /GroupNotFound/ }); }); - diff --git a/clients/js/test/setCollectionV2.test.ts b/clients/js/test/setCollectionV2.test.ts index 8dac38c..68f4f82 100644 --- a/clients/js/test/setCollectionV2.test.ts +++ b/clients/js/test/setCollectionV2.test.ts @@ -6,7 +6,10 @@ import { import test from 'ava'; import { setComputeUnitLimit } from '@metaplex-foundation/mpl-toolbox'; -import { PluginType, revokeCollectionPluginAuthorityV1 } from '@metaplex-foundation/mpl-core'; +import { + PluginType, + revokeCollectionPluginAuthorityV1, +} from '@metaplex-foundation/mpl-core'; import { CandyMachine, fetchCandyMachine, @@ -51,7 +54,6 @@ test('it can update the collection of a candy machine v2', async (t) => { }); }); - test('it cannot update the collection of a candy machine when mint is in progress', async (t) => { // Given a Candy Machine associated with Collection A. const umi = await createUmi(); @@ -137,8 +139,7 @@ test.only('it can set the same collection of a candy machine when mint is in pro collection: collectionA.publicKey, authority: collectionUpdateAuthorityA, pluginType: PluginType.UpdateDelegate, - }).sendAndConfirm(umi) - + }).sendAndConfirm(umi); // When we set the same collection. await setCollectionV2(umi, { diff --git a/configs/program-scripts/dump.sh b/configs/program-scripts/dump.sh index 3dc6f63..90d9804 100755 --- a/configs/program-scripts/dump.sh +++ b/configs/program-scripts/dump.sh @@ -1,7 +1,7 @@ #!/bin/bash -EXTERNAL_ID=("metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s" "auth9SigNpDKz4sJJ1DfCTuZrZNSAgh9sFD3rboVmgg" "SysExL2WDyJi9aRZrXorrjHJut3JwHQ7R9bTyctbNNG" "TokExjvjJmhKaRBShsBAsbSvEWMA1AgUNK7ps4SAc2p" "gatem74V238djXdzWnJf94Wo1DcnuGkfijbf3AuBhfs" "TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb") -EXTERNAL_SO=("mpl_token_metadata.so" "mpl_token_auth_rules.so" "mpl_system_extras.so" "mpl_token_extras.so" "civic_gateway.so" "spl_token_2022.so") +EXTERNAL_ID=("CoREENxT6tW1HoK8ypY1SxRMZTcVPm7R94rH4PZNhX7d" "metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s" "auth9SigNpDKz4sJJ1DfCTuZrZNSAgh9sFD3rboVmgg" "SysExL2WDyJi9aRZrXorrjHJut3JwHQ7R9bTyctbNNG" "TokExjvjJmhKaRBShsBAsbSvEWMA1AgUNK7ps4SAc2p" "gatem74V238djXdzWnJf94Wo1DcnuGkfijbf3AuBhfs" "TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb") +EXTERNAL_SO=("mpl_core_program.so" "mpl_token_metadata.so" "mpl_token_auth_rules.so" "mpl_system_extras.so" "mpl_token_extras.so" "civic_gateway.so" "spl_token_2022.so") # output colours RED() { echo $'\e[1;31m'$1$'\e[0m'; } diff --git a/programs/candy-guard/Cargo.lock b/programs/candy-guard/Cargo.lock index 24d01b3..5fe1e14 100644 --- a/programs/candy-guard/Cargo.lock +++ b/programs/candy-guard/Cargo.lock @@ -1241,9 +1241,9 @@ dependencies = [ [[package]] name = "mpl-core" -version = "0.2.0" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d7e1f1a471cd145c7649ff062c553a7370488a8564ac0629eed85c37bb86dea" +checksum = "a12ab13d9c75156048c3e6d57717ec3ece59fdcae195124bf1cec82aef5295fa" dependencies = [ "base64 0.22.0", "borsh 0.10.3", diff --git a/programs/candy-guard/program/Cargo.toml b/programs/candy-guard/program/Cargo.toml index 203733e..06ecfbe 100644 --- a/programs/candy-guard/program/Cargo.toml +++ b/programs/candy-guard/program/Cargo.toml @@ -23,7 +23,7 @@ arrayref = "0.3.6" mpl-candy-guard-derive = { path = "../macro", version = "0.2.0" } mpl-core-candy-machine-core = { path = "../../candy-machine-core/program", version = "0.1.0", features = ["cpi"] } mpl-token-metadata = "3.2.1" -mpl-core = { version = "0.2.0" } +mpl-core = { version = "0.3.0" } solana-program = "~1.16.5" spl-associated-token-account = { version = ">= 1.1.3, < 3.0", features = ["no-entrypoint"] } spl-token = { version = ">= 3.5.0, < 5.0", features = ["no-entrypoint"] } diff --git a/programs/candy-guard/program/src/guards/freeze_sol_payment.rs b/programs/candy-guard/program/src/guards/freeze_sol_payment.rs index 446398f..fd12db4 100644 --- a/programs/candy-guard/program/src/guards/freeze_sol_payment.rs +++ b/programs/candy-guard/program/src/guards/freeze_sol_payment.rs @@ -1,15 +1,14 @@ use super::*; use anchor_lang::AccountsClose; -use mpl_core_candy_machine_core::CandyMachine; use mpl_core::{ accounts::BaseAssetV1, instructions::{ - AddPluginV1CpiBuilder, RevokePluginAuthorityV1CpiBuilder, - UpdatePluginV1CpiBuilder, + AddPluginV1CpiBuilder, RevokePluginAuthorityV1CpiBuilder, UpdatePluginV1CpiBuilder, }, - types::{PluginAuthority, FreezeDelegate, Plugin, PluginType}, + types::{FreezeDelegate, Plugin, PluginAuthority, PluginType}, }; +use mpl_core_candy_machine_core::CandyMachine; use solana_program::{ program::{invoke, invoke_signed}, @@ -500,7 +499,8 @@ pub fn thaw_nft<'info>( &[bump], ]; - let maybe_freeze_plugin = mpl_core::fetch_plugin::(&asset, PluginType::FreezeDelegate); + let maybe_freeze_plugin = + mpl_core::fetch_plugin::(&asset, PluginType::FreezeDelegate); let is_frozen = match maybe_freeze_plugin { Ok((_, freeze_plugin, _)) => freeze_plugin.frozen, diff --git a/programs/candy-guard/program/src/guards/freeze_token_payment.rs b/programs/candy-guard/program/src/guards/freeze_token_payment.rs index b046152..f3993f4 100644 --- a/programs/candy-guard/program/src/guards/freeze_token_payment.rs +++ b/programs/candy-guard/program/src/guards/freeze_token_payment.rs @@ -17,8 +17,8 @@ use crate::{ instructions::Token, state::GuardType, utils::{ - assert_initialized, assert_is_ata, assert_keys_equal, - assert_owned_by, cmp_pubkeys, spl_token_transfer, TokenTransferParams, + assert_initialized, assert_is_ata, assert_keys_equal, assert_owned_by, cmp_pubkeys, + spl_token_transfer, TokenTransferParams, }, }; diff --git a/programs/candy-guard/program/src/guards/mod.rs b/programs/candy-guard/program/src/guards/mod.rs index 3bcafb9..56a1cba 100644 --- a/programs/candy-guard/program/src/guards/mod.rs +++ b/programs/candy-guard/program/src/guards/mod.rs @@ -47,8 +47,8 @@ mod nft_mint_limit; mod nft_payment; mod program_gate; mod redeemed_amount; -mod sol_payment; mod sol_fixed_fee; +mod sol_payment; mod start_date; mod third_party_signer; mod token2022_payment; diff --git a/programs/candy-guard/program/src/guards/nft_burn.rs b/programs/candy-guard/program/src/guards/nft_burn.rs index b049031..9f4e9aa 100644 --- a/programs/candy-guard/program/src/guards/nft_burn.rs +++ b/programs/candy-guard/program/src/guards/nft_burn.rs @@ -103,10 +103,10 @@ impl Condition for NftBurn { let nft_mint_collection_metadata = try_get_account_info(ctx.accounts.remaining, index + 4)?; let spl_token_program = try_get_account_info(ctx.accounts.remaining, index + 5)?; let token_metadata_program = try_get_account_info(ctx.accounts.remaining, index + 6)?; - + let spl_token_info = spl_token_program.to_account_info(); let token_metadata_info = token_metadata_program.to_account_info(); - + if matches!(ctx.accounts.candy_machine.version, AccountVersion::V2) { let metadata: Metadata = Metadata::try_from(nft_metadata)?; let mut burn_cpi = BurnV1CpiBuilder::new(&token_metadata_info); diff --git a/programs/candy-guard/program/src/guards/nft_payment.rs b/programs/candy-guard/program/src/guards/nft_payment.rs index 1c93e3f..d31daf0 100644 --- a/programs/candy-guard/program/src/guards/nft_payment.rs +++ b/programs/candy-guard/program/src/guards/nft_payment.rs @@ -111,7 +111,8 @@ impl Condition for NftPayment { let (owner_token_record_key, _) = TokenRecord::find_pda(nft_mint.key, nft_account.key); assert_keys_equal(&owner_token_record_key, owner_token_record.key)?; - let destination_token_record = try_get_account_info(ctx.accounts.remaining, index + 10)?; + let destination_token_record = + try_get_account_info(ctx.accounts.remaining, index + 10)?; let (destination_token_record_key, _) = TokenRecord::find_pda(nft_mint.key, destination_ata.key); assert_keys_equal(&destination_token_record_key, destination_token_record.key)?; @@ -152,7 +153,7 @@ impl Condition for NftPayment { let spl_ata_program = try_get_account_info(ctx.accounts.remaining, index + 5)?; let spl_token_program = try_get_account_info(ctx.accounts.remaining, index + 6)?; let token_metadata_program = try_get_account_info(ctx.accounts.remaining, index + 7)?; - + let spl_token_info = spl_token_program.to_account_info(); let token_metadata_info = spl_token_program.to_account_info(); diff --git a/programs/candy-guard/program/src/guards/token_payment.rs b/programs/candy-guard/program/src/guards/token_payment.rs index 5ff297e..fcd26ea 100644 --- a/programs/candy-guard/program/src/guards/token_payment.rs +++ b/programs/candy-guard/program/src/guards/token_payment.rs @@ -47,7 +47,8 @@ impl Condition for TokenPayment { let token_account_info = try_get_account_info(ctx.accounts.remaining, token_account_index)?; let destination_ata = try_get_account_info(ctx.accounts.remaining, token_account_index + 1)?; - let spl_token_program = try_get_account_info(ctx.accounts.remaining, token_account_index + 2)?; + let spl_token_program = + try_get_account_info(ctx.accounts.remaining, token_account_index + 2)?; ctx.account_cursor += 3; assert_keys_equal(destination_ata.key, &self.destination_ata)?; diff --git a/programs/candy-guard/program/src/instructions/mint_v2.rs b/programs/candy-guard/program/src/instructions/mint_v2.rs index 6e1f27c..e079afc 100644 --- a/programs/candy-guard/program/src/instructions/mint_v2.rs +++ b/programs/candy-guard/program/src/instructions/mint_v2.rs @@ -10,7 +10,7 @@ use crate::{ utils::cmp_pubkeys, }; -use super::{MintAccounts}; +use super::MintAccounts; pub fn mint_v2<'info>( ctx: Context<'_, '_, '_, 'info, MintV2<'info>>, diff --git a/programs/candy-machine-core/Cargo.lock b/programs/candy-machine-core/Cargo.lock index d5ca33f..8351cf5 100644 --- a/programs/candy-machine-core/Cargo.lock +++ b/programs/candy-machine-core/Cargo.lock @@ -1233,9 +1233,9 @@ dependencies = [ [[package]] name = "mpl-core" -version = "0.2.0" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d7e1f1a471cd145c7649ff062c553a7370488a8564ac0629eed85c37bb86dea" +checksum = "a12ab13d9c75156048c3e6d57717ec3ece59fdcae195124bf1cec82aef5295fa" dependencies = [ "base64 0.22.0", "borsh 0.10.3", diff --git a/programs/candy-machine-core/program/Cargo.toml b/programs/candy-machine-core/program/Cargo.toml index f17e1b4..88db688 100644 --- a/programs/candy-machine-core/program/Cargo.toml +++ b/programs/candy-machine-core/program/Cargo.toml @@ -21,7 +21,7 @@ anchor-lang = "0.28.0" arrayref = "0.3.6" mpl-token-metadata = "3.2.1" mpl-utils = { version = "0.3", default-features = false } -mpl-core = { version = "0.2.0" } +mpl-core = { version = "0.3.0" } solana-program = "~1.16.5" spl-associated-token-account = { version = ">= 1.1.3, < 3.0", features = ["no-entrypoint"] } spl-token = { version = ">= 3.5.0, < 5.0", features = ["no-entrypoint"] } diff --git a/programs/candy-machine-core/program/src/instructions/initialize_v2.rs b/programs/candy-machine-core/program/src/instructions/initialize_v2.rs index 9128804..afeeff6 100644 --- a/programs/candy-machine-core/program/src/instructions/initialize_v2.rs +++ b/programs/candy-machine-core/program/src/instructions/initialize_v2.rs @@ -2,15 +2,14 @@ use anchor_lang::{prelude::*, solana_program::sysvar, Discriminator}; use mpl_token_metadata::MAX_SYMBOL_LENGTH; use crate::{ - approve_asset_collection_delegate, constants::{ - AUTHORITY_SEED, HIDDEN_SECTION, - }, state::{CandyMachine, CandyMachineData}, utils::fixed_length_string, AccountVersion, ApproveAssetDelegateHelperAccounts + approve_asset_collection_delegate, + constants::{AUTHORITY_SEED, HIDDEN_SECTION}, + state::{CandyMachine, CandyMachineData}, + utils::fixed_length_string, + AccountVersion, ApproveAssetDelegateHelperAccounts, }; -pub fn initialize_v2( - ctx: Context, - data: CandyMachineData, -) -> Result<()> { +pub fn initialize_v2(ctx: Context, data: CandyMachineData) -> Result<()> { let candy_machine_account = &mut ctx.accounts.candy_machine; let mut candy_machine = CandyMachine { @@ -110,5 +109,4 @@ pub struct InitializeV2<'info> { /// CHECK: account constraint checked in account trait #[account(address = sysvar::instructions::id())] sysvar_instructions: UncheckedAccount<'info>, - } diff --git a/programs/candy-machine-core/program/src/instructions/mint_asset.rs b/programs/candy-machine-core/program/src/instructions/mint_asset.rs index 683232b..a5e2958 100644 --- a/programs/candy-machine-core/program/src/instructions/mint_asset.rs +++ b/programs/candy-machine-core/program/src/instructions/mint_asset.rs @@ -1,6 +1,12 @@ use anchor_lang::prelude::*; use arrayref::array_ref; -use mpl_core::{self, accounts::BaseCollectionV1, fetch_plugin, instructions::CreateV1CpiBuilder, types::{PluginType, UpdateDelegate}}; +use mpl_core::{ + self, + accounts::BaseCollectionV1, + fetch_plugin, + instructions::CreateV1CpiBuilder, + types::{PluginType, UpdateDelegate}, +}; use solana_program::sysvar; use crate::{ @@ -71,7 +77,10 @@ pub(crate) fn process_mint_asset( return err!(CandyError::IncorrectOwner); } - let (auth, _, _) = fetch_plugin::(&accounts.collection, PluginType::UpdateDelegate)?; + let (auth, _, _) = fetch_plugin::( + &accounts.collection, + PluginType::UpdateDelegate, + )?; assert_plugin_pubkey_authority(&auth, &accounts.authority_pda.key())?; diff --git a/programs/candy-machine-core/program/src/instructions/set_collection_v2.rs b/programs/candy-machine-core/program/src/instructions/set_collection_v2.rs index 2282154..907e2dc 100644 --- a/programs/candy-machine-core/program/src/instructions/set_collection_v2.rs +++ b/programs/candy-machine-core/program/src/instructions/set_collection_v2.rs @@ -1,10 +1,8 @@ use anchor_lang::{prelude::*, solana_program::sysvar}; use crate::{ - approve_asset_collection_delegate, cmp_pubkeys, - constants::AUTHORITY_SEED, - revoke_asset_collection_delegate, - CandyError, CandyMachine, ApproveAssetDelegateHelperAccounts, + approve_asset_collection_delegate, cmp_pubkeys, constants::AUTHORITY_SEED, + revoke_asset_collection_delegate, ApproveAssetDelegateHelperAccounts, CandyError, CandyMachine, RevokeAssetDelegateHelperAccounts, }; @@ -15,10 +13,7 @@ pub fn set_collection_v2(ctx: Context) -> Result<()> { // check whether the new collection mint is the same as the current collection; when they // are the same, we are just using this instruction to update the collection delegate so // we don't enforce the "mint in progress" constraint - if !cmp_pubkeys( - accounts.new_collection.key, - &candy_machine.collection_mint, - ) { + if !cmp_pubkeys(accounts.new_collection.key, &candy_machine.collection_mint) { if candy_machine.items_redeemed > 0 { return err!(CandyError::NoChangingCollectionDuringMint); } else if !cmp_pubkeys(accounts.collection.key, &candy_machine.collection_mint) { diff --git a/programs/candy-machine-core/program/src/lib.rs b/programs/candy-machine-core/program/src/lib.rs index 4ae90b9..d9e5032 100644 --- a/programs/candy-machine-core/program/src/lib.rs +++ b/programs/candy-machine-core/program/src/lib.rs @@ -51,10 +51,7 @@ pub mod candy_machine_core { /// 11. `[]` Instructions sysvar account /// 12. `[optional]` Token Authorization Rules program /// 13. `[optional]` Token authorization rules account - pub fn initialize_v2( - ctx: Context, - data: CandyMachineData, - ) -> Result<()> { + pub fn initialize_v2(ctx: Context, data: CandyMachineData) -> Result<()> { instructions::initialize_v2(ctx, data) } diff --git a/programs/candy-machine-core/program/src/utils.rs b/programs/candy-machine-core/program/src/utils.rs index 599a269..ba8e39f 100644 --- a/programs/candy-machine-core/program/src/utils.rs +++ b/programs/candy-machine-core/program/src/utils.rs @@ -1,12 +1,13 @@ use anchor_lang::prelude::*; use arrayref::array_ref; use mpl_core::{ - fetch_plugin, accounts::BaseCollectionV1, + fetch_plugin, instructions::{ AddCollectionPluginV1CpiBuilder, ApproveCollectionPluginAuthorityV1CpiBuilder, RevokeCollectionPluginAuthorityV1CpiBuilder, - }, types::{Plugin, PluginAuthority, PluginType, UpdateDelegate} + }, + types::{Plugin, PluginAuthority, PluginType, UpdateDelegate}, }; use mpl_token_metadata::{ accounts::Metadata, @@ -306,10 +307,9 @@ pub fn approve_asset_collection_delegate( AddCollectionPluginV1CpiBuilder::new(&accounts.mpl_core_program) .collection(&accounts.collection) .authority(Some(&accounts.collection_update_authority)) - .plugin(Plugin::UpdateDelegate(UpdateDelegate {})) - // .init_authority(PluginAuthority::Pubkey { - // address: accounts.authority_pda.key(), - // }) + .plugin(Plugin::UpdateDelegate(UpdateDelegate { + additional_delegates: vec![], + })) .payer(&accounts.payer) .system_program(&accounts.system_program) .invoke()?;