Meteora
  • Meteora: The most dynamic and sustainable liquidity layer on Solana
  • PRODUCT OVERVIEW
    • Meteora Liquidity Pools
      • DLMM Overview
        • What is DLMM?
        • DLMM Program
        • Dynamic Fees
        • Strategies & Use Cases
        • DLMM Farming Rewards
      • DLMM Launch Pool Overview
      • Dynamic AMM Overview
        • What is a Dynamic AMM Pool?
        • Dynamic AMM LP Fee and APY Calculation
        • Creating a Dynamic AMM Pool via the UI
        • Claiming Fees from Permanently Locked Liquidity
        • Dynamic AMM Stable Pools
        • Dynamic LST Pools
        • Additional yield from Dynamic Vaults
        • Dynamic AMM Farm Overview
      • DAMM v2 Overview
      • Memecoin Pool Overview
        • Memecoin Pool v2
          • What is Memecoin Pool v2?
        • Memecoin Pool v1
          • What is Memecoin Pool v1?
          • Permanently Locking Liquidity
      • Stake2Earn Pool Overview
        • What is a Stake2Earn Pool?
        • Stake2Earn for Launchpads
      • Multi-Token Stable Pool Overview
    • Alpha Vault Overview
    • Dynamic Vault Overview
      • What is a Dynamic Vault?
      • Dynamic Vault Program
      • Hermes - Meteora's Keeper
        • Algorithm to find optimal yield allocations
        • Rebalance crank
        • Operation fee calculation
      • Design Goals
      • Security
      • Dynamic Vaults Whitepaper
      • Dynamic Vaults Community Explainers
      • Affiliate Program for Dynamic Vault
        • Become an Affiliate Partner (Dynamic Vaults)
    • Dynamic Bonding Curve (DBC) Overview
      • What is the Dynamic Bonding Curve?
      • Customizable Pool Configuration
      • Bonding Curve Formula
      • DBC Migrator Keeper
    • Meteora’s Anti-Sniper Suite
  • INTEGRATION
    • DLMM Integration
      • DLMM SDK
        • DLMM TypeScript SDK
        • CPI Examples
      • DLMM API
      • Fetching information on locked liquidity in a DLMM
    • Dynamic AMM Pool Integration
      • Dynamic AMM SDK
        • Dynamic AMM TypeScript SDK
        • CPI Examples
      • Dynamic AMM API
        • Pool Info
        • Pool State
      • Setting Pool and Fee Config for Dynamic AMM Pools
      • Create Dynamic Pool with Timestamp/Slot Activation
      • Dynamic AMM - Farm Integration
    • DAMM v2 Integration
      • DAMM v2 SDK
        • DAMM v2 TypeScript SDK
        • DAMM v2 Rust SDK
      • Setting Pool and Fee Config for DAMM v2
      • Technical FAQ
    • Memecoin Pool Integration
      • Memecoin Pool v2 Integration
        • Setting Pool and Fee Config for Memecoin Pool v2
      • Memecoin Pool v1 Integration
        • TypeScript Code Examples
        • CPI Examples
        • Setting Pool and Fee Config for Memecoin Pool v1
        • Track permanently-locked liquidity in Memecoin Pool v1
        • Track Protocol Fee from swaps in Memecoin Pool v1
    • Stake2Earn Pool Integration
    • Dynamic Vault Integration
      • Using TypeScript-Client
      • Using Rust-Client
      • Using CPI
      • Vault API
        • Vault Info
        • Vault State
      • Vault Developer Resources
    • Alpha Vault Integration
      • Alpha Vault TypeScript SDK
      • Alpha Vault without Whitelist Setup
      • Alpha Vault with Whitelist Setup
    • Dynamic Bonding Curve (DBC) Integration
      • DBC SDK
        • DBC TypeScript SDK
        • DBC Rust SDK
      • DBC Fee Scheduler Formula
      • Program Repo
      • Technical FAQ
  • TOKEN LAUNCH POOLS
    • Steps to Create a Pool for a Token Launch
      • Create: DLMM Launch Pool
      • Create: Dynamic AMM Pool
      • Create: Memecoin Pool v1
      • Create: Stake2Earn Pool
      • Create: Pools with Alpha Vault
        • Create: DLMM Launch Pool with Alpha Vault
        • Create: Dynamic AMM Pool with Alpha Vault
        • Create: Memecoin Pool with Alpha Vault
        • Create: Stake2Earn Pool with Alpha Vault
    • Anti-Sniper Fee Suite for a Token Launch
  • Resources
    • Audits
    • Meteora Program IDs
    • Meteora APIs
    • Devnet Testing
    • Community Data Dashboards & Tools
    • Meteora Brand Assets
    • THE MASSIVE METEORA STIMULUS PACKAGE
      • Overview
      • 1. Dynamic Liquidity Market Maker (DLMM)
      • 2. Formation Of An LP Army DAO
      • 3. The 10% Stimulus Proposal
  • USER FAQ
    • Getting Started LPing
      • Supported Wallets
      • Prepare SOL
      • SOL required for Rent
      • What is Wrapped SOL?
      • What is an AMM?
      • What does it mean to provide liquidity?
      • How to swap to the tokens required for adding liquidity to a pool
      • How to quickly check if a token has any risks
      • Viewing your transaction history
      • My wallet has been compromised. What should I do?
    • Differences between DLMM and Dynamic Pools
    • DLMM FAQ
    • Dynamic AMM FAQ
      • How is the pool price of the token calculated in a Dynamic AMM?
      • What is a Meteora LP token?
      • How do I see fees earned on a Dynamic AMM Pool?
      • How to track your earnings for a Dynamic Pool?
      • What is Virtual Price in a Dynamic Pool?
      • How do LP tokens, fees, and virtual price work for Dynamic Pools?
      • Why must I add liquidity in non-stable Dynamic Pools using a 50:50 value ratio?
      • What is AMP in a Dynamic Pool with stable coins?
      • Why is the USDT-USDC pool not 1:1 in ratio of assets?
      • Can I create an LST, FX, or Multi-token pool using the Dynamic Pool creation tool?
    • Alpha Vault FAQ
    • Why is the token sometimes not picked up and tradable on Jupiter?
    • How do I create a new farm?
    • Video Tutorials to Get Started
      • LP Army Boot Camp
      • DLMM Strategy Sessions / Jam Sessions
  • Security and Risks
    • Risk of Impermanent Loss (IL)
    • Risk of depositing into an imbalanced pool / pool with price out of sync
    • Smart contract risk
    • Risk of a stablecoin depeg
    • Operational risk for dynamic vaults and pools
    • Lending risk for dynamic vaults and pools
  • legal
    • Terms of Service
    • Stake2Earn Terms of Service
