UNPKG

@mirrorworld/library.assetminting.new

Version:

asset minting SDK

530 lines (441 loc) 23.3 kB
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; }