Skip to content

Commit

Permalink
update tests to verify whether LeafSchema is returned for non CPI calls
Browse files Browse the repository at this point in the history
  • Loading branch information
kstepanovdev committed Feb 15, 2024
1 parent dec5dae commit 9e9bcf2
Show file tree
Hide file tree
Showing 4 changed files with 173 additions and 4 deletions.
21 changes: 21 additions & 0 deletions clients/js/test/_setup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {
Pda,
PublicKey,
SolAmount,
TransactionWithMeta,
generateSigner,
none,
publicKey,
Expand Down Expand Up @@ -101,3 +102,23 @@ export const mint = async (
),
};
};

// TransactionWithMeta doesn't have ReturnData field that is discribed in
// https://solana.com/docs/rpc/http/gettransaction#result
// so ugly log parsing is provided
export function getReturnLog(transaction: TransactionWithMeta | null): null | [string, string, Buffer] {
if (transaction === null) {
return null
}
const prefix = "Program return: ";
let log = transaction.meta.logs.find((logs) =>
logs.startsWith(prefix)
);
if (log === undefined) {
return null
};
log = log.slice(prefix.length);
const [key, data] = log.split(" ", 2);
const buffer = Buffer.from(data, "base64");
return [key, data, buffer];
};
56 changes: 55 additions & 1 deletion clients/js/test/mintToCollectionV1.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,12 @@ import test from 'ava';
import {
MetadataArgsArgs,
fetchMerkleTree,
findLeafAssetIdPda,
getLeafSchemaSerializer,
hashLeaf,
mintToCollectionV1,
} from '../src';
import { createTree, createUmi } from './_setup';
import { createTree, createUmi, getReturnLog } from './_setup';

test('it can mint an NFT from a collection (collection unverified in passed-in metadata)', async (t) => {
// Given an empty Bubblegum tree.
Expand Down Expand Up @@ -279,3 +281,55 @@ test('it can mint an NFT from a collection using a legacy collection delegate',
});
t.is(merkleTreeAccount.tree.rightMostPath.leaf, publicKey(leaf));
});

test('it can mint an NFT from a collection (collection verified in passed-in metadata) && can get created LeafSchema from returnedValue ', async (t) => {
// Given an empty Bubblegum tree.
const umi = await createUmi();
const merkleTree = await createTree(umi);
const leafOwner = generateSigner(umi).publicKey;

// And a Collection NFT.
const collectionMint = generateSigner(umi);
await createNft(umi, {
mint: collectionMint,
name: 'My Collection',
uri: 'https://example.com/my-collection.json',
sellerFeeBasisPoints: percentAmount(5.5), // 5.5%
isCollection: true,
}).sendAndConfirm(umi);

// When we mint a new NFT from the tree using the following metadata, with collection verified.
const metadata: MetadataArgsArgs = {
name: 'My NFT',
uri: 'https://example.com/my-nft.json',
sellerFeeBasisPoints: 550, // 5.5%
collection: {
key: collectionMint.publicKey,
verified: true,
},
creators: [],
};

const transactionResult = await mintToCollectionV1(umi, {
leafOwner,
merkleTree,
metadata,
collectionMint: collectionMint.publicKey,
}).sendAndConfirm(umi);;
const transaction = await umi.rpc.getTransaction(transactionResult.signature);

const unparsedLogs = getReturnLog(transaction);
if (unparsedLogs != null) {
const buffer = unparsedLogs[2];
const leaf = getLeafSchemaSerializer().deserialize(
buffer
)[0];
const assetId = findLeafAssetIdPda(umi, { merkleTree, leafIndex: 0 });

t.is(leafOwner, leaf.owner);
t.is(Number(leaf.nonce), 0);
t.is(leaf.id, assetId[0]);
} else {
t.fail()
}
});
39 changes: 37 additions & 2 deletions clients/js/test/mintV1.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ import {
publicKey,
} from '@metaplex-foundation/umi';
import test from 'ava';
import { MetadataArgsArgs, fetchMerkleTree, hashLeaf, mintV1 } from '../src';
import { createTree, createUmi } from './_setup';
import { MetadataArgsArgs, fetchMerkleTree, findLeafAssetIdPda, getLeafSchemaSerializer, hashLeaf, mintV1 } from '../src';
import { createTree, createUmi, getReturnLog } from './_setup';

