Untitled

mail@pastecode.io avatar
unknown
typescript
13 days ago
7.2 kB
3
Indexable
Never
import * as fs from 'fs';

import {Connection, Keypair, sendAndConfirmTransaction, SystemProgram, Transaction} from '@solana/web3.js';
import {
    createAssociatedTokenAccountIdempotent,
    createInitializeMintInstruction,
    createInitializeTransferFeeConfigInstruction,
    ExtensionType,
    getMintLen, mintTo,
    TOKEN_2022_PROGRAM_ID,
} from "@solana/spl-token";
import {
    createSignerFromKeypair, keypairIdentity,
    none,
    percentAmount,
    PublicKey as SPLTokenPublicKey,
    signerIdentity, signerPayer, Umi
} from "@metaplex-foundation/umi";
import {
    Collection, CollectionDetails, createV1,
    CreateV1InstructionAccounts,
    CreateV1InstructionData,
    Creator, PrintSupply, TokenStandard,
    Uses,
} from "@metaplex-foundation/mpl-token-metadata";
import {fromWeb3JsKeypair, fromWeb3JsPublicKey} from "@metaplex-foundation/umi-web3js-adapters";
import {createUmi} from "@metaplex-foundation/umi-bundle-defaults";

const bs58 = require('bs58');

import * as dotenv from 'dotenv';
dotenv.config();

let connection: Connection;

// const tokenKeypairFile = "wallets/test/token.json";
// const tokenKey = loadWalletKey(tokenKeypairFile);
// const tokenAcckountKey = loadWalletKey(tokenAccountKeyfile);

const devKeypairFile = "wallets/test/dev.json";
const dev = loadWalletKey(devKeypairFile); //Dev is signer
const mintAuthority = dev;
const transferFeeConfigAuthority = dev;
const withdrawWithheldAuthority = dev;

const mintKeypair = Keypair.generate();
const mint = mintKeypair.publicKey;

let umi: Umi;

let devPk: string = '';
let rpcEndpoint: string = '';
let tokenDecimals: string = '';
let tokenMintAmount: string = '';
let tokenTransferFeeBasispoints: string = '';
let tokenName: string = '';
let tokenSymbol: string = '';
let tokenJsonUri: string = '';

// @ts-ignore
let mintAmount = BigInt(0);

export function loadWalletKey(keypairFile:string): Keypair {
    if (!keypairFile || keypairFile == '') {
        throw new Error('Keypair is required!');
    }
    const loaded = Keypair.fromSecretKey(
        new Uint8Array(JSON.parse(fs.readFileSync(keypairFile).toString())),
    );
    return loaded;
}

const MINT_EXTENSIONS = [ExtensionType.TransferFeeConfig];

async function createToken() {
    const mintLen = getMintLen(MINT_EXTENSIONS);
    const mintLamports = await connection.getMinimumBalanceForRentExemption(mintLen);

    const mintTransaction = new Transaction().add(
        SystemProgram.createAccount({ //Token account
            fromPubkey: dev.publicKey,
            newAccountPubkey: mint,
            space: mintLen,
            lamports: mintLamports,
            programId: TOKEN_2022_PROGRAM_ID,
        }),
        createInitializeTransferFeeConfigInstruction(
            mint,
            transferFeeConfigAuthority.publicKey,
            withdrawWithheldAuthority.publicKey,
            Number(tokenTransferFeeBasispoints),
            mintAmount,
            TOKEN_2022_PROGRAM_ID
        ),
        createInitializeMintInstruction(mint, Number(tokenDecimals), mintAuthority.publicKey, null, TOKEN_2022_PROGRAM_ID)
    );
    const newTokenTx = await sendAndConfirmTransaction(connection, mintTransaction, [dev, mintKeypair], undefined);
    console.log("New Token Created:", newTokenTx);
}

async function mintToken(){
    const owner = dev;
    const ownerTokenAccount = await createAssociatedTokenAccountIdempotent(connection, dev, mint, owner.publicKey, {}, TOKEN_2022_PROGRAM_ID);
    const mintSignature = await mintTo(
        connection,
        dev,
        mint,
        ownerTokenAccount,
        dev.publicKey,
        mintAmount,
        [],
        undefined,
        TOKEN_2022_PROGRAM_ID
    );
    console.log("Tokens Minted:", mintSignature);
}

