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

MET-96: Add Inscription support for Token22 #11

Merged
merged 3 commits into from
Mar 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion clients/js/test/_setup.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/* eslint-disable import/no-extraneous-dependencies */
import { createUmi as basecreateUmi } from '@metaplex-foundation/umi-bundle-tests';
import { Umi } from '@metaplex-foundation/umi';
import { PublicKey, Umi, publicKey } from '@metaplex-foundation/umi';
import pMap from 'p-map';
import {
mplInscription,
Expand All @@ -9,6 +9,10 @@ import {
safeFetchInscriptionShard,
} from '../src';

export const SPL_TOKEN_2022_PROGRAM_ID: PublicKey = publicKey(
'TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb'
);

export const createUmi = async () => {
const umi = (await basecreateUmi()).use(mplInscription());

Expand Down
105 changes: 97 additions & 8 deletions clients/js/test/initializeFromMint.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import {
mintV1,
mplTokenMetadata,
} from '@metaplex-foundation/mpl-token-metadata';
import { publicKey as publicKeySerializer } from '@metaplex-foundation/umi/serializers';
import { SPL_ASSOCIATED_TOKEN_PROGRAM_ID } from '@metaplex-foundation/mpl-toolbox';
import {
AssociatedInscription,
DataType,
Expand All @@ -19,7 +21,7 @@ import {
findMintInscriptionPda,
initializeFromMint,
} from '../src';
import { createUmi } from './_setup';
import { SPL_TOKEN_2022_PROGRAM_ID, createUmi } from './_setup';

test('it can initialize a Mint Inscription account', async (t) => {
// Given a Umi instance and a new signer.
Expand All @@ -40,14 +42,101 @@ test('it can initialize a Mint Inscription account', async (t) => {
tokenStandard: TokenStandard.NonFungible,
}).sendAndConfirm(umi);

const inscriptionAccount = await findMintInscriptionPda(umi, {
const inscriptionAccount = findMintInscriptionPda(umi, {
mint: mint.publicKey,
});
const inscriptionMetadataAccount = await findInscriptionMetadataPda(umi, {
const inscriptionMetadataAccount = findInscriptionMetadataPda(umi, {
inscriptionAccount: inscriptionAccount[0],
});

const inscriptionShardAccount = await findInscriptionShardPda(umi, {
const inscriptionShardAccount = findInscriptionShardPda(umi, {
shardNumber: 0,
});
const shardDataBefore = await fetchInscriptionShard(
umi,
inscriptionShardAccount
);

// const asset = await fetchDigitalAsset(umi, mint.publicKey);

// When we create a new account.
await initializeFromMint(umi, {
mintAccount: mint.publicKey,
inscriptionShardAccount,
}).sendAndConfirm(umi);

// Then an account was created with the correct data.
const inscriptionMetadata = await fetchInscriptionMetadata(
umi,
inscriptionMetadataAccount
);

const shardDataAfter = await fetchInscriptionShard(
umi,
inscriptionShardAccount
);
t.is(shardDataBefore.count + BigInt(1), shardDataAfter.count);

t.like(inscriptionMetadata, <InscriptionMetadata>{
key: Key.MintInscriptionMetadataAccount,
inscriptionAccount: inscriptionAccount[0],
bump: inscriptionMetadataAccount[1],
dataType: DataType.Uninitialized,
inscriptionRank:
shardDataBefore.count * BigInt(32) + BigInt(shardDataBefore.shardNumber),
updateAuthorities: [umi.identity.publicKey],
associatedInscriptions: [] as AssociatedInscription[],
mint: some(mint.publicKey),
});

const jsonData = await umi.rpc.getAccount(inscriptionAccount[0]);
if (jsonData.exists) {
t.like(jsonData, {
owner: MPL_INSCRIPTION_PROGRAM_ID,
data: Uint8Array.from([]),
});
}
});

test('it can initialize a Mint Inscription account from SPL Token 2022', async (t) => {
// Given a Umi instance and a new signer.
const umi = await createUmi();
umi.use(mplTokenMetadata());

const mint = generateSigner(umi);
await createV1(umi, {
mint,
name: 'My Programmable NFT',
uri: 'https://arweave.net/LcjCf-NDr5bhCJ0YMKGlc8m8qT_J6TDWtIuW8lbu0-A',
sellerFeeBasisPoints: percentAmount(5.5),
splTokenProgram: SPL_TOKEN_2022_PROGRAM_ID,
tokenStandard: TokenStandard.NonFungible,
}).sendAndConfirm(umi);

// And we derive the associated token account from SPL Token 2022.
const [token] = umi.eddsa.findPda(SPL_ASSOCIATED_TOKEN_PROGRAM_ID, [
publicKeySerializer().serialize(umi.identity.publicKey),
publicKeySerializer().serialize(SPL_TOKEN_2022_PROGRAM_ID),
publicKeySerializer().serialize(mint.publicKey),
]);

// When we mint one token.
await mintV1(umi, {
mint: mint.publicKey,
token,
tokenOwner: umi.identity.publicKey,
splTokenProgram: SPL_TOKEN_2022_PROGRAM_ID,
tokenStandard: TokenStandard.NonFungible,
}).sendAndConfirm(umi);

const inscriptionAccount = findMintInscriptionPda(umi, {
mint: mint.publicKey,
});
const inscriptionMetadataAccount = findInscriptionMetadataPda(umi, {
inscriptionAccount: inscriptionAccount[0],
});

const inscriptionShardAccount = findInscriptionShardPda(umi, {
shardNumber: 0,
});
const shardDataBefore = await fetchInscriptionShard(
Expand Down Expand Up @@ -116,7 +205,7 @@ test('it cannot initialize a Mint Inscription account if it is not the update au
tokenStandard: TokenStandard.NonFungible,
}).sendAndConfirm(umi);

const inscriptionShardAccount = await findInscriptionShardPda(umi, {
const inscriptionShardAccount = findInscriptionShardPda(umi, {
shardNumber: 0,
});
const shardDataBefore = await fetchInscriptionShard(
Expand Down Expand Up @@ -160,7 +249,7 @@ test('it can initialize a Mint Inscription account with separate authority', asy
creators: [{ address: authority.publicKey, verified: false, share: 100 }],
}).sendAndConfirm(umi);

const inscriptionShardAccount = await findInscriptionShardPda(umi, {
const inscriptionShardAccount = findInscriptionShardPda(umi, {
shardNumber: 0,
});
const shardDataBefore = await fetchInscriptionShard(
Expand All @@ -174,10 +263,10 @@ test('it can initialize a Mint Inscription account with separate authority', asy
authority,
}).sendAndConfirm(umi);

const inscriptionAccount = await findMintInscriptionPda(umi, {
const inscriptionAccount = findMintInscriptionPda(umi, {
mint: mint.publicKey,
});
const inscriptionMetadataAccount = await findInscriptionMetadataPda(umi, {
const inscriptionMetadataAccount = findInscriptionMetadataPda(umi, {
inscriptionAccount: inscriptionAccount[0],
});

Expand Down
89 changes: 83 additions & 6 deletions clients/js/test/setMint.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ import {
mintV1,
mplTokenMetadata,
} from '@metaplex-foundation/mpl-token-metadata';
import { SPL_ASSOCIATED_TOKEN_PROGRAM_ID } from '@metaplex-foundation/mpl-toolbox';
import { publicKey as publicKeySerializer } from '@metaplex-foundation/umi/serializers';
import {
AssociatedInscription,
DataType,
Expand All @@ -23,7 +25,7 @@ import {
initializeFromMint,
setMint,
} from '../src';
import { createUmi } from './_setup';
import { createUmi, SPL_TOKEN_2022_PROGRAM_ID } from './_setup';

test('it can set the mint on a Mint Inscription account', async (t) => {
// Given a Umi instance and a new signer.
Expand All @@ -44,10 +46,10 @@ test('it can set the mint on a Mint Inscription account', async (t) => {
tokenStandard: TokenStandard.NonFungible,
}).sendAndConfirm(umi);

const inscriptionAccount = await findMintInscriptionPda(umi, {
const inscriptionAccount = findMintInscriptionPda(umi, {
mint: mint.publicKey,
});
const inscriptionMetadataAccount = await findInscriptionMetadataPda(umi, {
const inscriptionMetadataAccount = findInscriptionMetadataPda(umi, {
inscriptionAccount: inscriptionAccount[0],
});

Expand Down Expand Up @@ -110,7 +112,7 @@ test('it cannot set the mint on an Inscription account that is not derived from
// We are creating an inscription account that is not derived from a mint and is not a PDA.
const inscriptionAccount = generateSigner(umi);

const inscriptionMetadataAccount = await findInscriptionMetadataPda(umi, {
const inscriptionMetadataAccount = findInscriptionMetadataPda(umi, {
inscriptionAccount: inscriptionAccount.publicKey,
});

Expand Down Expand Up @@ -171,10 +173,10 @@ test('it cannot set the wrong mint on a Mint Inscription account', async (t) =>
tokenStandard: TokenStandard.NonFungible,
}).sendAndConfirm(umi);

const inscriptionAccount = await findMintInscriptionPda(umi, {
const inscriptionAccount = findMintInscriptionPda(umi, {
mint: mint.publicKey,
});
const inscriptionMetadataAccount = await findInscriptionMetadataPda(umi, {
const inscriptionMetadataAccount = findInscriptionMetadataPda(umi, {
inscriptionAccount: inscriptionAccount[0],
});

Expand All @@ -201,3 +203,78 @@ test('it cannot set the wrong mint on a Mint Inscription account', async (t) =>
// And it fails because the derivation from the wrong mint is invalid.
await t.throwsAsync(promise, { name: 'DerivedKeyInvalid' });
});

test('it can mint from SPL Token 2022', async (t) => {
// Given a created NonFungible.
const umi = await createUmi();
umi.use(mplTokenMetadata());
const mint = generateSigner(umi);

await createV1(umi, {
mint,
name: 'My Programmable NFT',
uri: 'https://arweave.net/LcjCf-NDr5bhCJ0YMKGlc8m8qT_J6TDWtIuW8lbu0-A',
sellerFeeBasisPoints: percentAmount(5.5),
splTokenProgram: SPL_TOKEN_2022_PROGRAM_ID,
tokenStandard: TokenStandard.NonFungible,
}).sendAndConfirm(umi);

// And we derive the associated token account from SPL Token 2022.
const [token] = umi.eddsa.findPda(SPL_ASSOCIATED_TOKEN_PROGRAM_ID, [
publicKeySerializer().serialize(umi.identity.publicKey),
publicKeySerializer().serialize(SPL_TOKEN_2022_PROGRAM_ID),
publicKeySerializer().serialize(mint.publicKey),
]);

// When we mint one token.
await mintV1(umi, {
mint: mint.publicKey,
token,
tokenOwner: umi.identity.publicKey,
splTokenProgram: SPL_TOKEN_2022_PROGRAM_ID,
tokenStandard: TokenStandard.NonFungible,
}).sendAndConfirm(umi);

const inscriptionAccount = findMintInscriptionPda(umi, {
mint: mint.publicKey,
});
const inscriptionMetadataAccount = findInscriptionMetadataPda(umi, {
inscriptionAccount: inscriptionAccount[0],
});

let builder = new TransactionBuilder();

// When we create a new account.
builder = builder.append(
initializeFromMint(umi, {
mintAccount: mint.publicKey,
})
);

// Set the mint on the account.
builder = builder.append(
setMint(umi, {
mintInscriptionAccount: inscriptionAccount,
inscriptionMetadataAccount,
mintAccount: mint.publicKey,
})
);

await builder.sendAndConfirm(umi);

// Then an account was created with the correct data.
const inscriptionMetadata = await fetchInscriptionMetadata(
umi,
inscriptionMetadataAccount
);

t.like(inscriptionMetadata, <InscriptionMetadata>{
key: Key.MintInscriptionMetadataAccount,
inscriptionAccount: inscriptionAccount[0],
bump: inscriptionMetadataAccount[1],
dataType: DataType.Uninitialized,
updateAuthorities: [umi.identity.publicKey],
associatedInscriptions: [] as AssociatedInscription[],
mint: some(mint.publicKey),
});
});
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
"programs:debug": "./configs/scripts/program/test.sh",
"programs:clean": "./configs/scripts/program/clean.sh",
"clients:rust:test": "./configs/scripts/client/test-rust.sh",
"clients:js:test": "./configs/sripts/client/test-js.sh",
"clients:js:test": "./configs/scripts/client/test-js.sh",
"generate": "pnpm generate:idls && pnpm generate:clients",
"generate:idls": "node ./configs/shank.cjs",
"generate:clients": "node ./configs/kinobi.cjs",
Expand Down
Loading
Loading