Powered by GitBook
On this page
  • Summary
  • Getting Started
  • For Creating a Memecoin Pool with Fee Scheduler - Using TypeScript SDK
  • For Creating a Stake2Earn Vault - Using Bun Scripts
  • API
  • 1. Install dependencies and initialize AmmImpl instance
  • 1.1 Install dependencies
  • 1.2 Initialize AmmImpl instance
  • 2. Fee Schedule Setup: Choose a suitable Pool and Fee Config
  • 2.1 Public Pool Config List
  • 2.2 Default Pool Config used by Meteora Frontend
  • 2.3 New Custom Pool Config and Fee Curve for Integrators / Launchpads
  • 2.4 Custom Fee Curve for a Specific Pool
  • 3. Create a Memecoin Pool with Stake2Earn Vault
  • Important Reminder:
  • 3.1 Using TypeScript SDK
  • 3.2 Using Bun Scripts
  • Dependencies
  • Important Considerations
  • Stake2Earn staking rewards distribution start time
  • Difference between locking liquidity via Stake2Earn vs directly locking liquidity in the Memecoin Pool
  • How to find the Stake2Earn vault address and a user wallet's unique personal Stake Escrow address?
  • Other Considerations
  1. TOKEN LAUNCH POOLS
  2. Steps to Create a Pool for a Token Launch

Create: Stake2Earn Pool

PreviousCreate: Memecoin Pool v1NextCreate: Pools with Alpha Vault

Last updated 25 days ago

Summary

