Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding Engraver support and test. #71

Open
wants to merge 11 commits into
base: main
Choose a base branch
from
Open
3 changes: 2 additions & 1 deletion clients/js/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@metaplex-foundation/mpl-token-metadata",
"version": "3.1.2",
"version": "3.2.0-alpha.0",
"description": "JavaScript client for Token Metadata",
"main": "dist/src/index.js",
"types": "dist/src/index.d.ts",
Expand Down Expand Up @@ -34,6 +34,7 @@
"@ava/typescript": "^3.0.1",
"@metaplex-foundation/umi": "^0.8.2",
"@metaplex-foundation/umi-bundle-tests": "^0.8.2",
"@metaplex-foundation/mpl-engraver": "^0.2.1",
"@solana/web3.js": "^1.73.0",
"@typescript-eslint/eslint-plugin": "^5.0.0",
"@typescript-eslint/parser": "^5.46.1",
Expand Down
24 changes: 24 additions & 0 deletions clients/js/pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

161 changes: 161 additions & 0 deletions clients/js/src/generated/instructions/engrave.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,161 @@
/**
* This code was AUTOGENERATED using the kinobi library.
* Please DO NOT EDIT THIS FILE, instead use visitors
* to add features, then rerun kinobi to update it.
*
* @see https://github.com/metaplex-foundation/kinobi
*/

import {
Context,
Pda,
PublicKey,
Signer,
TransactionBuilder,
publicKey,
transactionBuilder,
} from '@metaplex-foundation/umi';
import {
Serializer,
mapSerializer,
struct,
u8,
} from '@metaplex-foundation/umi/serializers';
import { findMasterEditionPda, findMetadataPda } from '../accounts';
import {
ResolvedAccount,
ResolvedAccountsWithIndices,
expectPublicKey,
getAccountMetasAndSigners,
} from '../shared';

// Accounts.
export type EngraveInstructionAccounts = {
/** Metadata account */
metadata?: PublicKey | Pda;
/** Edition account */
edition?: PublicKey | Pda;
/** Mint of token asset */
mint: PublicKey | Pda;
/** Update authority of the metadata account */
updateAuthority?: Signer;
/** MPL Engraver program */
engraverProgram: PublicKey | Pda;
/** System program */
systemProgram?: PublicKey | Pda;
/** Instructions sysvar account */
sysvarInstructions?: PublicKey | Pda;
};

// Data.
export type EngraveInstructionData = { discriminator: number };

export type EngraveInstructionDataArgs = {};

export function getEngraveInstructionDataSerializer(): Serializer<
EngraveInstructionDataArgs,
EngraveInstructionData
> {
return mapSerializer<EngraveInstructionDataArgs, any, EngraveInstructionData>(
struct<EngraveInstructionData>([['discriminator', u8()]], {
description: 'EngraveInstructionData',
}),
(value) => ({ ...value, discriminator: 56 })
) as Serializer<EngraveInstructionDataArgs, EngraveInstructionData>;
}