async function attachMetadata() {
    const metadata = {
        name: tokenName,
        symbol: tokenSymbol,
        uri: tokenJsonUri,
    };

    const onChainData = {
        ...metadata,
        sellerFeeBasisPoints: percentAmount(5,2),
        creators: none<Creator[]>(),
        collection: none<Collection>(),
        uses: none<Uses>(),
    }

    const mintSigner = createSignerFromKeypair(umi, fromWeb3JsKeypair(mintKeypair));
    const devSigner = createSignerFromKeypair(umi, fromWeb3JsKeypair(dev));

    const accounts: CreateV1InstructionAccounts = {
        mint: fromWeb3JsPublicKey(mint),
        // payer: devSigner,
        // authority: devSigner,
        splTokenProgram: fromWeb3JsPublicKey(TOKEN_2022_PROGRAM_ID)
    }

    const data: CreateV1InstructionData = {
        ...onChainData,
        isMutable: true,
        discriminator: 0,
        tokenStandard: TokenStandard.Fungible,
        collectionDetails: none<CollectionDetails>(),
        ruleSet: none<SPLTokenPublicKey>(),
        createV1Discriminator: 0,
        primarySaleHappened: true,
        decimals: none<number>(),
        printSupply: none<PrintSupply>(),
    }

    const txid = await createV1(umi, {...accounts, ...data}).sendAndConfirm(umi);
    console.log("Metadata attached: ",bs58.encode(txid.signature))
}

async function main() {
    if(!validateEnv()) {
        return;
    }

    connection = new Connection(rpcEndpoint, 'confirmed');

    console.log(Number.parseInt(tokenMintAmount), Number.parseInt(tokenDecimals));
    // return;
    mintAmount = BigInt(Number.parseInt(tokenMintAmount) * Math.pow(10, Number.parseInt(tokenDecimals)))

    umi = createUmi(rpcEndpoint);
    // const signer = createSignerFromKeypair(umi, fromWeb3JsKeypair(mintKeypair));
    // umi.use(signerIdentity(signer, false));
    // const devSigner = createSignerFromKeypair(umi, fromWeb3JsKeypair(dev));
    // umi.use(signerIdentity(devSigner, true))

    const devSigner = createSignerFromKeypair(umi, fromWeb3JsKeypair(dev));
    umi.use(keypairIdentity(devSigner, true));

    const mintSigner = createSignerFromKeypair(umi, fromWeb3JsKeypair(mintKeypair));
    umi.use(keypairIdentity(mintSigner, false));

    // umi.use(mplCandyMachine());

    await createToken();
    await mintToken();
    await attachMetadata();
}

main();

function validateEnv() {
    devPk = process.env.DEV_PRIVATE_KEY as string;
    rpcEndpoint = process.env.RPC_ENDPOINT as string;
    tokenDecimals = process.env.TOKEN_DECIMALS as string;
    tokenMintAmount = process.env.TOKEN_MINT_AMOUNT as string;
    tokenTransferFeeBasispoints = process.env.TOKEN_TRANSFER_FEE_BASISPOINTS as string;
    tokenName = process.env.TOKEN_NAME as string;
    tokenSymbol = process.env.TOKEN_SYMBOL as string;
    tokenJsonUri = process.env.TOKEN_JSON_URI as string;

    if((devPk == null || devPk == '') ||
        (rpcEndpoint == null || rpcEndpoint == '') ||
        (tokenDecimals == null || tokenDecimals == '') ||
        (tokenMintAmount == null || tokenMintAmount == '') ||
        (tokenTransferFeeBasispoints == null || tokenTransferFeeBasispoints == '') ||
        (tokenName == null || tokenName == '') ||
        (tokenSymbol == null || tokenSymbol == '') ||
        (tokenJsonUri == null || tokenJsonUri == '')
    ) {
        console.log("Missing environment variables. Please ensure you have all variables defined in your .env file.");
        return false;
    }

    return true;
}

Leave a Comment