are Dynamic AMM Memecoin Pools that are launched with a Stake2Earn Vault. In this page, we provide the code examples that can be used to create a Stake2Earn Pool.

  • Memecoin Pool: A Dynamic AMM Pool created with a fee scheduler and with initial liquidity perma-locked.

  • Stake2Earn Vault: Stake-to-earn farming mechanism and vault where top stakers can earn a share of fees from the locked liquidity.

  • Stake2Earn Pool: A Memecoin Pool with a Stake2Earn Vault.

Getting Started

For Creating a Memecoin Pool with Fee Scheduler - Using TypeScript SDK

  • Dynamic AMM SDK:

  • Stake2Earn Vault SDK:

  • Dynamic AMM Program ID: Eo7WjKq67rjJQSZxS6z3YkapzY3eMj6Xy8X5EQVn5UaB

  • Stake2Earn Vault Program ID: FEESngU3neckdwib9X3KWqdL7Mjmqk9XNp3uh5JbP4KP

  • Devnet:

For Creating a Stake2Earn Vault - Using Bun Scripts

  • Clone repo:

  • Config list to reference:

  • Readme:

API

1. Install dependencies and initialize AmmImpl instance

1.1 Install dependencies

# NPM
npm i @meteora-ag/dynamic-amm-sdk @coral-xyz/anchor @solana/web3.js @solana/spl-token
# YARN
yarn add @meteora-ag/dynamic-amm-sdk @coral-xyz/anchor @solana/web3.js @solana/spl-token
# Or, use any package manager of your choice.

1.2 Initialize AmmImpl instance

import AmmImpl, { MAINNET_POOL } from '@meteora-ag/dynamic-amm-sdk';
import { Connection, Keypair, PublicKey } from '@solana/web3.js';
import { AnchorProvider, Wallet } from '@coral-xyz/anchor';

// Connection, Wallet, and AnchorProvider to interact with the network
const mainnetConnection = new Connection('https://api.mainnet-beta.solana.com');
const mockWallet = new Wallet(new Keypair());
const provider = new AnchorProvider(mainnetConnection, mockWallet, {
  commitment: 'confirmed',
});
// Alternatively, to use Solana Wallet Adapter

// Create single instance
const constantProductPool = await AmmImpl.create(mainnetConnection, MAINNET_POOL.USDC_SOL);
const stablePool = await AmmImpl.create(mainnetConnection, MAINNET_POOL.USDT_USDC);
// Or with any other pool address, refer to the pool creation section below
const pool = await AmmImpl.create(mainnetConnection, new PublicKey('...'));

// If you need to create multiple, can consider using `createMultiple`
const pools = [MAINNET_POOL.USDC_SOL, MAINNET_POOL.USDT_USDC];
const [constantProductPool, stablePool] = await AmmImpl.createMultiple(mainnetConnection, pools);

2. Fee Schedule Setup: Choose a suitable Pool and Fee Config

If you want to create an Alpha Vault along with your new pool, you also need to find a pool_config_key that is mapped to a vault_config_key that meets your requirements.

If none of the pool_config_key in the list meet your requirements, please reach out to Meteora for a custom pool config key.

2.1 Public Pool Config List

    • Using this endpoint, integrators can input the config pubkey, and it will return an array of fee update timings for the config, if there's any.

    • Integrators may choose a pool_config_key with a fee curve that suits your integration.

  • If there is no existing config in the list that fits your project's requirement, a new config needs to be created.

  • Only the Meteora team can create a new config to add it to the preset pool config list.

2.2 Default Pool Config used by Meteora Frontend

  • By default, Meteora's frontend is currently using this pool config key for Memecoin Pool creation: FiENCCbPi3rFh5pW2AJ59HC53yM32eLaCjMKxRqanKFJ

  • For the FiENCCbPi3rFh5pW2AJ59HC53yM32eLaCjMKxRqanKFJ pool config, it doesn't allow creation of any Alpha Vault, therefore it's field vault_config_key is 1111111...

2.3 New Custom Pool Config and Fee Curve for Integrators / Launchpads

Custom Pool Config Key: Integrators such as launchpads or other partners may need to use their own unique custom pool config key, if they want custom pool_creator_authority to prevent front-running of the token launch pool.

