@dinolab/crypto-mm
Version:
Crypto Market Maker
238 lines • 11.6 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
const web3_js_1 = require("@solana/web3.js");
const spl_token_1 = require("@solana/spl-token");
const umi_bundle_defaults_1 = require("@metaplex-foundation/umi-bundle-defaults");
const mpl_token_metadata_1 = require("@metaplex-foundation/mpl-token-metadata");
const umi_1 = require("@metaplex-foundation/umi");
const pinata_1 = require("pinata");
class SolTokenCreator {
constructor(rpcUrl) {
// this.rpcUrl = rpcUrl;
this.rpcUrl = (0, web3_js_1.clusterApiUrl)('devnet'); // HM - Test
this.connection = new web3_js_1.Connection(this.rpcUrl);
}
async createToken(tokenInfo, ownerKeypair, revokeMintAuthority, revokeFreezeAuthority) {
try {
console.log('⏳ Generating token address...');
const tokenKeypair = web3_js_1.Keypair.generate();
console.log('⏳ Mining token...');
const mintAddress = await this.mintToken(tokenKeypair, ownerKeypair);
console.log(`✅ Token created: ${mintAddress.toString()}`);
const tokenAccount = await this.createTokenAccount(mintAddress, ownerKeypair);
await this.supplyToken(mintAddress, tokenAccount, ownerKeypair, tokenInfo.totalSupply);
await this.createTokenMetadata(mintAddress.toString(), tokenInfo, ownerKeypair);
if (revokeMintAuthority) {
await this.revokeMintAuthority(mintAddress, ownerKeypair);
}
if (revokeFreezeAuthority) {
await this.revokeFreezeAuthority(mintAddress, ownerKeypair);
}
console.log('Completely create');
return mintAddress.toString();
}
catch (e) {
console.error('❌ Error creating token');
throw e;
}
}
async mintToken(tokenKeypair, ownerKeypair) {
try {
const mintAddress = await (0, spl_token_1.createMint)(this.connection, ownerKeypair, ownerKeypair.publicKey, // mint authority
ownerKeypair.publicKey, // freeze authority
9, tokenKeypair, { commitment: 'confirmed' });
return mintAddress;
}
catch (error) {
console.error('❌ Error minting token:', error.message);
throw error;
}
}
async createTokenAccount(mintAddress, ownerKeypair) {
try {
console.log('📋 Creating token account...');
const tokenAccount = await (0, spl_token_1.createAccount)(this.connection, ownerKeypair, mintAddress, ownerKeypair.publicKey, undefined, { commitment: 'confirmed' });
console.log(`✅ Token account created: ${tokenAccount}`);
return tokenAccount;
}
catch (error) {
console.error('❌ Error creating token account:', error.message);
throw error;
}
}
async supplyToken(mintAddress, tokenAccount, ownerKeypair, amount) {
try {
const signature = await (0, spl_token_1.mintTo)(this.connection, ownerKeypair, mintAddress, tokenAccount, ownerKeypair, amount, [], { commitment: 'confirmed' });
console.log(`✅ Tokens supplied. Signature: ${signature}`);
return signature;
}
catch (error) {
console.error('❌ Error supplying tokens:', error.message);
throw error;
}
}
// Function mới để tạo metadata với UMI
async createTokenMetadata(mintAddress, tokenInfo, ownerKeypair) {
try {
// 3. Upload metadata JSON đơn giản
const metadataUri = await this.uploadMetadataToStorage({
name: tokenInfo.name,
symbol: tokenInfo.symbol,
description: tokenInfo.description,
image: tokenInfo.imageUrl || '',
website: tokenInfo.social?.website,
twitter: tokenInfo.social?.twitter,
telegram: tokenInfo.social?.telegram,
extensions: {
website: tokenInfo.social?.website,
twitter: tokenInfo.social?.twitter,
telegram: tokenInfo.social?.telegram,
}
});
if (!metadataUri) {
throw new Error('Metadata was not uploaded');
}
let result = undefined;
const delayTime = 10000;
console.log(`Delay ${(delayTime / 1000).toFixed(2)}s to update token metadata...`);
await new Promise(resolve => {
setTimeout(async () => {
result = await this.updateTokenMetadata(ownerKeypair, mintAddress.toString(), tokenInfo.name, tokenInfo.symbol, 9, metadataUri);
resolve(result);
}, delayTime);
});
return result;
}
catch (error) {
console.error('❌ Error creating metadata:', error.message);
throw error;
}
}
async uploadMetadataToStorage(metadata) {
try {
console.log('📤 Uploading metadata JSON: ', metadata);
const pinata = new pinata_1.PinataSDK({
pinataJwt: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySW5mb3JtYXRpb24iOnsiaWQiOiJlM2RkYjM3OC02NzUyLTRhYjUtYTcyYi0xOGU0M2U3YzhjNGMiLCJlbWFpbCI6Im5nb2NodW5nMTI0M0BnbWFpbC5jb20iLCJlbWFpbF92ZXJpZmllZCI6dHJ1ZSwicGluX3BvbGljeSI6eyJyZWdpb25zIjpbeyJkZXNpcmVkUmVwbGljYXRpb25Db3VudCI6MSwiaWQiOiJGUkExIn0seyJkZXNpcmVkUmVwbGljYXRpb25Db3VudCI6MSwiaWQiOiJOWUMxIn1dLCJ2ZXJzaW9uIjoxfSwibWZhX2VuYWJsZWQiOmZhbHNlLCJzdGF0dXMiOiJBQ1RJVkUifSwiYXV0aGVudGljYXRpb25UeXBlIjoic2NvcGVkS2V5Iiwic2NvcGVkS2V5S2V5IjoiNWY0ZGVkZDI1ZGU4OTBiYmZkZGYiLCJzY29wZWRLZXlTZWNyZXQiOiI5OWRjYzJjNjkxNmVmOWE0OGUxM2FkMzEyNTRlMmMzZDBhZjljOGM4NDMwZGIxOTY0ZTdkMDI3NTY1NDYxYmM4IiwiZXhwIjoxNzgxNjQ0ODk4fQ.w0rGl2cDRmpWr1hmX4Qx4sw_5jMW9jzRtKRoc3p6w5Y',
pinataGateway: 'white-effective-tarantula-591.mypinata.cloud'
});
const ts = Date.now();
const file = new File([JSON.stringify(metadata)], `${metadata.symbol}_${ts}`, { type: 'text/plain' });
const upload = await pinata.upload.public.file(file);
const url = `https://gateway.pinata.cloud/ipfs/${upload.cid}`;
console.log(`✅ Metadata uploaded to Pinata: ${url}`);
return url;
}
catch (error) {
console.log(`❌ Error uploading metadata to storage. Error: ${error.message}`);
}
}
async updateTokenMetadata(keypair, mintAddress, name, symbol, decimals, uri) {
try {
const umi = (0, umi_bundle_defaults_1.createUmi)(this.rpcUrl).use((0, mpl_token_metadata_1.mplTokenMetadata)());
// Setup keypair và signer
const umiKeypair = umi.eddsa.createKeypairFromSecretKey(keypair.secretKey);
const signer = (0, umi_1.createSignerFromKeypair)(umi, umiKeypair);
umi.use((0, umi_1.signerIdentity)(signer));
// Convert mint address string to PublicKey
const mint = (0, umi_1.publicKey)(mintAddress);
// Lấy metadata PDA
const [metadataAddress] = (0, mpl_token_metadata_1.findMetadataPda)(umi, { mint: mint });
console.log('Processing metadata...');
try {
await (0, mpl_token_metadata_1.fetchMetadata)(umi, metadataAddress);
console.log('Existing metadata found. Updating...');
// Update metadata
const tx = (0, mpl_token_metadata_1.updateV1)(umi, {
mint: mint,
authority: signer,
data: (0, umi_1.some)({
name: name,
symbol: symbol,
uri: uri,
sellerFeeBasisPoints: 0,
creators: (0, umi_1.some)([{
address: keypair.publicKey,
verified: true,
share: 100
}]),
}),
collection: (0, mpl_token_metadata_1.collectionToggle)('None'),
uses: (0, mpl_token_metadata_1.usesToggle)('None'),
});
const result = await tx.sendAndConfirm(umi);
console.log('Update metadata successful!');
return {
metadataAddress,
uri,
signature: result.signature.toString(),
};
}
catch (error) {
if (error.name === 'AccountNotFoundError') {
console.log('Metadata account not found. Creating new metadata...');
// Create new metadata
const tx = (0, mpl_token_metadata_1.createV1)(umi, {
mint: mint,
authority: signer,
name: name,
symbol: symbol,
decimals: decimals,
uri: uri,
sellerFeeBasisPoints: (0, umi_1.percentAmount)(0),
creators: (0, umi_1.some)([{
address: keypair.publicKey.toBase58(),
verified: true,
share: 100
}]),
collection: (0, umi_1.none)(),
uses: (0, umi_1.none)(),
tokenStandard: mpl_token_metadata_1.TokenStandard.Fungible,
isMutable: true,
});
const result = await tx.sendAndConfirm(umi);
console.log('Creation metadata successful!');
return {
metadataAddress,
uri,
signature: result.signature.toString(),
};
}
else {
throw error;
}
}
}
catch (error) {
console.error('Error:', error);
if (error.logs) {
console.error('Transaction logs:', error.logs);
}
}
}
async revokeMintAuthority(mintAddress, ownerKeypair) {
try {
console.log('🔒 Revoking mint authority...');
const signature = await (0, spl_token_1.setAuthority)(this.connection, ownerKeypair, mintAddress, ownerKeypair, spl_token_1.AuthorityType.MintTokens, null, [], { commitment: 'confirmed' });
console.log(`✅ Mint authority revoked. Signature: ${signature}`);
return signature;
}
catch (error) {
console.error('❌ Error revoking mint authority:', error.message);
throw error;
}
}
async revokeFreezeAuthority(mintAddress, ownerKeypair) {
try {
console.log('🔒 Revoking freeze authority...');
const signature = await (0, spl_token_1.setAuthority)(this.connection, ownerKeypair, mintAddress, ownerKeypair, spl_token_1.AuthorityType.FreezeAccount, null, [], { commitment: 'confirmed' });
console.log(`✅ Freeze authority revoked. Signature: ${signature}`);
return signature;
}
catch (error) {
console.error('❌ Error revoking freeze authority:', error.message);
throw error;
}
}
}
exports.default = SolTokenCreator;
//# sourceMappingURL=sol.token.creator.js.map