Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Add script to create token metadata #16

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,11 @@ Then run the test: `bun test`
## Run the scripts
Run the script with config file specified in the CLI, some examples:

** Create new token with metadata**
```bash
bun run src/create_token.ts --config ./config/create_token.json
```

** Create dynamic AMM pool**
```bash
bun run src/create_pool.ts --config ./config/create_dynamic_amm_pool.json
Expand Down
Binary file modified bun.lockb
Binary file not shown.
16 changes: 16 additions & 0 deletions config/create_token.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"rpcUrl": "https://api.mainnet-beta.solana.com",
"dryRun": false,
"keypairFilePath": "keypair.json",
"computeUnitPriceMicroLamports": 100000,
"quoteSymbol": "SOL",
"createBaseToken": {
"mintBaseTokenAmount": 10000000,
"baseDecimals": 6,
"tokenMetadata": {
"name": "Test token",
"symbol": "TEST",
"uri": "https://static.jup.ag/jup/metadata.json"
}
}
}
5 changes: 5 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,11 @@
"dependencies": {
"@coral-xyz/anchor": "^0.28.0",
"@mercurial-finance/dynamic-amm-sdk": "^1.1.19",
"@metaplex-foundation/mpl-token-metadata": "^3.3.0",
"@metaplex-foundation/mpl-toolbox": "^0.9.4",
"@metaplex-foundation/umi": "^1.0.0",
"@metaplex-foundation/umi-bundle-defaults": "^1.0.0",
"@metaplex-foundation/umi-web3js-adapters": "^1.0.0",
"@meteora-ag/alpha-vault": "^1.1.8",
"@meteora-ag/dlmm": "^1.3.5",
"@meteora-ag/m3m3": "^1.0.5",
Expand Down
81 changes: 81 additions & 0 deletions src/create_token.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
import { Wallet } from "@coral-xyz/anchor";
import { ComputeBudgetProgram, Connection, PublicKey } from "@solana/web3.js";
import { DEFAULT_COMMITMENT_LEVEL, MeteoraConfig, createPermissionlessDlmmPool, createPermissionlessDynamicPool, createTokenMint, getQuoteMint, parseConfigFromCli, safeParseKeypairFromFile } from ".";
import { createTokenMetadata } from "./libs/create_token_metadata";
import { mplTokenMetadata, createV1, TokenStandard, createFungible, mintV1 } from "@metaplex-foundation/mpl-token-metadata";
import { createUmi } from "@metaplex-foundation/umi-bundle-defaults";
import { mplToolbox, setComputeUnitPrice } from "@metaplex-foundation/mpl-toolbox";
import {
fromWeb3JsKeypair,
fromWeb3JsPublicKey,
toWeb3JsPublicKey,
} from "@metaplex-foundation/umi-web3js-adapters";
import { base58, generateSigner, keypairIdentity } from "@metaplex-foundation/umi";

async function main() {
let config: MeteoraConfig = parseConfigFromCli();

console.log(`> Using keypair file path ${config.keypairFilePath}`);
let keypair = safeParseKeypairFromFile(config.keypairFilePath);

console.log("\n> Initializing with general configuration...");
console.log(`- Using RPC URL ${config.rpcUrl}`);
console.log(`- Dry run = ${config.dryRun}`);
console.log(`- Using payer ${keypair.publicKey} to execute commands`);

const connection = new Connection(config.rpcUrl, DEFAULT_COMMITMENT_LEVEL);
const wallet = new Wallet(keypair);

if (!config.createBaseToken) {
throw new Error("Missing createBaseToken in configuration");
}

if (!config.createBaseToken.tokenMetadata) {
throw new Error("Missing tokenMetadata in createBaseToken configuration");
}

console.log(`>>> Creating token mint and metadata...`);

const umi = createUmi(connection).use(mplToolbox())
umi.use(keypairIdentity(fromWeb3JsKeypair(keypair)));
// Create new token mint
const mint = generateSigner(umi);

console.log(`>>> Prepare to create token mint ${mint.publicKey}`);

let builder = createFungible(umi, {
mint,
name: config.createBaseToken.tokenMetadata.name as string,
symbol: config.createBaseToken.tokenMetadata.symbol as string,
uri: config.createBaseToken.tokenMetadata.uri as string,
decimals: config.createBaseToken.baseDecimals,
sellerFeeBasisPoints: {
basisPoints: 0n,
identifier: "%",
decimals: 2,
},
});

const supply = Number(config.createBaseToken.mintBaseTokenAmount);
if (Number.isNaN(supply)) {
throw new Error("Invalid mint base token amount, not a number");
}
builder = builder.add(
mintV1(umi, {
mint: mint.publicKey,
tokenStandard: TokenStandard.Fungible,
tokenOwner: fromWeb3JsPublicKey(wallet.publicKey),
amount: supply * Math.pow(10, config.createBaseToken.baseDecimals),
}),
);

builder = builder.prepend(setComputeUnitPrice(umi, {
microLamports: config.computeUnitPriceMicroLamports
}));

const { signature } = await builder.sendAndConfirm(umi, { confirm: { commitment: DEFAULT_COMMITMENT_LEVEL } });

console.log(`>>> Created token mint and token metadata successfully with tx hash ${base58.deserialize(signature)[0]}`);
}

main();
23 changes: 23 additions & 0 deletions src/libs/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,22 @@ const CONFIG_SCHEMA: JSONSchemaType<MeteoraConfig> = {
baseDecimals: {
type: "number",
},
tokenMetadata: {
type: "object",
properties: {
name: {
type: "string",
},
symbol: {
type: "string",
},
uri: {
type: "string",
},
},
required: ["name", "symbol", "uri"],
additionalProperties: false,
}
},
required: ["mintBaseTokenAmount", "baseDecimals"],
additionalProperties: false,
Expand Down Expand Up @@ -274,6 +290,13 @@ export interface MeteoraConfig {
export interface CreateBaseMintConfig {
mintBaseTokenAmount: number | string;
baseDecimals: number;
tokenMetadata: TokenMetadataConfig | null;
}

export interface TokenMetadataConfig {
name: String;
symbol: String;
uri: String;
}

export interface DynamicAmmConfig {
Expand Down
Loading