NOTE:

  • New dedicated config keys can only be created by Meteora. Please reach out to us if this is required.

  • The pool_creator_authority doesn't work with program address. It's not a program whitelist, it needs to be a PDA (program derived address) or normal account.

Custom Fee Curve: If you are an integrator, Meteora can also apply a custom fee curve/schedule for your pools, but we will need to create a dedicated config key for your team, where pool_creator_authority is linked to your signer wallet for pool creation. You would need to send us your signer wallet that would be used to deploy the pools.

NOTE:

  • Even with a dedicated config key for your team, Meteora would need to customize the fee curve/schedule for you. You can't do it on your own.

  • Custom Pool Config and Fee Curve is used by integrators such as Moonshot by DEX Screener.

2.4 Custom Fee Curve for a Specific Pool

If required, Meteora can set a custom fee curve for a single, specific pool. This would override the fee curve used by the pool's config key, doesn't matter which config key is used.

3. Create a Memecoin Pool with Stake2Earn Vault

Important Reminder:

You are recommended to configure your Stake2Earn staking rewards distribution start time (fee claim start time) to be approximately 48 hours after launch. This allows more time for total fee rewards to accumulate from trading activity in the memecoin pool. A bigger total fee reward would help make your Stake2Earn Vault look more appealing to potential stakers.

3.1 Using TypeScript SDK

This code example includes the steps to:

  • Mint a token

  • Create dynamic vault and pool

  • Create Stake2Earn Vault

  • Lock user's LP to Stake2Earn Vault

import AmmImpl from "@mercurial-finance/dynamic-amm-sdk";
import { NATIVE_MINT } from "@solana/spl-token";
import { Connection, Keypair, PublicKey } from "@solana/web3.js";
import BN from "bn.js";
import { StakeForFee } from "../stake-for-fee";
import {
  DEFAULT_KEYPAIR_PATH,
  DEVNET_URL,
  handleSendTransaction,
  initializeMintAndMint,
  loadKeypairFromFile,
} from "./utils";
import { createFeeVault, createPool, lockLiquidityToFeeVault } from "./actions";
import { U64_MAX } from "../stake-for-fee/constants";

const connection = new Connection(DEVNET_URL);
const poolConfigKey = new PublicKey(
  "BdfD7rrTZEWmf8UbEBPVpvM3wUqyrR8swjAy5SNT8gJ2"
);
const mintADecimal = 9;
const mintANativeAmountMultiplier = 10 ** mintADecimal;
const mintAmount = 10_000;
const stakeFarmAmount = 1_000;