test('it can mint an NFT from a Bubblegum tree', async (t) => {
// Given an empty Bubblegum tree.
Expand Down Expand Up @@ -46,3 +46,38 @@ test('it can mint an NFT from a Bubblegum tree', async (t) => {
});
t.is(merkleTreeAccount.tree.rightMostPath.leaf, publicKey(leaf));
});

test('it can get LeafScheme from mint without CPI', async (t) => {
// Given an empty Bubblegum tree.
const umi = await createUmi();


const merkleTree = await createTree(umi);
const leafOwner = generateSigner(umi).publicKey;

// When we mint a new NFT from the tree using the following metadata.
const metadata: MetadataArgsArgs = {
name: 'My NFT',
uri: 'https://example.com/my-nft.json',
sellerFeeBasisPoints: 500, // 5%
collection: none(),
creators: [],
};
const transactionResult = await mintV1(umi, { leafOwner, merkleTree, metadata }).sendAndConfirm(umi);
const transaction = await umi.rpc.getTransaction(transactionResult.signature);

const unparsedLogs = getReturnLog(transaction);
if (unparsedLogs != null) {
const buffer = unparsedLogs[2];
const leaf = getLeafSchemaSerializer().deserialize(
buffer
)[0];
const assetId = findLeafAssetIdPda(umi, { merkleTree, leafIndex: 0 });

t.is(leafOwner, leaf.owner);
t.is(Number(leaf.nonce), 0);
t.is(leaf.id, assetId[0]);
} else {
t.fail()
}
});
61 changes: 60 additions & 1 deletion clients/rust/tests/mint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,11 @@
pub mod setup;
pub use setup::*;

use mpl_bubblegum::types::{Creator, MetadataArgs, TokenProgramVersion, TokenStandard};
use mpl_bubblegum::{
hash::{hash_creators, hash_metadata},
types::{Creator, MetadataArgs, TokenProgramVersion, TokenStandard},
utils::get_asset_id,
};
use solana_program_test::tokio;
use solana_sdk::signature::Keypair;
use solana_sdk::signature::Signer;
Expand Down Expand Up @@ -117,4 +121,59 @@ mod mint {

tree_manager.assert_root(&mut context).await;
}

#[tokio::test]
async fn recieve_leaf_schema() {
let mut program_test = create_program_test();
program_test.set_compute_max_units(400_000);
let mut context = program_test.start_with_context().await;

// Given a new merkle tree.

let mut tree_manager = TreeManager::<5, 8>::default();
tree_manager.create(&mut context).await.unwrap();

assert!(find_account(&mut context, &tree_manager.tree.pubkey())
.await
.is_some());

// When minting a new cNFT.

let owner = Keypair::new();

let metadata = MetadataArgs {
name: String::from("cNFT"),
uri: String::from("https://c.nft"),
symbol: String::from("cNFT"),
creators: vec![Creator {
address: context.payer.pubkey(),
share: 100,
verified: false,
}],
edition_nonce: None,
is_mutable: true,
primary_sale_happened: true,
seller_fee_basis_points: 500,
token_program_version: TokenProgramVersion::Original,
token_standard: Some(TokenStandard::NonFungible),
collection: None,
uses: None,
};

let leaf = tree_manager
.mint(&mut context, owner.pubkey(), metadata.clone())
.await
.unwrap();

// Then LeafSchema returned and valid.
assert_eq!(
leaf.id(),
get_asset_id(&tree_manager.tree.pubkey(), tree_manager.minted() - 1)
);
assert_eq!(leaf.owner(), owner.pubkey());
assert_eq!(leaf.delegate(), owner.pubkey());
assert_eq!(leaf.nonce(), tree_manager.minted() - 1);
assert_eq!(leaf.data_hash(), hash_metadata(&metadata).unwrap());
assert_eq!(leaf.creator_hash(), hash_creators(&metadata.creators));
}
}

0 comments on commit 9e9bcf2

Please sign in to comment.