@mirrorworld/library.assetminting.new
Version:
asset minting SDK
530 lines (441 loc) • 23.3 kB
text/typescript
import {AnchorProvider, BN, Program, Wallet} from '@project-serum/anchor';
import web3, {
Connection,
Keypair,
PublicKey,
SystemProgram,
SYSVAR_RENT_PUBKEY,
Transaction,
TransactionInstruction
} from '@solana/web3.js';
import {ASSOCIATED_TOKEN_PROGRAM_ID, getAssociatedTokenAddress, TOKEN_PROGRAM_ID} from '@solana/spl-token';
import {AssetMinting, IDL} from './types/asset_minting';
import * as base58 from "bs58";
import * as nacl from "tweetnacl";
import {createSignMetadataInstruction, PROGRAM_ID as METADATA_PROGRAM_ID} from "@metaplex-foundation/mpl-token-metadata"
import {
ASSET_EVENT_NAME,
AssetEvent,
COLLECTION_EVENT_NAME,
CollectionEvent,
MINT_EVENT_NAME,
MintEvent,
SUB_COLLECTION_EVENT_NAME,
SubCollectionEvent
} from './events-types'
const CONFIG_ACCOUNT_PREFIX = "CONFIG";
const NAME = "MirrorWorld";
export class AssetMintingLib {
program: Program<AssetMinting>;
connection: Connection;
constructor(programId: PublicKey, connection: Connection, wallet: Wallet) {
this.connection = connection;
const provider = new AnchorProvider(connection, wallet, AnchorProvider.defaultOptions());
this.program = new Program(IDL, programId, provider);
}
/**
* Sign the transaction and add the signature in the transaction.
* @param tx Transaction object which needs to sign.
* @param secretKey Transaction signer secret key (secret key in base58 string).
*/
signTransaction(tx: Transaction, secretKey: string): Transaction {
const keypair: Keypair = Keypair.fromSecretKey(base58.decode(secretKey));
const signature = nacl.sign.detached(tx.serializeMessage(), keypair.secretKey);
tx.addSignature(keypair.publicKey, Buffer.from(signature));
return tx;
}
/**
* Add signature in the transaction.
* @param tx Transaction object where signature needs to add.
* @param signerAddress Signer public key from which secret key transaction is signed.
* @param signature Signed transaction message signature.
*/
addSignatureInTransaction(tx: Transaction, signerAddress: PublicKey, signature: Buffer): Transaction {
tx.addSignature(signerAddress, signature);
return tx;
}
/**
* Add signature in the transaction.
* @param tx Transaction object where signature needs to add.
* @param feePayer public key of the address which going to pay the fee.
*/
async addFeePayerAndRecentBlockHashInTransaction(tx: Transaction, feePayer: PublicKey): Promise<Transaction> {
tx.feePayer = feePayer;
tx.recentBlockhash = (await this.connection.getLatestBlockhash()).blockhash;
return tx;
}
/**
* Is pda address initialize.
*/
async isPdaAddressInitialize(pdaAddress: PublicKey): Promise<boolean> {
const pdaAccountInfo = await this.connection.getAccountInfo(pdaAddress);
return pdaAccountInfo != null;
}
/**
* get the config account pda and bump.
* @param name seed for the config account.
*/
async getConfigAccountPdaAndBump(name: String = NAME): Promise<[PublicKey, number]> {
return PublicKey.findProgramAddressSync([Buffer.from(name), Buffer.from(CONFIG_ACCOUNT_PREFIX)],
this.program.programId);
}
/**
* get the mint account pda and bump.
* @param uuid seed for the mint account.
*/
async getMintAccountPdaAndBump(uuid: String): Promise<[PublicKey, number]> {
return PublicKey.findProgramAddressSync([Buffer.from(uuid)],
this.program.programId);
}
/**
* Get metadata account pda.
* @param mintAccountPda token mint account
* @param mplProgramId metadata program id
*/
async getMetadataAccountPda(mintAccountPda: PublicKey, mplProgramId: PublicKey = METADATA_PROGRAM_ID): Promise<[PublicKey, number]> {
return PublicKey.findProgramAddressSync(
[
Buffer.from('metadata'),
mplProgramId.toBuffer(),
mintAccountPda.toBuffer(),
],
mplProgramId
);
}
/**
* Get master edition account pda.
* @param mintAccountPda token mint account
* @param mplProgramId metadata program id
*/
async getMasterEditionAccountPda(mintAccountPda: PublicKey, mplProgramId: PublicKey = METADATA_PROGRAM_ID): Promise<[PublicKey, number]> {
return PublicKey.findProgramAddressSync(
[
Buffer.from('metadata'),
mplProgramId.toBuffer(),
mintAccountPda.toBuffer(),
Buffer.from('edition')
],
mplProgramId
);
}
/**
* Get config account pda data
* @param configAccountPda pda address for data
*/
async getConfigAccountData(configAccountPda: PublicKey): Promise<any> {
return await this.program.account.configAccount.fetch(configAccountPda);
}
/**
* Get current block time
*/
async getCurrentBlockTime(): Promise<BN> {
return new BN(await this.connection.getBlockTime(
await this.connection.getSlot(undefined)
));
}
/**
* Create initialize config transaction
* @param payer transaction fee payer public key
* @param signingAuthority signing authority public key
* @param configName config account seed for pda
* @param systemProgram system program id
* @param rent rent program id
*/
async createInitializeConfigTransaction(payer: PublicKey, signingAuthority: PublicKey, configName: string = NAME,
systemProgram: PublicKey = SystemProgram.programId, rent: PublicKey = SYSVAR_RENT_PUBKEY): Promise<Transaction> {
const [configAccount] = await this.getConfigAccountPdaAndBump(configName);
let tx: Transaction = await this.program.methods.initializeConfig(configName)
.accounts({
payer: payer,
signingAuthority: signingAuthority,
config: configAccount,
systemProgram: systemProgram,
rent: rent
})
.transaction();
return tx;
}
/**
* Create mint token transaction
* @param assetUuid seed for the mint account
* @param payer transaction fee payer public key
* @param signingAuthority signing authority public key
* @param mintAuthority token mint authority
* @param configName config account seed for pda
* @param tokenProgram token program id
* @param associatedTokenProgram associated token program id
* @param systemProgram system program id
* @param rent rent program id
*/
async createMintTokenTransaction(assetUuid: string, payer: PublicKey, signingAuthority: PublicKey,
mintAuthority: PublicKey, configName: string = NAME,
systemProgram: PublicKey = SystemProgram.programId, rent: PublicKey = SYSVAR_RENT_PUBKEY,
associatedTokenProgram: PublicKey = ASSOCIATED_TOKEN_PROGRAM_ID, tokenProgram: PublicKey = TOKEN_PROGRAM_ID): Promise<Transaction> {
const [configAccount, configAccountBump] = await this.getConfigAccountPdaAndBump(configName);
const [mintAccount] = await this.getMintAccountPdaAndBump(assetUuid);
let tx = await this.program.methods.createMintToken(configName, configAccountBump, assetUuid)
.accounts({
payer: payer,
signingAuthority: signingAuthority,
config: configAccount,
mint: mintAccount,
mintAuthority: mintAuthority,
associatedTokenProgram: associatedTokenProgram,
tokenProgram: tokenProgram,
systemProgram: systemProgram,
rent: rent
})
.transaction();
return tx;
}
/**
* Create collection token transaction
* @param collectionUuid seed for the collection mint account
* @param payer transaction fee payer public key
* @param signingAuthority signing authority public key
* @param collectionMintAuthority collection mint authority public key
* @param collectionOwner collection owner
* @param tokenName token name
* @param tokenSymbol token symbol
* @param tokenUrl token url
* @param tokenIsMutable token is mutable
* @param tokenSellerPoint token seller point
* @param creators List of the creators
* @param configName config account seed for pda
* @param tokenProgram token program id
* @param associatedTokenProgram associated token program id
* @param systemProgram system program id
* @param rent rent program id
* @param mplProgram Metadata program id
*/
async createCollectionTokenTransaction(collectionUuid: string, payer: PublicKey, signingAuthority: PublicKey, collectionMintAuthority: PublicKey, collectionOwner: PublicKey,
tokenName: string, tokenSymbol: string, tokenUrl: string, tokenIsMutable: boolean, tokenSellerPoint: number, creators: CreatorType[], configName: string = NAME,
systemProgram: PublicKey = SystemProgram.programId, rent: PublicKey = SYSVAR_RENT_PUBKEY,
associatedTokenProgram: PublicKey = ASSOCIATED_TOKEN_PROGRAM_ID, tokenProgram: PublicKey = TOKEN_PROGRAM_ID,
mplProgram: PublicKey = METADATA_PROGRAM_ID): Promise<Transaction> {
const [configAccount, configAccountBump] = await this.getConfigAccountPdaAndBump(configName);
const [collectionMintAccount, collectionMintAccountBump] = await this.getMintAccountPdaAndBump(collectionUuid);
const [collectionMetadata] = await this.getMetadataAccountPda(collectionMintAccount, mplProgram);
const [collectionMasterEdition] = await this.getMasterEditionAccountPda(collectionMintAccount, mplProgram);
const collectionTokenAccount = await getAssociatedTokenAddress(collectionMintAccount, collectionOwner);
let tx = await this.createMintTokenTransaction(collectionUuid, payer, signingAuthority, collectionMintAuthority, configName,
systemProgram, rent, associatedTokenProgram, tokenProgram);
let collectionTx = await this.program.methods.createCollection(configName, configAccountBump, collectionUuid, collectionMintAccountBump,
tokenName, tokenSymbol, tokenUrl, tokenIsMutable, tokenSellerPoint, creators)
.accounts({
payer: payer,
signingAuthority: signingAuthority,
config: configAccount,
collectionMintAuthority: collectionMintAuthority,
collectionOwner: collectionOwner,
collectionMintAccount: collectionMintAccount,
collectionMintTokenAccount: collectionTokenAccount,
collectionMetadata: collectionMetadata,
collectionMasterEdition: collectionMasterEdition,
mplProgram: mplProgram,
associatedTokenProgram: associatedTokenProgram,
tokenProgram: tokenProgram,
systemProgram: systemProgram,
rent: rent
}).transaction();
tx.add(collectionTx);
return tx;
}
/**
* Create sub collection token transaction
* @param collectionUuid seed for the collection mint account
* @param subCollectionUuid seed for the sub collection mint account
* @param payer transaction fee payer public key
* @param signingAuthority signing authority public key
* @param subCollectionMintAuthority sub collection mint authority public key
* @param subCollectionOwner sub collection owner public key
* @param tokenName token name
* @param tokenSymbol token symbol
* @param tokenUrl token url
* @param tokenIsMutable token is mutable
* @param tokenSellerPoint token seller point
* @param creators List of the creators
* @param configName config account seed for pda
* @param collectionUpdateAuthority collection update authority (By default it's singing authority)
* @param tokenProgram token program id
* @param associatedTokenProgram associated token program id
* @param systemProgram system program id
* @param rent rent program id
* @param mplProgram Metadata program id
*/
async createSubCollectionTokenTransaction(collectionUuid: string, subCollectionUuid: string, payer: PublicKey, signingAuthority: PublicKey,
subCollectionMintAuthority: PublicKey, subCollectionOwner: PublicKey, tokenName: string, tokenSymbol: string, tokenUrl: string,
tokenIsMutable: boolean, tokenSellerPoint: number, creators: CreatorType[], configName: string = NAME,
collectionUpdateAuthority: PublicKey = signingAuthority, systemProgram: PublicKey = SystemProgram.programId, rent: PublicKey = SYSVAR_RENT_PUBKEY,
associatedTokenProgram: PublicKey = ASSOCIATED_TOKEN_PROGRAM_ID, tokenProgram: PublicKey = TOKEN_PROGRAM_ID,
mplProgram: PublicKey = METADATA_PROGRAM_ID): Promise<Transaction> {
const [configAccount, configAccountBump] = await this.getConfigAccountPdaAndBump(configName);
const [collectionMintAccount, collectionMintAccountBump] = await this.getMintAccountPdaAndBump(collectionUuid);
const [collectionMetadata] = await this.getMetadataAccountPda(collectionMintAccount, mplProgram);
const [collectionMasterEdition] = await this.getMasterEditionAccountPda(collectionMintAccount, mplProgram);
const [subCollectionMintAccount, subCollectionMintAccountBump] = await this.getMintAccountPdaAndBump(subCollectionUuid);
const [subCollectionMetadata] = await this.getMetadataAccountPda(subCollectionMintAccount, mplProgram);
const [subCollectionMasterEdition] = await this.getMasterEditionAccountPda(subCollectionMintAccount, mplProgram);
const subCollectionTokenAccount = await getAssociatedTokenAddress(subCollectionMintAccount, subCollectionOwner);
let tx = await this.createMintTokenTransaction(subCollectionUuid, payer, signingAuthority, subCollectionMintAuthority, configName,
systemProgram, rent, associatedTokenProgram, tokenProgram);
let collectionTx = await this.program.methods.createSubCollection(configName, configAccountBump, collectionUuid, collectionMintAccountBump, subCollectionUuid, subCollectionMintAccountBump,
tokenName, tokenSymbol, tokenUrl, tokenIsMutable, tokenSellerPoint, creators)
.accounts({
payer: payer,
signingAuthority: signingAuthority,
config: configAccount,
collectionUpdateAuthority: collectionUpdateAuthority,
collectionMintAccount: collectionMintAccount,
collectionMetadata: collectionMetadata,
collectionMasterEdition: collectionMasterEdition,
subCollectionMintAuthority: subCollectionMintAuthority,
subCollectionOwner: subCollectionOwner,
subCollectionMintAccount: subCollectionMintAccount,
subCollectionMetadata: subCollectionMetadata,
subCollectionMasterEdition: subCollectionMasterEdition,
subCollectionMintTokenAccount: subCollectionTokenAccount,
mplProgram: mplProgram,
associatedTokenProgram: associatedTokenProgram,
tokenProgram: tokenProgram,
systemProgram: systemProgram,
rent: rent
}).transaction();
tx.add(collectionTx);
return tx;
}
/**
* Create asset token transaction
* @param assetUuid asset uuid
* @param collectionUuid seed for the collection mint account
* @param payer transaction fee payer public key
* @param signingAuthority signing authority public key
* @param user user public key
* @param assetMintAuthority: asset mint authority
* @param tokenName token name
* @param tokenSymbol token symbol
* @param tokenUrl token url
* @param tokenIsMutable token is mutable
* @param tokenSellerPoint token seller point
* @param creators List of the creators
* @param configName config account seed for pda
* @param collectionUpdateAuthority collection update authority (by default it's singing )
* @param tokenProgram token program id
* @param associatedTokenProgram associated token program id
* @param systemProgram system program id
* @param rent rent program id
* @param mplProgram Metadata program id
*/
async createAssetTokenTransaction(assetUuid: string, collectionUuid: string, payer: PublicKey, signingAuthority: PublicKey, user: PublicKey, assetMintAuthority: PublicKey,
tokenName: string, tokenSymbol: string, tokenUrl: string, tokenIsMutable: boolean, tokenSellerPoint: number, creators: CreatorType[],
configName: string = NAME, collectionUpdateAuthority: PublicKey = signingAuthority,
systemProgram: PublicKey = SystemProgram.programId, rent: PublicKey = SYSVAR_RENT_PUBKEY,
associatedTokenProgram: PublicKey = ASSOCIATED_TOKEN_PROGRAM_ID, tokenProgram: PublicKey = TOKEN_PROGRAM_ID,
mplProgram: PublicKey = METADATA_PROGRAM_ID): Promise<Transaction> {
const [configAccount, configAccountBump] = await this.getConfigAccountPdaAndBump(configName);
const [collectionMintAccount, collectionMintAccountBump] = await this.getMintAccountPdaAndBump(collectionUuid);
const [collectionMetadata] = await this.getMetadataAccountPda(collectionMintAccount, mplProgram);
const [collectionMasterEdition] = await this.getMasterEditionAccountPda(collectionMintAccount, mplProgram);
const [assetMintAccount, assetMintAccountBump] = await this.getMintAccountPdaAndBump(assetUuid);
const [assetMetadata] = await this.getMetadataAccountPda(assetMintAccount, mplProgram);
const [assetMasterEdition] = await this.getMasterEditionAccountPda(assetMintAccount, mplProgram);
const assetTokenAccount = await getAssociatedTokenAddress(assetMintAccount, user);
const currentBlockTime = await this.getCurrentBlockTime();
let tx = await this.createMintTokenTransaction(assetUuid, payer, signingAuthority, assetMintAuthority, configName,
systemProgram, rent, associatedTokenProgram, tokenProgram);
const assetTx = await this.program.methods.createAsset(configName, configAccountBump, collectionUuid, collectionMintAccountBump, assetUuid, assetMintAccountBump,
tokenName, tokenSymbol, tokenUrl, tokenIsMutable, tokenSellerPoint, creators)
.accounts({
payer: payer,
signingAuthority: signingAuthority,
user: user,
config: configAccount,
assetMintAuthority: assetMintAuthority,
assetMintAccount: assetMintAccount,
assetMetadata: assetMetadata,
assetMasterEdition: assetMasterEdition,
assetMintTokenAccount: assetTokenAccount,
collectionUpdateAuthority: collectionUpdateAuthority,
collectionMintAccount: collectionMintAccount,
collectionMetadata: collectionMetadata,
collectionMasterEdition: collectionMasterEdition,
mplProgram: mplProgram,
associatedTokenProgram: associatedTokenProgram,
tokenProgram: tokenProgram,
systemProgram: systemProgram,
rent: rent
})
.transaction();
tx.add(assetTx);
return tx;
}
/**
* Remove event listener.
* @param eventId Event id which need to remove.
*/
async removeEventListener(eventId: number) {
await this.program.removeEventListener(eventId);
}
/**
* Add mint event listener.
* @param callback Callback for the event to manage the event response on emit.
*/
addMintEventListener(callback: (event: MintEvent) => void): number {
return this.program.addEventListener(MINT_EVENT_NAME, callback);
}
/**
* Add collection event listener.
* @param callback Callback for the event to manage the event response on emit.
*/
addCollectionEventListener(callback: (event: CollectionEvent) => void): number {
return this.program.addEventListener(COLLECTION_EVENT_NAME, callback);
}
/**
* Add sub collection event listener.
* @param callback Callback for the event to manage the event response on emit.
*/
addSubCollectionEventListener(callback: (event: SubCollectionEvent) => void): number {
return this.program.addEventListener(SUB_COLLECTION_EVENT_NAME, callback);
}
/**
* Add asset event listener.
* @param callback Callback for the event to manage the event response on emit.
*/
addAssetEventListener(callback: (event: AssetEvent) => void): number {
return this.program.addEventListener(ASSET_EVENT_NAME, callback);
}
/**
* Creator sign metadata instruction.
* @param uuid Seed for the mint account
* @param creatorPublicKey Creator public key
* @param mplProgram Metadata program id
*/
async creatorSignMetadataInstruction(uuid: string, creatorPublicKey: PublicKey, mplProgram: PublicKey = METADATA_PROGRAM_ID): Promise<TransactionInstruction> {
const [mintPda] = await this.getMintAccountPdaAndBump(uuid);
const [metadataPda] = await this.getMetadataAccountPda(mintPda, mplProgram);
return createSignMetadataInstruction({
metadata: metadataPda,
creator: creatorPublicKey
});
}
/**
* Create and add creator sign metadata instruction.
* @param tx Transaction object where instruction needs to add.
* @param uuid Seed for the mint account
* @param creatorPublicKey Creator public key
* @param mplProgram Metadata program id
*/
async createAndAddCreatorSignMetadataInstruction(tx: Transaction, uuid: string, creatorPublicKey: PublicKey, mplProgram: PublicKey = METADATA_PROGRAM_ID): Promise<Transaction> {
const [mintPda] = await this.getMintAccountPdaAndBump(uuid);
const [metadataPda] = await this.getMetadataAccountPda(mintPda, mplProgram);
return tx.add(createSignMetadataInstruction({
metadata: metadataPda,
creator: creatorPublicKey
}));
}
}
export interface CreatorType {
address: web3.PublicKey;
verified: boolean;
share: number;
}