async function createPoolAndInteractWithFeeVaultExample() {
  const keypair = loadKeypairFromFile(DEFAULT_KEYPAIR_PATH);
  console.log(`Wallet ${keypair.publicKey} connected`);

  const amountAToMint =
    BigInt(mintAmount) * BigInt(mintANativeAmountMultiplier);
  const amountAToDeposit =
    BigInt(mintAmount - stakeFarmAmount) * BigInt(mintANativeAmountMultiplier); // 1,000 reserve to stake
  const amountB = BigInt(1_000_000);

  console.log("Create mint A");
  const mintA = await initializeMintAndMint(
    connection,
    keypair,
    keypair,
    mintADecimal,
    amountAToMint
  );

  console.log("1. Create dynamic vaults and pool");
  const poolKey = await createPool(
    keypair,
    mintA,
    NATIVE_MINT,
    new BN(amountAToDeposit.toString()),
    new BN(amountB.toString()),
    poolConfigKey
  );

  const pool = await AmmImpl.create(connection, poolKey);

  console.log("2. Create fee vault");
  const currentSlot = await connection.getSlot("confirmed");
  const currentOnchainTimestamp = await connection.getBlockTime(currentSlot);
  // Number of top stakers
  const topListLength = 10;
  // Number of seconds to withdraw unstaked token
  const unstakeLockDuration = new BN(3600 * 24);
  // Number of seconds for the swap fee fully dripped to stakers
  const secondsToFullUnlock = new BN(3600 * 24 * 7);
  // Timestamp to start fee distribution / drip to stakers
  const startFeeDistributeTimestamp = new BN(currentOnchainTimestamp + 10); // delay 10 seconds to be able to claim

  await createFeeVault(
    poolKey,
    pool.poolState.tokenAMint,
    keypair,
    topListLength,
    unstakeLockDuration,
    secondsToFullUnlock,
    startFeeDistributeTimestamp
  );

  console.log("3. Lock user LP for fee vault");
  await lockLiquidityToFeeVault(poolKey, pool, keypair, 10_000); // 10_000 means 100% of LP is being lock

  console.log("4. Connect to the fee vault");
  const feeVault = await StakeForFee.create(connection, poolKey);

  console.log("5. Stake amount");
  const stakeAmount = new BN(
    (BigInt(stakeFarmAmount) * BigInt(mintANativeAmountMultiplier)).toString()
  ); // 1,000 stake token (make sure you have enough balance in your wallet)
  const stakeTx = await feeVault.stake(stakeAmount, keypair.publicKey);
  const stakeSignature = await handleSendTransaction(
    connection,
    stakeTx,
    keypair
  );
  console.log("Stake Signature", stakeSignature);

  console.log("6. Get stake balance");
  await feeVault.refreshStates();
  const userEscrow = await feeVault.getUserStakeAndClaimBalance(
    keypair.publicKey
  );
  const stakeBalance =
    userEscrow.stakeEscrow.stakeAmount.toNumber() /
    10 ** feeVault.accountStates.tokenAMint.decimals;
  console.log("Stake Balance", stakeBalance);
  const claimableFeeA =
    (userEscrow.unclaimFee.feeA.toNumber() || 0) /
    10 ** feeVault.accountStates.tokenAMint.decimals;
  console.log("Claimable Fee A", claimableFeeA);
  const claimableFeeB =
    (userEscrow.unclaimFee.feeB.toNumber() || 0) /
    10 ** feeVault.accountStates.tokenBMint.decimals;
  console.log("Claimable Fee B", claimableFeeB);

  console.log("7. Claim fee");
  const claimFeeTx = await feeVault.claimFee(
    keypair.publicKey,
    new BN(U64_MAX)
  );
  for (const [index, tx] of claimFeeTx.entries()) {
    const signature = await handleSendTransaction(connection, tx, keypair);
    console.log(`Claim Fee Signature ${index + 1}`, signature);
  }

  console.log("8. Unstake");
  const unstakeKeyPair = new Keypair();
  const unstakeTx = await feeVault.unstake(
    userEscrow.stakeEscrow.stakeAmount,
    unstakeKeyPair.publicKey,
    keypair.publicKey
  );
  const unstakeSignature = await handleSendTransaction(connection, unstakeTx, [
    unstakeKeyPair,
    keypair,
  ]);
  console.log("Unstake Signature", unstakeSignature);

  console.log("9. Cancel unstaked");
  const cancelUnstake = await feeVault.cancelUnstake(
    unstakeKeyPair.publicKey,
    keypair.publicKey
  );
  const cancelUnstakeSignature = await handleSendTransaction(
    connection,
    cancelUnstake,
    keypair
  );
  console.log("Cancel Unstake Signature", cancelUnstakeSignature);

  // ⚠️ This only works after unstake period is over
  console.log("10. Withdraw unstake");
  const withdrawUnstake = await feeVault.withdraw(
    unstakeKeyPair.publicKey,
    keypair.publicKey
  );
  const withdrawUnstakeSignature = await handleSendTransaction(
    connection,
    withdrawUnstake,
    keypair
  );
  console.log("Withdraw Unstake Signature", withdrawUnstakeSignature);
}

createPoolAndInteractWithFeeVaultExample()
  .then(() => console.log("Done"))
  .catch(console.error);

3.2 Using Bun Scripts

Alternatively, the following bun script examples can be used to initialize a Stake2Earn Vault for the Memecoin Pool you created on Meteora.

First, make sure you create the token mint and the Memecoin Pool. After that, you need to lock the liquidity, before creating the Stake2Earn Vault for the Memecoin Pool. The addresses in the allocations should contain the feeFarm (Stake2Earn Vault) address.