// Instruction.
export function engrave(
context: Pick<Context, 'eddsa' | 'identity' | 'programs'>,
input: EngraveInstructionAccounts
): TransactionBuilder {
// Program ID.
const programId = context.programs.getPublicKey(
'mplTokenMetadata',
'metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s'
);

// Accounts.
const resolvedAccounts = {
metadata: {
index: 0,
isWritable: true as boolean,
value: input.metadata ?? null,
},
edition: {
index: 1,
isWritable: true as boolean,
value: input.edition ?? null,
},
mint: { index: 2, isWritable: false as boolean, value: input.mint ?? null },
updateAuthority: {
index: 3,
isWritable: true as boolean,
value: input.updateAuthority ?? null,
},
engraverProgram: {
index: 4,
isWritable: false as boolean,
value: input.engraverProgram ?? null,
},
systemProgram: {
index: 5,
isWritable: false as boolean,
value: input.systemProgram ?? null,
},
sysvarInstructions: {
index: 6,
isWritable: false as boolean,
value: input.sysvarInstructions ?? null,
},
} satisfies ResolvedAccountsWithIndices;

// Default values.
if (!resolvedAccounts.metadata.value) {
resolvedAccounts.metadata.value = findMetadataPda(context, {
mint: expectPublicKey(resolvedAccounts.mint.value),
});
}
if (!resolvedAccounts.edition.value) {
resolvedAccounts.edition.value = findMasterEditionPda(context, {
mint: expectPublicKey(resolvedAccounts.mint.value),
});
}
if (!resolvedAccounts.updateAuthority.value) {
resolvedAccounts.updateAuthority.value = context.identity;
}
if (!resolvedAccounts.systemProgram.value) {
resolvedAccounts.systemProgram.value = context.programs.getPublicKey(
'splSystem',
'11111111111111111111111111111111'
);
resolvedAccounts.systemProgram.isWritable = false;
}
if (!resolvedAccounts.sysvarInstructions.value) {
resolvedAccounts.sysvarInstructions.value = publicKey(
'Sysvar1nstructions1111111111111111111111111'
);
}

// Accounts in order.
const orderedAccounts: ResolvedAccount[] = Object.values(
resolvedAccounts
).sort((a, b) => a.index - b.index);

// Keys and Signers.
const [keys, signers] = getAccountMetasAndSigners(
orderedAccounts,
'programId',
programId
);

// Data.
const data = getEngraveInstructionDataSerializer().serialize({});

// Bytes Created On Chain.
const bytesCreatedOnChain = 0;

return transactionBuilder([
{ instruction: { keys, programId, data }, signers, bytesCreatedOnChain },
]);
}
1 change: 1 addition & 0 deletions clients/js/src/generated/instructions/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ export * from './delegateStandardV1';
export * from './delegateTransferV1';
export * from './delegateUtilityV1';
export * from './deprecatedMintNewEditionFromMasterEditionViaPrintingToken';
export * from './engrave';
export * from './freezeDelegatedAccount';
export * from './lockV1';
export * from './migrate';
Expand Down
92 changes: 92 additions & 0 deletions clients/js/test/engrave.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
import {
fetchMint,
Mint,
setComputeUnitLimit,
} from '@metaplex-foundation/mpl-toolbox';
import {
generateSigner,
percentAmount,
publicKey,
} from '@metaplex-foundation/umi';
import test from 'ava';
import { MPL_ENGRAVER_PROGRAM_ID } from '@metaplex-foundation/mpl-engraver';
import {
createV1,
engrave,
fetchDigitalAssetWithTokenByMint,
mintV1,
TokenStandard,
} from '../src';
import { createUmi } from './_setup';

test('it can mint and engrave a NonFungible', async (t) => {
// Given a created NonFungible.
const umi = await createUmi();
const mint = generateSigner(umi);
await createV1(umi, {
mint,
name: 'My Engraved NFT',
uri: 'https://example.com/my-nft.json',
sellerFeeBasisPoints: percentAmount(5.5),
}).sendAndConfirm(umi);

// When we mint one token.
await mintV1(umi, {
mint: mint.publicKey,
amount: 1,
tokenStandard: TokenStandard.NonFungible,
}).sendAndConfirm(umi);

// Then a token was minted to the associated token account.
const mintAccount = await fetchMint(umi, mint.publicKey);
t.like(mintAccount, <Mint>{ publicKey: publicKey(mint), supply: 1n });

const nft = await fetchDigitalAssetWithTokenByMint(umi, mint.publicKey);

// And when we engrave the token.
await engrave(umi, {
metadata: nft.metadata.publicKey,
edition: nft.edition?.publicKey,
mint: mint.publicKey,
updateAuthority: umi.identity,
engraverProgram: MPL_ENGRAVER_PROGRAM_ID,
})
.prepend(setComputeUnitLimit(umi, { units: 1000000 }))
.sendAndConfirm(umi, { send: { skipPreflight: true } });
});

test('it can mint and engrave a ProgrammableNonFungible', async (t) => {
// Given a created NonFungible.
const umi = await createUmi();
const mint = generateSigner(umi);
await createV1(umi, {
mint,
name: 'My Engraved pNFT',
uri: 'https://example.com/my-nft.json',
sellerFeeBasisPoints: percentAmount(5.5),
}).sendAndConfirm(umi);

// When we mint one token.
await mintV1(umi, {
mint: mint.publicKey,
amount: 1,
tokenStandard: TokenStandard.ProgrammableNonFungible,
}).sendAndConfirm(umi);

// Then a token was minted to the associated token account.
const mintAccount = await fetchMint(umi, mint.publicKey);
t.like(mintAccount, <Mint>{ publicKey: publicKey(mint), supply: 1n });

const nft = await fetchDigitalAssetWithTokenByMint(umi, mint.publicKey);

// And when we engrave the token.
await engrave(umi, {
metadata: nft.metadata.publicKey,
edition: nft.edition?.publicKey,
mint: mint.publicKey,
updateAuthority: umi.identity,
engraverProgram: MPL_ENGRAVER_PROGRAM_ID,
})
.prepend(setComputeUnitLimit(umi, { units: 1000000 }))
.sendAndConfirm(umi, { send: { skipPreflight: true } });
});
Loading
Loading