Dependencies

  • Run the script with the config file which is set with your preferred parameters

Lock Liquidity

Run:

bun run src/lock_liquidity_for_m3m3.ts --config ./config/create_m3m3_farm.json

Create the Stake2Earn Vault

Run:

bun run src/create_m3m3_farm.ts --config ./config/create_m3m3_farm.json

Important Considerations

Stake2Earn staking rewards distribution start time

  • You are recommended to configure your Stake2Earn staking rewards distribution start time (fee claim start time) to be approximately 48 hours after launch. This allows more time for total fee rewards to accumulate from trading activity in the memecoin pool. A bigger total fee reward would help make your Stake2Earn Vault look more appealing to potential stakers.

Difference between locking liquidity via Stake2Earn vs directly locking liquidity in the Memecoin Pool

  • User lock and Stake2Earn lock use the same lock mechanism on a Dynamic AMM / Memecoin Pool. But users and Stake2Eearn vaults have their own personal lock escrow account for the pool.

  • When a user permanently locks liquidity directly on the Memecoin Pool page, the user is locking the LP token to their own personal escrow account for the pool. Fees from this locked liquidity go to the user's wallet.

  • However, when a user locks via the Stake2Earn creation process, the user is locking the LP to their unique Stake2Earn Vault stake escrow account. Therefore, fees from this locked liquidity go to the Stake2Earn Vault, which then distributes fees to the top stakers.

How to find the Stake2Earn vault address and a user wallet's unique personal Stake Escrow address?

  • Click "Open explorer" and on the explorer page search for Vault and/or Stake Escrow fields to find the respective addresses.

Other Considerations

  • If you plan to use a multisig on the Meteora website, please make sure it is the SquadsX multisig, as that is the only type supported on Meteora website. Otherwise, you can't manage liquidity through the website.

Dynamic AMM API endpoints:

Stake2Earn Mainnet API endpoint:

API endpoint to get Stake2Earn vault info from pool address:

Stake2Earn Devnet API endpoint:

Dynamic AMM SDK:

What fee parameters to choose depends on your project's needs. You will need to look at the and choose a suitable pool_config_key with your preferred fee parameters.

Pool config list:

Devnet API: You can also get the list of config keys from devnet API

API endpoint to return the associated fee curve for each existing config:

Note: For more information about setting Pool and Fee Config for Memecoin Pools, please read .

After you have selected your preferred pool config key, use this example to to create a Memecoin Pool with Stake2Earn Vault:

Install Bun: You'll also need to run the scripts. Install it via . Then install the dependencies by running the command bun install

Clone repo:

Select an example config from the list to reference and change the parameters inside according to your needs:

Use a wallet simulator (e.g. ) and paste the user's wallet address. Try to stake or unstake tokens in a Stake2Earn Vault.

Stake2Earn Pools
https://github.com/mercurial-finance/mercurial-dynamic-amm-sdk
https://github.com/MeteoraAg/stake-for-fee-sdk
https://devnet.meteora.ag/
https://github.com/MeteoraAg/meteora-pool-setup
https://github.com/MeteoraAg/meteora-pool-setup/tree/main/config
https://github.com/MeteoraAg/meteora-pool-setup/blob/main/README.md
https://amm-v2.meteora.ag/swagger-ui/
https://stake-for-fee-api.meteora.ag/swagger-ui/
https://stake-for-fee-api.meteora.ag/swagger-ui/#/vault/filter_vaults
https://devnet.stake-for-fee-api.meteora.ag/swagger-ui/
https://github.com/mercurial-finance/mercurial-dynamic-amm-sdk
pool config list
https://amm-v2.meteora.ag/swagger-ui/#/pools/get_all_pool_configs
https://devnet-amm-v2.meteora.ag/pool-configs
https://amm-v2.meteora.ag/swagger-ui/#/fee_config/get_config_associated_fee_configs
here
https://github.com/MeteoraAg/stake-for-fee-sdk/blob/main/ts-client/src/examples/index.ts
bun
bun installation
https://github.com/MeteoraAg/meteora-pool-setup
https://github.com/MeteoraAg/meteora-pool-setup/tree/main/config
Sherlock extension