testsetset
Version:
A Typescript SDK for interacting with the Dynamic Bonding Curve on Meteora.
1,443 lines (1,431 loc) • 604 kB
JavaScript
// src/services/migration.ts
import {
ComputeBudgetProgram,
Keypair,
SystemProgram as SystemProgram3,
SYSVAR_RENT_PUBKEY as SYSVAR_RENT_PUBKEY2
} from "@solana/web3.js";
// src/types.ts
var ActivationType = /* @__PURE__ */ ((ActivationType3) => {
ActivationType3[ActivationType3["Slot"] = 0] = "Slot";
ActivationType3[ActivationType3["Timestamp"] = 1] = "Timestamp";
return ActivationType3;
})(ActivationType || {});
var TokenType = /* @__PURE__ */ ((TokenType2) => {
TokenType2[TokenType2["SPL"] = 0] = "SPL";
TokenType2[TokenType2["Token2022"] = 1] = "Token2022";
return TokenType2;
})(TokenType || {});
var CollectFeeMode = /* @__PURE__ */ ((CollectFeeMode4) => {
CollectFeeMode4[CollectFeeMode4["QuoteToken"] = 0] = "QuoteToken";
CollectFeeMode4[CollectFeeMode4["OutputToken"] = 1] = "OutputToken";
return CollectFeeMode4;
})(CollectFeeMode || {});
var DammV2DynamicFeeMode = /* @__PURE__ */ ((DammV2DynamicFeeMode3) => {
DammV2DynamicFeeMode3[DammV2DynamicFeeMode3["Disabled"] = 0] = "Disabled";
DammV2DynamicFeeMode3[DammV2DynamicFeeMode3["Enabled"] = 1] = "Enabled";
return DammV2DynamicFeeMode3;
})(DammV2DynamicFeeMode || {});
var MigrationOption = /* @__PURE__ */ ((MigrationOption2) => {
MigrationOption2[MigrationOption2["MET_DAMM"] = 0] = "MET_DAMM";
MigrationOption2[MigrationOption2["MET_DAMM_V2"] = 1] = "MET_DAMM_V2";
return MigrationOption2;
})(MigrationOption || {});
var BaseFeeMode = /* @__PURE__ */ ((BaseFeeMode2) => {
BaseFeeMode2[BaseFeeMode2["FeeSchedulerLinear"] = 0] = "FeeSchedulerLinear";
BaseFeeMode2[BaseFeeMode2["FeeSchedulerExponential"] = 1] = "FeeSchedulerExponential";
BaseFeeMode2[BaseFeeMode2["RateLimiter"] = 2] = "RateLimiter";
return BaseFeeMode2;
})(BaseFeeMode || {});
var MigrationFeeOption = /* @__PURE__ */ ((MigrationFeeOption2) => {
MigrationFeeOption2[MigrationFeeOption2["FixedBps25"] = 0] = "FixedBps25";
MigrationFeeOption2[MigrationFeeOption2["FixedBps30"] = 1] = "FixedBps30";
MigrationFeeOption2[MigrationFeeOption2["FixedBps100"] = 2] = "FixedBps100";
MigrationFeeOption2[MigrationFeeOption2["FixedBps200"] = 3] = "FixedBps200";
MigrationFeeOption2[MigrationFeeOption2["FixedBps400"] = 4] = "FixedBps400";
MigrationFeeOption2[MigrationFeeOption2["FixedBps600"] = 5] = "FixedBps600";
MigrationFeeOption2[MigrationFeeOption2["Customizable"] = 6] = "Customizable";
return MigrationFeeOption2;
})(MigrationFeeOption || {});
var TokenDecimal = /* @__PURE__ */ ((TokenDecimal3) => {
TokenDecimal3[TokenDecimal3["SIX"] = 6] = "SIX";
TokenDecimal3[TokenDecimal3["SEVEN"] = 7] = "SEVEN";
TokenDecimal3[TokenDecimal3["EIGHT"] = 8] = "EIGHT";
TokenDecimal3[TokenDecimal3["NINE"] = 9] = "NINE";
return TokenDecimal3;
})(TokenDecimal || {});
var TradeDirection = /* @__PURE__ */ ((TradeDirection3) => {
TradeDirection3[TradeDirection3["BaseToQuote"] = 0] = "BaseToQuote";
TradeDirection3[TradeDirection3["QuoteToBase"] = 1] = "QuoteToBase";
return TradeDirection3;
})(TradeDirection || {});
var Rounding = /* @__PURE__ */ ((Rounding2) => {
Rounding2[Rounding2["Up"] = 0] = "Up";
Rounding2[Rounding2["Down"] = 1] = "Down";
return Rounding2;
})(Rounding || {});
var TokenUpdateAuthorityOption = /* @__PURE__ */ ((TokenUpdateAuthorityOption2) => {
TokenUpdateAuthorityOption2[TokenUpdateAuthorityOption2["CreatorUpdateAuthority"] = 0] = "CreatorUpdateAuthority";
TokenUpdateAuthorityOption2[TokenUpdateAuthorityOption2["Immutable"] = 1] = "Immutable";
TokenUpdateAuthorityOption2[TokenUpdateAuthorityOption2["PartnerUpdateAuthority"] = 2] = "PartnerUpdateAuthority";
TokenUpdateAuthorityOption2[TokenUpdateAuthorityOption2["CreatorUpdateAndMintAuthority"] = 3] = "CreatorUpdateAndMintAuthority";
TokenUpdateAuthorityOption2[TokenUpdateAuthorityOption2["PartnerUpdateAndMintAuthority"] = 4] = "PartnerUpdateAndMintAuthority";
return TokenUpdateAuthorityOption2;
})(TokenUpdateAuthorityOption || {});
var SwapMode = /* @__PURE__ */ ((SwapMode2) => {
SwapMode2[SwapMode2["ExactIn"] = 0] = "ExactIn";
SwapMode2[SwapMode2["PartialFill"] = 1] = "PartialFill";
SwapMode2[SwapMode2["ExactOut"] = 2] = "ExactOut";
return SwapMode2;
})(SwapMode || {});
// src/constants.ts
import BN from "bn.js";
import { PublicKey } from "@solana/web3.js";
var OFFSET = 64;
var U128_MAX = new BN("340282366920938463463374607431768211455");
var U64_MAX = new BN("18446744073709551615");
var U16_MAX = 65535;
var MIN_SQRT_PRICE = new BN("4295048016");
var MAX_SQRT_PRICE = new BN("79226673521066979257578248091");
var RESOLUTION = 64;
var ONE_Q64 = new BN(1).shln(RESOLUTION);
var FEE_DENOMINATOR = 1e9;
var MAX_FEE_BPS = 9900;
var MIN_FEE_BPS = 1;
var MIN_FEE_NUMERATOR = 1e5;
var MAX_FEE_NUMERATOR = 99e7;
var BASIS_POINT_MAX = 1e4;
var MAX_CURVE_POINT = 16;
var PARTNER_SURPLUS_SHARE = 80;
var SWAP_BUFFER_PERCENTAGE = 25;
var MAX_MIGRATION_FEE_PERCENTAGE = 50;
var MAX_CREATOR_MIGRATION_FEE_PERCENTAGE = 100;
var MAX_SWALLOW_PERCENTAGE = 20;
var MAX_RATE_LIMITER_DURATION_IN_SECONDS = 43200;
var MAX_RATE_LIMITER_DURATION_IN_SLOTS = 108e3;
var SLOT_DURATION = 400;
var TIMESTAMP_DURATION = 1e3;
var DYNAMIC_BONDING_CURVE_PROGRAM_ID = new PublicKey(
"dbcij3LWUppWqq96dh6gJWwBifmcGfLSB5D4DuSMaqN"
);
var METAPLEX_PROGRAM_ID = new PublicKey(
"metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s"
);
var DAMM_V1_PROGRAM_ID = new PublicKey(
"Eo7WjKq67rjJQSZxS6z3YkapzY3eMj6Xy8X5EQVn5UaB"
);
var DAMM_V2_PROGRAM_ID = new PublicKey(
"cpamdpZCGKUy5JxQXB4dcpGPiikHawvSWAd6mEn1sGG"
);
var VAULT_PROGRAM_ID = new PublicKey(
"24Uqj9JCLxUeoC3hGfh5W3s9FM9uCHDS2SG3LYwBpyTi"
);
var LOCKER_PROGRAM_ID = new PublicKey(
"LocpQgucEQHbqNABEYvBvwoxCPsSbG91A1QaQhQQqjn"
);
var BASE_ADDRESS = new PublicKey(
"HWzXGcGHy4tcpYfaRDCyLNzXqBTv3E6BttpCH2vJxArv"
);
var DYNAMIC_FEE_FILTER_PERIOD_DEFAULT = 10;
var DYNAMIC_FEE_DECAY_PERIOD_DEFAULT = 120;
var DYNAMIC_FEE_REDUCTION_FACTOR_DEFAULT = 5e3;
var MAX_DYNAMIC_FEE_PERCENTAGE = 20;
var DYNAMIC_FEE_SCALING_FACTOR = new BN(1e11);
var DYNAMIC_FEE_ROUNDING_OFFSET = new BN(99999999999);
var BIN_STEP_BPS_DEFAULT = 1;
var BIN_STEP_BPS_U128_DEFAULT = new BN("1844674407370955");
var MAX_PRICE_CHANGE_BPS_DEFAULT = 1500;
var MIN_MIGRATED_POOL_FEE_BPS = 10;
var MAX_MIGRATED_POOL_FEE_BPS = 1e3;
var DAMM_V1_MIGRATION_FEE_ADDRESS = [
new PublicKey("8f848CEy8eY6PhJ3VcemtBDzPPSD4Vq7aJczLZ3o8MmX"),
// FixedBps25
new PublicKey("HBxB8Lf14Yj8pqeJ8C4qDb5ryHL7xwpuykz31BLNYr7S"),
// FixedBps30
new PublicKey("7v5vBdUQHTNeqk1HnduiXcgbvCyVEZ612HLmYkQoAkik"),
// FixedBps100
new PublicKey("EkvP7d5yKxovj884d2DwmBQbrHUWRLGK6bympzrkXGja"),
// FixedBps200
new PublicKey("9EZYAJrcqNWNQzP2trzZesP7XKMHA1jEomHzbRsdX8R2"),
// FixedBps400
new PublicKey("8cdKo87jZU2R12KY1BUjjRPwyjgdNjLGqSGQyrDshhud")
// FixedBps600
];
var DAMM_V2_MIGRATION_FEE_ADDRESS = [
new PublicKey("7F6dnUcRuyM2TwR8myT1dYypFXpPSxqwKNSFNkxyNESd"),
// FixedBps25
new PublicKey("2nHK1kju6XjphBLbNxpM5XRGFj7p9U8vvNzyZiha1z6k"),
// FixedBps30
new PublicKey("Hv8Lmzmnju6m7kcokVKvwqz7QPmdX9XfKjJsXz8RXcjp"),
// FixedBps100
new PublicKey("2c4cYd4reUYVRAB9kUUkrq55VPyy2FNQ3FDL4o12JXmq"),
// FixedBps200
new PublicKey("AkmQWebAwFvWk55wBoCr5D62C6VVDTzi84NJuD9H7cFD"),
// FixedBps400
new PublicKey("DbCRBj8McvPYHJG1ukj8RE15h2dCNUdTAESG49XpQ44u"),
// FixedBps600
new PublicKey("A8gMrEPJkacWkcb3DGwtJwTe16HktSEfvwtuDh2MCtck")
// Customizable
];
// src/helpers/common.ts
import BN6 from "bn.js";
import Decimal2 from "decimal.js";
// src/math/curve.ts
import BN4 from "bn.js";
// src/math/safeMath.ts
import BN2 from "bn.js";
var SafeMath = class {
/**
* Safe addition
* @param a First number
* @param b Second number
* @returns Sum of a and b
*/
static add(a, b) {
return a.add(b);
}
/**
* Safe subtraction
* @param a First number
* @param b Second number
* @returns Difference of a and b
* @throws Error if b > a
*/
static sub(a, b) {
if (b.gt(a)) {
throw new Error("SafeMath: subtraction overflow");
}
return a.sub(b);
}
/**
* Safe multiplication
* @param a First number
* @param b Second number
* @returns Product of a and b
*/
static mul(a, b) {
return a.mul(b);
}
/**
* Safe division
* @param a First number
* @param b Second number
* @returns Quotient of a and b
* @throws Error if b is zero
*/
static div(a, b) {
if (b.isZero()) {
throw new Error("SafeMath: division by zero");
}
return a.div(b);
}
/**
* Safe modulo
* @param a First number
* @param b Second number
* @returns Remainder of a divided by b
* @throws Error if b is zero
*/
static mod(a, b) {
if (b.isZero()) {
throw new Error("SafeMath: modulo by zero");
}
return a.mod(b);
}
/**
* Safe left shift
* @param a Number to shift
* @param b Number of bits to shift
* @returns a << b
*/
static shl(a, b) {
return a.shln(b);
}
/**
* Safe right shift
* @param a Number to shift
* @param b Number of bits to shift
* @returns a >> b
*/
static shr(a, b) {
return a.shrn(b);
}
};
function pow(base, exponent, scaling = true) {
const ONE = new BN2(1).shln(RESOLUTION);
if (exponent.isZero()) return ONE;
if (base.isZero()) return new BN2(0);
if (base.eq(ONE)) return ONE;
const isNegative = exponent.isNeg();
const absExponent = isNegative ? exponent.neg() : exponent;
let result = ONE;
let currentBase = base;
let exp = absExponent;
while (!exp.isZero()) {
if (exp.and(new BN2(1)).eq(new BN2(1))) {
result = SafeMath.div(SafeMath.mul(result, currentBase), ONE);
}
currentBase = SafeMath.div(SafeMath.mul(currentBase, currentBase), ONE);
exp = exp.shrn(1);
}
if (isNegative) {
result = SafeMath.div(ONE.mul(ONE), result);
}
return scaling ? result : SafeMath.div(result, ONE);
}
// src/math/utilsMath.ts
import BN3 from "bn.js";
function mulDiv(x, y, denominator, rounding) {
if (denominator.isZero()) {
throw new Error("MulDiv: division by zero");
}
if (denominator.eq(new BN3(1)) || x.isZero() || y.isZero()) {
return x.mul(y);
}
const prod = x.mul(y);
if (rounding === 0 /* Up */) {
const numerator = prod.add(denominator.sub(new BN3(1)));
return numerator.div(denominator);
} else {
return prod.div(denominator);
}
}
function mulShr(x, y, offset) {
if (offset === 0 || x.isZero() || y.isZero()) {
return x.mul(y);
}
const prod = SafeMath.mul(x, y);
return SafeMath.shr(prod, offset);
}
function sqrt(value) {
if (value.isZero()) {
return new BN3(0);
}
if (value.eq(new BN3(1))) {
return new BN3(1);
}
let x = value;
let y = value.add(new BN3(1)).div(new BN3(2));
while (y.lt(x)) {
x = y;
y = x.add(value.div(x)).div(new BN3(2));
}
return x;
}
// src/math/curve.ts
function getInitialLiquidityFromDeltaQuote(quoteAmount, sqrtMinPrice, sqrtPrice) {
const priceDelta = SafeMath.sub(sqrtPrice, sqrtMinPrice);
const quoteAmountShifted = SafeMath.shl(quoteAmount, 128);
return SafeMath.div(quoteAmountShifted, priceDelta);
}
function getInitialLiquidityFromDeltaBase(baseAmount, sqrtMaxPrice, sqrtPrice) {
const priceDelta = SafeMath.sub(sqrtMaxPrice, sqrtPrice);
const prod = SafeMath.mul(SafeMath.mul(baseAmount, sqrtPrice), sqrtMaxPrice);
const liquidity = SafeMath.div(prod, priceDelta);
return liquidity;
}
function getDeltaAmountBaseUnsigned(lowerSqrtPrice, upperSqrtPrice, liquidity, round) {
const result = getDeltaAmountBaseUnsigned256(
lowerSqrtPrice,
upperSqrtPrice,
liquidity,
round
);
return result;
}
function getDeltaAmountBaseUnsigned256(lowerSqrtPrice, upperSqrtPrice, liquidity, round) {
const result = getDeltaAmountBaseUnsignedUnchecked(
lowerSqrtPrice,
upperSqrtPrice,
liquidity,
round
);
return result;
}
function getDeltaAmountBaseUnsignedUnchecked(lowerSqrtPrice, upperSqrtPrice, liquidity, round) {
const numerator1 = liquidity;
const numerator2 = SafeMath.sub(upperSqrtPrice, lowerSqrtPrice);
const denominator = SafeMath.mul(lowerSqrtPrice, upperSqrtPrice);
if (denominator.isZero()) {
throw new Error("Denominator cannot be zero");
}
const result = mulDiv(numerator1, numerator2, denominator, round);
return result;
}
function getDeltaAmountQuoteUnsigned(lowerSqrtPrice, upperSqrtPrice, liquidity, round) {
const result = getDeltaAmountQuoteUnsigned256(
lowerSqrtPrice,
upperSqrtPrice,
liquidity,
round
);
return result;
}
function getDeltaAmountQuoteUnsigned256(lowerSqrtPrice, upperSqrtPrice, liquidity, round) {
const result = getDeltaAmountQuoteUnsignedUnchecked(
lowerSqrtPrice,
upperSqrtPrice,
liquidity,
round
);
return result;
}
function getDeltaAmountQuoteUnsignedUnchecked(lowerSqrtPrice, upperSqrtPrice, liquidity, round) {
const deltaSqrtPrice = SafeMath.sub(upperSqrtPrice, lowerSqrtPrice);
const prod = SafeMath.mul(liquidity, deltaSqrtPrice);
if (round === 0 /* Up */) {
const denominator = new BN4(1).shln(RESOLUTION * 2);
const numerator = SafeMath.add(
prod,
SafeMath.sub(denominator, new BN4(1))
);
return SafeMath.div(numerator, denominator);
} else {
return SafeMath.shr(prod, RESOLUTION * 2);
}
}
function getNextSqrtPriceFromInput(sqrtPrice, liquidity, amountIn, baseForQuote) {
if (sqrtPrice.isZero()) {
throw new Error("sqrt_price must be greater than 0");
}
if (liquidity.isZero()) {
throw new Error("liquidity must be greater than 0");
}
if (baseForQuote) {
return getNextSqrtPriceFromBaseAmountInRoundingUp(
sqrtPrice,
liquidity,
amountIn
);
} else {
return getNextSqrtPriceFromQuoteAmountInRoundingDown(
sqrtPrice,
liquidity,
amountIn
);
}
}
function getNextSqrtPriceFromOutput(sqrtPrice, liquidity, amountOut, baseForQuote) {
if (sqrtPrice.isZero()) {
throw new Error("sqrt_price must be greater than 0");
}
if (liquidity.isZero()) {
throw new Error("liquidity must be greater than 0");
}
if (baseForQuote) {
return getNextSqrtPriceFromQuoteAmountOutRoundingDown(
sqrtPrice,
liquidity,
amountOut
);
} else {
return getNextSqrtPriceFromBaseAmountOutRoundingUp(
sqrtPrice,
liquidity,
amountOut
);
}
}
function getNextSqrtPriceFromQuoteAmountOutRoundingDown(sqrtPrice, liquidity, amount) {
const qAmount = SafeMath.shl(amount, 128);
const numerator = SafeMath.add(qAmount, SafeMath.sub(liquidity, new BN4(1)));
const quotient = SafeMath.div(numerator, liquidity);
const result = SafeMath.sub(sqrtPrice, quotient);
return result;
}
function getNextSqrtPriceFromBaseAmountOutRoundingUp(sqrtPrice, liquidity, amount) {
if (amount.isZero()) {
return sqrtPrice;
}
const product = SafeMath.mul(amount, sqrtPrice);
const denominator = SafeMath.sub(liquidity, product);
if (denominator.isZero() || denominator.isNeg()) {
throw new Error(
"Invalid denominator: liquidity must be greater than amount * sqrt_price"
);
}
return mulDiv(liquidity, sqrtPrice, denominator, 0 /* Up */);
}
function getNextSqrtPriceFromBaseAmountInRoundingUp(sqrtPrice, liquidity, amount) {
if (amount.isZero()) {
return sqrtPrice;
}
const product = SafeMath.mul(amount, sqrtPrice);
if (product.gt(U128_MAX)) {
const quotient = SafeMath.div(liquidity, sqrtPrice);
const denominator2 = SafeMath.add(quotient, amount);
return SafeMath.div(liquidity, denominator2);
}
const denominator = SafeMath.add(liquidity, product);
return mulDiv(liquidity, sqrtPrice, denominator, 0 /* Up */);
}
function getNextSqrtPriceFromQuoteAmountInRoundingDown(sqrtPrice, liquidity, amount) {
const quotient = SafeMath.div(
SafeMath.shl(amount, RESOLUTION * 2),
liquidity
);
return SafeMath.add(sqrtPrice, quotient);
}
// src/helpers/common.ts
import { PublicKey as PublicKey4 } from "@solana/web3.js";
// src/helpers/utils.ts
import BN5 from "bn.js";
import { PublicKey as PublicKey2 } from "@solana/web3.js";
import { NATIVE_MINT } from "@solana/spl-token";
import Decimal from "decimal.js";
function convertToLamports(amount, tokenDecimal) {
const valueInLamports = new Decimal(amount).mul(
Decimal.pow(10, tokenDecimal)
);
return fromDecimalToBN(valueInLamports);
}
function fromDecimalToBN(value) {
return new BN5(value.floor().toFixed());
}
function createProgramAccountFilter(owner, offset) {
const ownerKey = typeof owner === "string" ? new PublicKey2(owner) : owner;
return [
{
memcmp: {
offset,
bytes: ownerKey.toBase58(),
encoding: "base58"
}
}
];
}
function isNativeSol(mint) {
return mint.toString() === NATIVE_MINT.toString();
}
function isDefaultLockedVesting(lockedVesting) {
return lockedVesting.amountPerPeriod.eqn(0) && lockedVesting.cliffDurationFromMigrationTime.eqn(0) && lockedVesting.frequency.eqn(0) && lockedVesting.numberOfPeriod.eqn(0) && lockedVesting.cliffUnlockAmount.eqn(0);
}
function convertDecimalToBN(value) {
return new BN5(value.floor().toFixed());
}
function bpsToFeeNumerator(bps) {
return new BN5(bps * FEE_DENOMINATOR).divn(BASIS_POINT_MAX);
}
function feeNumeratorToBps(feeNumerator) {
return feeNumerator.muln(BASIS_POINT_MAX).div(new BN5(FEE_DENOMINATOR)).toNumber();
}
// src/helpers/token.ts
import {
PublicKey as PublicKey3,
SystemProgram,
Transaction,
TransactionInstruction
} from "@solana/web3.js";
import {
ASSOCIATED_TOKEN_PROGRAM_ID,
createAssociatedTokenAccountIdempotentInstruction,
createCloseAccountInstruction,
getAccount,
getAssociatedTokenAddressSync,
getMint,
NATIVE_MINT as NATIVE_MINT2,
TOKEN_2022_PROGRAM_ID,
TOKEN_PROGRAM_ID,
TokenAccountNotFoundError,
TokenInvalidAccountOwnerError
} from "@solana/spl-token";
var getOrCreateATAInstruction = async (connection, tokenMint, owner, payer, allowOwnerOffCurve = true, tokenProgram) => {
const toAccount = getAssociatedTokenAddressSync(
tokenMint,
owner,
allowOwnerOffCurve,
tokenProgram
);
try {
await getAccount(connection, toAccount);
return { ataPubkey: toAccount, ix: void 0 };
} catch (e) {
if (e instanceof TokenAccountNotFoundError || e instanceof TokenInvalidAccountOwnerError) {
const ix = createAssociatedTokenAccountIdempotentInstruction(
payer,
toAccount,
owner,
tokenMint,
tokenProgram
);
return { ataPubkey: toAccount, ix };
} else {
console.error("Error::getOrCreateATAInstruction", e);
throw e;
}
}
};
function unwrapSOLInstruction(owner, receiver, allowOwnerOffCurve = true) {
const wSolATAAccount = getAssociatedTokenAddressSync(
NATIVE_MINT2,
owner,
allowOwnerOffCurve
);
if (wSolATAAccount) {
const closedWrappedSolInstruction = createCloseAccountInstruction(
wSolATAAccount,
receiver,
owner,
[],
TOKEN_PROGRAM_ID
);
return closedWrappedSolInstruction;
}
return null;
}
function wrapSOLInstruction(from, to, amount) {
return [
SystemProgram.transfer({
fromPubkey: from,
toPubkey: to,
lamports: amount
}),
new TransactionInstruction({
keys: [
{
pubkey: to,
isSigner: false,
isWritable: true
}
],
data: Buffer.from(new Uint8Array([17])),
programId: TOKEN_PROGRAM_ID
})
];
}
function findAssociatedTokenAddress(walletAddress, tokenMintAddress, tokenProgramId) {
return PublicKey3.findProgramAddressSync(
[
walletAddress.toBuffer(),
tokenProgramId.toBuffer(),
tokenMintAddress.toBuffer()
],
ASSOCIATED_TOKEN_PROGRAM_ID
)[0];
}
async function getTokenDecimals(connection, mintAddress) {
const mintPubkey = mintAddress instanceof PublicKey3 ? mintAddress : new PublicKey3(mintAddress);
const tokenProgram = (await connection.getAccountInfo(mintPubkey)).owner;
const mintInfo = await getMint(
connection,
mintPubkey,
"confirmed",
tokenProgram
);
return mintInfo.decimals;
}
function getTokenProgram(tokenType) {
return tokenType === 0 /* SPL */ ? TOKEN_PROGRAM_ID : TOKEN_2022_PROGRAM_ID;
}
async function getTokenType(connection, tokenMint) {
const accountInfo = await connection.getAccountInfo(tokenMint);
if (!accountInfo) {
return null;
}
return accountInfo.owner.equals(TOKEN_PROGRAM_ID) ? 0 /* SPL */ : 1 /* Token2022 */;
}
async function prepareTokenAccountTx(connection, owner, payer, tokenMint, amount, tokenProgram) {
const instructions = [];
const { ataPubkey: tokenAccount, ix: createAtaIx } = await getOrCreateATAInstruction(
connection,
tokenMint,
owner,
payer,
true,
tokenProgram
);
createAtaIx && instructions.push(createAtaIx);
if (tokenMint.equals(NATIVE_MINT2)) {
const wrapIx = wrapSOLInstruction(owner, tokenAccount, amount);
instructions.push(...wrapIx);
}
const transaction = new Transaction();
if (instructions.length > 0) {
transaction.add(...instructions);
}
return { tokenAccount, transaction };
}
async function cleanUpTokenAccountTx(owner, receiver, tokenMint) {
if (tokenMint.equals(NATIVE_MINT2)) {
const unwrapIx = unwrapSOLInstruction(owner, receiver);
if (unwrapIx) {
return { transaction: new Transaction().add(unwrapIx) };
}
}
return null;
}
// src/helpers/common.ts
function getFirstKey(key1, key2) {
const buf1 = key1.toBuffer();
const buf2 = key2.toBuffer();
if (Buffer.compare(buf1, buf2) === 1) {
return buf1;
}
return buf2;
}
function getSecondKey(key1, key2) {
const buf1 = key1.toBuffer();
const buf2 = key2.toBuffer();
if (Buffer.compare(buf1, buf2) === 1) {
return buf2;
}
return buf1;
}
async function getAccountData(accountAddress, accountType, program, commitment) {
const address = accountAddress instanceof PublicKey4 ? accountAddress : new PublicKey4(accountAddress);
return await program.account[accountType].fetchNullable(
address,
commitment
);
}
async function getAccountCreationTimestamp(accountAddress, connection) {
const address = accountAddress instanceof PublicKey4 ? accountAddress : new PublicKey4(accountAddress);
const signatures = await connection.getSignaturesForAddress(address, {
limit: 1
});
return signatures[0]?.blockTime ? new Date(signatures[0].blockTime * 1e3) : void 0;
}
async function getAccountCreationTimestamps(accountAddresses, connection) {
const timestampPromises = accountAddresses.map(
(address) => getAccountCreationTimestamp(address, connection)
);
return Promise.all(timestampPromises);
}
function getTotalTokenSupply(swapBaseAmount, migrationBaseThreshold, lockedVestingParams) {
try {
const totalCirculatingAmount = swapBaseAmount.add(
migrationBaseThreshold
);
const totalLockedVestingAmount = lockedVestingParams.cliffUnlockAmount.add(
lockedVestingParams.amountPerPeriod.mul(
lockedVestingParams.numberOfPeriod
)
);
const totalAmount = totalCirculatingAmount.add(totalLockedVestingAmount);
if (totalAmount.isNeg() || totalAmount.bitLength() > 64) {
throw new Error("Math overflow");
}
return totalAmount;
} catch (error) {
throw new Error("Math overflow");
}
}
function getPriceFromSqrtPrice(sqrtPrice, tokenBaseDecimal, tokenQuoteDecimal) {
const sqrtPriceDecimal = new Decimal2(sqrtPrice.toString());
const lamportPrice = sqrtPriceDecimal.mul(sqrtPriceDecimal).div(new Decimal2(2).pow(128));
const tokenPrice = lamportPrice.mul(
new Decimal2(10).pow(tokenBaseDecimal - tokenQuoteDecimal)
);
return tokenPrice;
}
var getSqrtPriceFromPrice = (price, tokenADecimal, tokenBDecimal) => {
const decimalPrice = new Decimal2(price);
const adjustedByDecimals = decimalPrice.div(
new Decimal2(10 ** (tokenADecimal - tokenBDecimal))
);
const sqrtValue = Decimal2.sqrt(adjustedByDecimals);
const sqrtValueQ64 = sqrtValue.mul(Decimal2.pow(2, 64));
return new BN6(sqrtValueQ64.floor().toFixed());
};
var getSqrtPriceFromMarketCap = (marketCap, totalSupply, tokenBaseDecimal, tokenQuoteDecimal) => {
let price = new Decimal2(marketCap).div(new Decimal2(totalSupply));
return getSqrtPriceFromPrice(
price.toString(),
tokenBaseDecimal,
tokenQuoteDecimal
);
};
function getBaseTokenForSwap(sqrtStartPrice, sqrtMigrationPrice, curve) {
let totalAmount = new BN6(0);
for (let i = 0; i < curve.length; i++) {
const lowerSqrtPrice = i == 0 ? sqrtStartPrice : curve[i - 1].sqrtPrice;
if (curve[i].sqrtPrice && curve[i].sqrtPrice.gt(sqrtMigrationPrice)) {
const deltaAmount = getDeltaAmountBaseUnsigned(
lowerSqrtPrice,
sqrtMigrationPrice,
curve[i].liquidity,
0 /* Up */
);
totalAmount = totalAmount.add(deltaAmount);
break;
} else {
const deltaAmount = getDeltaAmountBaseUnsigned(
lowerSqrtPrice,
curve[i].sqrtPrice,
curve[i].liquidity,
0 /* Up */
);
totalAmount = totalAmount.add(deltaAmount);
}
}
return totalAmount;
}
var getMigrationQuoteAmountFromMigrationQuoteThreshold = (migrationQuoteThreshold, migrationFeePercent) => {
const migrationQuoteAmount = migrationQuoteThreshold.mul(new Decimal2(100).sub(new Decimal2(migrationFeePercent))).div(new Decimal2(100));
return migrationQuoteAmount;
};
var getMigrationQuoteThresholdFromMigrationQuoteAmount = (migrationQuoteAmount, migrationFeePercent) => {
const migrationQuoteThreshold = migrationQuoteAmount.mul(new Decimal2(100)).div(new Decimal2(100).sub(new Decimal2(migrationFeePercent)));
return migrationQuoteThreshold;
};
var getMigrationBaseToken = (migrationQuoteAmount, sqrtMigrationPrice, migrationOption) => {
if (migrationOption == 0 /* MET_DAMM */) {
const price = sqrtMigrationPrice.mul(sqrtMigrationPrice);
const quote = migrationQuoteAmount.shln(128);
const { div: baseDiv, mod } = quote.divmod(price);
let div = baseDiv;
if (!mod.isZero()) {
div = div.add(new BN6(1));
}
return div;
} else if (migrationOption == 1 /* MET_DAMM_V2 */) {
const liquidity = getInitialLiquidityFromDeltaQuote(
migrationQuoteAmount,
MIN_SQRT_PRICE,
sqrtMigrationPrice
);
const baseAmount = getDeltaAmountBaseUnsigned(
sqrtMigrationPrice,
MAX_SQRT_PRICE,
liquidity,
0 /* Up */
);
return baseAmount;
} else {
throw Error("Invalid migration option");
}
};
var getTotalVestingAmount = (lockedVesting) => {
const totalVestingAmount = lockedVesting.cliffUnlockAmount.add(
lockedVesting.amountPerPeriod.mul(lockedVesting.numberOfPeriod)
);
return totalVestingAmount;
};
var getLiquidity = (baseAmount, quoteAmount, minSqrtPrice, maxSqrtPrice) => {
const liquidityFromBase = getInitialLiquidityFromDeltaBase(
baseAmount,
maxSqrtPrice,
minSqrtPrice
);
const liquidityFromQuote = getInitialLiquidityFromDeltaQuote(
quoteAmount,
minSqrtPrice,
maxSqrtPrice
);
return BN6.min(liquidityFromBase, liquidityFromQuote);
};
var getFirstCurve = (migrationSqrtPrice, migrationBaseAmount, swapAmount, migrationQuoteThreshold, migrationFeePercent) => {
const migrationSqrPriceDecimal = new Decimal2(migrationSqrtPrice.toString());
const migrationBaseAmountDecimal = new Decimal2(
migrationBaseAmount.toString()
);
const swapAmountDecimal = new Decimal2(swapAmount.toString());
const migrationFeePercentDecimal = new Decimal2(
migrationFeePercent.toString()
);
const denominator = swapAmountDecimal.mul(new Decimal2(100).sub(migrationFeePercentDecimal)).div(new Decimal2(100));
const sqrtStartPriceDecimal = migrationSqrPriceDecimal.mul(migrationBaseAmountDecimal).div(denominator);
const sqrtStartPrice = new BN6(sqrtStartPriceDecimal.floor().toFixed());
const liquidity = getLiquidity(
swapAmount,
migrationQuoteThreshold,
sqrtStartPrice,
migrationSqrtPrice
);
return {
sqrtStartPrice,
curve: [
{
sqrtPrice: migrationSqrtPrice,
liquidity
}
]
};
};
var getTotalSupplyFromCurve = (migrationQuoteThreshold, sqrtStartPrice, curve, lockedVesting, migrationOption, leftover, migrationFeePercent) => {
const sqrtMigrationPrice = getMigrationThresholdPrice(
migrationQuoteThreshold,
sqrtStartPrice,
curve
);
const swapBaseAmount = getBaseTokenForSwap(
sqrtStartPrice,
sqrtMigrationPrice,
curve
);
const swapBaseAmountBuffer = getSwapAmountWithBuffer(
swapBaseAmount,
sqrtStartPrice,
curve
);
const migrationQuoteAmount = getMigrationQuoteAmountFromMigrationQuoteThreshold(
new Decimal2(migrationQuoteThreshold.toString()),
migrationFeePercent
);
const migrationBaseAmount = getMigrationBaseToken(
fromDecimalToBN(migrationQuoteAmount),
sqrtMigrationPrice,
migrationOption
);
const totalVestingAmount = getTotalVestingAmount(lockedVesting);
const minimumBaseSupplyWithBuffer = swapBaseAmountBuffer.add(migrationBaseAmount).add(totalVestingAmount).add(leftover);
return minimumBaseSupplyWithBuffer;
};
var getMigrationThresholdPrice = (migrationThreshold, sqrtStartPrice, curve) => {
let nextSqrtPrice = sqrtStartPrice;
if (curve.length === 0) {
throw Error("Curve is empty");
}
const totalAmount = getDeltaAmountQuoteUnsigned(
nextSqrtPrice,
curve[0].sqrtPrice,
curve[0].liquidity,
0 /* Up */
);
if (totalAmount.gt(migrationThreshold)) {
nextSqrtPrice = getNextSqrtPriceFromInput(
nextSqrtPrice,
curve[0].liquidity,
migrationThreshold,
false
);
} else {
let amountLeft = migrationThreshold.sub(totalAmount);
nextSqrtPrice = curve[0].sqrtPrice;
for (let i = 1; i < curve.length; i++) {
const maxAmount = getDeltaAmountQuoteUnsigned(
nextSqrtPrice,
curve[i].sqrtPrice,
curve[i].liquidity,
0 /* Up */
);
if (maxAmount.gt(amountLeft)) {
nextSqrtPrice = getNextSqrtPriceFromInput(
nextSqrtPrice,
curve[i].liquidity,
amountLeft,
false
);
amountLeft = new BN6(0);
break;
} else {
amountLeft = amountLeft.sub(maxAmount);
nextSqrtPrice = curve[i].sqrtPrice;
}
}
if (!amountLeft.isZero()) {
let migrationThresholdStr = migrationThreshold.toString();
let amountLeftStr = amountLeft.toString();
throw Error(
`Not enough liquidity, migrationThreshold: ${migrationThresholdStr} amountLeft: ${amountLeftStr}`
);
}
}
return nextSqrtPrice;
};
var getSwapAmountWithBuffer = (swapBaseAmount, sqrtStartPrice, curve) => {
const swapAmountBuffer = swapBaseAmount.add(
swapBaseAmount.mul(new BN6(25)).div(new BN6(100))
);
const maxBaseAmountOnCurve = getBaseTokenForSwap(
sqrtStartPrice,
MAX_SQRT_PRICE,
curve
);
return BN6.min(swapAmountBuffer, maxBaseAmountOnCurve);
};
var getPercentageSupplyOnMigration = (initialMarketCap, migrationMarketCap, lockedVesting, totalLeftover, totalTokenSupply) => {
const marketCapRatio = initialMarketCap.div(migrationMarketCap);
const sqrtRatio = Decimal2.sqrt(marketCapRatio);
const totalVestingAmount = getTotalVestingAmount(lockedVesting);
const vestingPercentage = new Decimal2(totalVestingAmount.toString()).mul(new Decimal2(100)).div(new Decimal2(totalTokenSupply.toString()));
const leftoverPercentage = new Decimal2(totalLeftover.toString()).mul(new Decimal2(100)).div(new Decimal2(totalTokenSupply.toString()));
const numerator = new Decimal2(100).mul(sqrtRatio).sub(vestingPercentage.add(leftoverPercentage).mul(sqrtRatio));
const denominator = new Decimal2(1).add(sqrtRatio);
return numerator.div(denominator).toNumber();
};
var getMigrationQuoteAmount = (migrationMarketCap, percentageSupplyOnMigration) => {
return migrationMarketCap.mul(percentageSupplyOnMigration).div(new Decimal2(100));
};
function getFeeSchedulerParams(startingBaseFeeBps, endingBaseFeeBps, baseFeeMode, numberOfPeriod, totalDuration) {
if (startingBaseFeeBps == endingBaseFeeBps) {
if (numberOfPeriod != 0 || totalDuration != 0) {
throw new Error(
"numberOfPeriod and totalDuration must both be zero"
);
}
return {
cliffFeeNumerator: bpsToFeeNumerator(startingBaseFeeBps),
firstFactor: 0,
secondFactor: new BN6(0),
thirdFactor: new BN6(0),
baseFeeMode: 0 /* FeeSchedulerLinear */
};
}
if (numberOfPeriod <= 0) {
throw new Error("Total periods must be greater than zero");
}
if (startingBaseFeeBps > MAX_FEE_BPS) {
throw new Error(
`startingBaseFeeBps (${startingBaseFeeBps} bps) exceeds maximum allowed value of ${MAX_FEE_BPS} bps`
);
}
if (endingBaseFeeBps > startingBaseFeeBps) {
throw new Error(
"endingBaseFeeBps bps must be less than or equal to startingBaseFeeBps bps"
);
}
if (numberOfPeriod == 0 || totalDuration == 0) {
throw new Error(
"numberOfPeriod and totalDuration must both greater than zero"
);
}
const maxBaseFeeNumerator = bpsToFeeNumerator(startingBaseFeeBps);
const minBaseFeeNumerator = bpsToFeeNumerator(endingBaseFeeBps);
const periodFrequency = new BN6(totalDuration / numberOfPeriod);
let reductionFactor;
if (baseFeeMode == 0 /* FeeSchedulerLinear */) {
const totalReduction = maxBaseFeeNumerator.sub(minBaseFeeNumerator);
reductionFactor = totalReduction.divn(numberOfPeriod);
} else {
const ratio = minBaseFeeNumerator.toNumber() / maxBaseFeeNumerator.toNumber();
const decayBase = Math.pow(ratio, 1 / numberOfPeriod);
reductionFactor = new BN6(BASIS_POINT_MAX * (1 - decayBase));
}
return {
cliffFeeNumerator: maxBaseFeeNumerator,
firstFactor: numberOfPeriod,
secondFactor: periodFrequency,
thirdFactor: reductionFactor,
baseFeeMode
};
}
function calculateFeeSchedulerEndingBaseFeeBps(cliffFeeNumerator, numberOfPeriod, periodFrequency, reductionFactor, baseFeeMode) {
if (numberOfPeriod === 0 || periodFrequency === 0) {
return cliffFeeNumerator / FEE_DENOMINATOR * BASIS_POINT_MAX;
}
let baseFeeNumerator;
if (baseFeeMode == 0 /* FeeSchedulerLinear */) {
baseFeeNumerator = cliffFeeNumerator - numberOfPeriod * reductionFactor;
} else {
const decayRate = 1 - reductionFactor / BASIS_POINT_MAX;
baseFeeNumerator = cliffFeeNumerator * Math.pow(decayRate, numberOfPeriod);
}
return Math.max(0, baseFeeNumerator / FEE_DENOMINATOR * BASIS_POINT_MAX);
}
function getRateLimiterParams(baseFeeBps, feeIncrementBps, referenceAmount, maxLimiterDuration, tokenQuoteDecimal, activationType) {
const cliffFeeNumerator = bpsToFeeNumerator(baseFeeBps);
const feeIncrementNumerator = bpsToFeeNumerator(feeIncrementBps);
if (baseFeeBps <= 0 || feeIncrementBps <= 0 || referenceAmount <= 0 || maxLimiterDuration <= 0) {
throw new Error("All rate limiter parameters must be greater than zero");
}
if (baseFeeBps > MAX_FEE_BPS) {
throw new Error(
`Base fee (${baseFeeBps} bps) exceeds maximum allowed value of ${MAX_FEE_BPS} bps`
);
}
if (feeIncrementBps > MAX_FEE_BPS) {
throw new Error(
`Fee increment (${feeIncrementBps} bps) exceeds maximum allowed value of ${MAX_FEE_BPS} bps`
);
}
if (feeIncrementNumerator.gte(new BN6(FEE_DENOMINATOR))) {
throw new Error(
"Fee increment numerator must be less than FEE_DENOMINATOR"
);
}
const deltaNumerator = new BN6(MAX_FEE_NUMERATOR).sub(cliffFeeNumerator);
const maxIndex = deltaNumerator.div(feeIncrementNumerator);
if (maxIndex.lt(new BN6(1))) {
throw new Error("Fee increment is too large for the given base fee");
}
if (cliffFeeNumerator.lt(new BN6(MIN_FEE_NUMERATOR)) || cliffFeeNumerator.gt(new BN6(MAX_FEE_NUMERATOR))) {
throw new Error("Base fee must be between 0.01% and 99%");
}
const maxDuration = activationType === 0 /* Slot */ ? MAX_RATE_LIMITER_DURATION_IN_SLOTS : MAX_RATE_LIMITER_DURATION_IN_SECONDS;
if (maxLimiterDuration > maxDuration) {
throw new Error(
`Max duration exceeds maximum allowed value of ${maxDuration}`
);
}
const referenceAmountInLamports = convertToLamports(
referenceAmount,
tokenQuoteDecimal
);
return {
cliffFeeNumerator,
firstFactor: feeIncrementBps,
secondFactor: new BN6(maxLimiterDuration),
thirdFactor: new BN6(referenceAmountInLamports),
baseFeeMode: 2 /* RateLimiter */
};
}
function getDynamicFeeParams(baseFeeBps, maxPriceChangeBps = MAX_PRICE_CHANGE_BPS_DEFAULT) {
if (maxPriceChangeBps > MAX_PRICE_CHANGE_BPS_DEFAULT) {
throw new Error(
`maxPriceChangeBps (${maxPriceChangeBps} bps) must be less than or equal to ${MAX_PRICE_CHANGE_BPS_DEFAULT}`
);
}
const priceRatio = maxPriceChangeBps / BASIS_POINT_MAX + 1;
const sqrtPriceRatioQ64 = new BN6(
Decimal2.sqrt(priceRatio.toString()).mul(Decimal2.pow(2, 64)).floor().toFixed()
);
const deltaBinId = sqrtPriceRatioQ64.sub(ONE_Q64).div(BIN_STEP_BPS_U128_DEFAULT).muln(2);
const maxVolatilityAccumulator = new BN6(deltaBinId.muln(BASIS_POINT_MAX));
const squareVfaBin = maxVolatilityAccumulator.mul(new BN6(BIN_STEP_BPS_DEFAULT)).pow(new BN6(2));
const baseFeeNumerator = new BN6(bpsToFeeNumerator(baseFeeBps));
const maxDynamicFeeNumerator = baseFeeNumerator.muln(20).divn(100);
const vFee = maxDynamicFeeNumerator.mul(new BN6(1e11)).sub(new BN6(99999999999));
const variableFeeControl = vFee.div(squareVfaBin);
return {
binStep: BIN_STEP_BPS_DEFAULT,
binStepU128: BIN_STEP_BPS_U128_DEFAULT,
filterPeriod: DYNAMIC_FEE_FILTER_PERIOD_DEFAULT,
decayPeriod: DYNAMIC_FEE_DECAY_PERIOD_DEFAULT,
reductionFactor: DYNAMIC_FEE_REDUCTION_FACTOR_DEFAULT,
maxVolatilityAccumulator: maxVolatilityAccumulator.toNumber(),
variableFeeControl: variableFeeControl.toNumber()
};
}
function getLockedVestingParams(totalLockedVestingAmount, numberOfVestingPeriod, cliffUnlockAmount, totalVestingDuration, cliffDurationFromMigrationTime, tokenBaseDecimal) {
if (totalLockedVestingAmount == 0) {
return {
amountPerPeriod: new BN6(0),
cliffDurationFromMigrationTime: new BN6(0),
frequency: new BN6(0),
numberOfPeriod: new BN6(0),
cliffUnlockAmount: new BN6(0)
};
}
if (totalLockedVestingAmount == cliffUnlockAmount) {
return {
amountPerPeriod: convertToLamports(1, tokenBaseDecimal),
cliffDurationFromMigrationTime: new BN6(
cliffDurationFromMigrationTime
),
frequency: new BN6(1),
numberOfPeriod: new BN6(1),
cliffUnlockAmount: convertToLamports(
totalLockedVestingAmount - 1,
tokenBaseDecimal
)
};
}
if (numberOfVestingPeriod <= 0) {
throw new Error("Total periods must be greater than zero");
}
if (numberOfVestingPeriod == 0 || totalVestingDuration == 0) {
throw new Error(
"numberOfPeriod and totalVestingDuration must both be greater than zero"
);
}
if (cliffUnlockAmount > totalLockedVestingAmount) {
throw new Error(
"Cliff unlock amount cannot be greater than total locked vesting amount"
);
}
const amountPerPeriod = (totalLockedVestingAmount - cliffUnlockAmount) / numberOfVestingPeriod;
const roundedAmountPerPeriod = Math.floor(amountPerPeriod);
const totalPeriodicAmount = roundedAmountPerPeriod * numberOfVestingPeriod;
const remainder = totalLockedVestingAmount - (cliffUnlockAmount + totalPeriodicAmount);
const adjustedCliffUnlockAmount = cliffUnlockAmount + remainder;
const periodFrequency = new BN6(totalVestingDuration / numberOfVestingPeriod);
return {
amountPerPeriod: convertToLamports(
roundedAmountPerPeriod,
tokenBaseDecimal
),
cliffDurationFromMigrationTime: new BN6(cliffDurationFromMigrationTime),
frequency: periodFrequency,
numberOfPeriod: new BN6(numberOfVestingPeriod),
cliffUnlockAmount: convertToLamports(
adjustedCliffUnlockAmount,
tokenBaseDecimal
)
};
}
var getTwoCurve = (migrationSqrtPrice, midSqrtPrice, initialSqrtPrice, swapAmount, migrationQuoteThreshold) => {
let p0 = new Decimal2(initialSqrtPrice.toString());
let p1 = new Decimal2(midSqrtPrice.toString());
let p2 = new Decimal2(migrationSqrtPrice.toString());
let a1 = new Decimal2(1).div(p0).sub(new Decimal2(1).div(p1));
let b1 = new Decimal2(1).div(p1).sub(new Decimal2(1).div(p2));
let c1 = new Decimal2(swapAmount.toString());
let a2 = p1.sub(p0);
let b2 = p2.sub(p1);
let c2 = new Decimal2(migrationQuoteThreshold.toString()).mul(
Decimal2.pow(2, 128)
);
let l0 = c1.mul(b2).sub(c2.mul(b1)).div(a1.mul(b2).sub(a2.mul(b1)));
let l1 = c1.mul(a2).sub(c2.mul(a1)).div(b1.mul(a2).sub(b2.mul(a1)));
if (l0.isNeg() || l1.isNeg()) {
return {
isOk: false,
sqrtStartPrice: new BN6(0),
curve: []
};
}
return {
isOk: true,
sqrtStartPrice: initialSqrtPrice,
curve: [
{
sqrtPrice: midSqrtPrice,
liquidity: new BN6(l0.floor().toFixed())
},
{
sqrtPrice: migrationSqrtPrice,
liquidity: new BN6(l1.floor().toFixed())
}
]
};
};
function checkRateLimiterApplied(baseFeeMode, swapBaseForQuote, currentPoint, activationPoint, maxLimiterDuration) {
return baseFeeMode === 2 /* RateLimiter */ && !swapBaseForQuote && currentPoint.gte(activationPoint) && currentPoint.lte(activationPoint.add(maxLimiterDuration));
}
function getBaseFeeParams(baseFeeParams, tokenQuoteDecimal, activationType) {
if (baseFeeParams.baseFeeMode === 2 /* RateLimiter */) {
if (!baseFeeParams.rateLimiterParam) {
throw new Error(
"Rate limiter parameters are required for RateLimiter mode"
);
}
const {
baseFeeBps,
feeIncrementBps,
referenceAmount,
maxLimiterDuration
} = baseFeeParams.rateLimiterParam;
return getRateLimiterParams(
baseFeeBps,
feeIncrementBps,
referenceAmount,
maxLimiterDuration,
tokenQuoteDecimal,
activationType
);
} else {
if (!baseFeeParams.feeSchedulerParam) {
throw new Error(
"Fee scheduler parameters are required for FeeScheduler mode"
);
}
const { startingFeeBps, endingFeeBps, numberOfPeriod, totalDuration } = baseFeeParams.feeSchedulerParam;
return getFeeSchedulerParams(
startingFeeBps,
endingFeeBps,
baseFeeParams.baseFeeMode,
numberOfPeriod,
totalDuration
);
}
}
function getQuoteReserveFromNextSqrtPrice(nextSqrtPrice, config) {
let totalAmount = new BN6(0);
for (let i = 0; i < config.curve.length; i++) {
const lowerSqrtPrice = i === 0 ? config.sqrtStartPrice : config.curve[i - 1].sqrtPrice;
if (nextSqrtPrice.gt(lowerSqrtPrice)) {
const upperSqrtPrice = nextSqrtPrice.lt(config.curve[i].sqrtPrice) ? nextSqrtPrice : config.curve[i].sqrtPrice;
const maxAmountIn = getDeltaAmountQuoteUnsigned(
lowerSqrtPrice,
upperSqrtPrice,
config.curve[i].liquidity,
0 /* Up */
);
totalAmount = totalAmount.add(maxAmountIn);
}
}
return totalAmount;
}
var getTokenomics = (initialMarketCap, migrationMarketCap, totalLockedVestingAmount, totalLeftover, totalTokenSupply) => {
const marketCapRatio = initialMarketCap.div(migrationMarketCap);
const sqrtRatio = Decimal2.sqrt(marketCapRatio);
const vestingPercentage = new Decimal2(totalLockedVestingAmount.toString()).mul(new Decimal2(100)).div(new Decimal2(totalTokenSupply.toString()));
const leftoverPercentage = new Decimal2(totalLeftover.toString()).mul(new Decimal2(100)).div(new Decimal2(totalTokenSupply.toString()));
const percentageSupplyOnMigration = new Decimal2(100).mul(sqrtRatio).sub(vestingPercentage.add(leftoverPercentage).mul(sqrtRatio));
const denominator = new Decimal2(1).add(sqrtRatio);
const migrationSupplyDecimal = percentageSupplyOnMigration.div(denominator).mul(new Decimal2(totalTokenSupply.toString())).div(new Decimal2(100));
const migrationSupply = new BN6(migrationSupplyDecimal.floor().toFixed());
const bondingCurveSupply = totalTokenSupply.sub(migrationSupply).sub(totalLeftover).sub(totalLockedVestingAmount);
return {
bondingCurveSupply,
migrationSupply,
leftoverSupply: totalLeftover,
lockedVestingSupply: totalLockedVestingAmount
};
};
function getMigratedPoolFeeParams(migrationOption, migrationFeeOption, migratedPoolFee) {
const defaultFeeParams = {
collectFeeMode: 0,
dynamicFee: 0,
poolFeeBps: 0
};
if (migrationOption === 0 /* MET_DAMM */) {
return defaultFeeParams;
}
if (migrationOption === 1 /* MET_DAMM_V2 */) {
if (migrationFeeOption === 6 /* Customizable */) {
return migratedPoolFee;
}
return defaultFeeParams;
}
return defaultFeeParams;
}
async function getCurrentPoint(connection, activationType) {
const currentSlot = await connection.getSlot();
if (activationType === 0 /* Slot */) {
return new BN6(currentSlot);
} else {
const currentTime = await connection.getBlockTime(currentSlot);
return new BN6(currentTime);
}
}
async function prepareSwapAmountParam(amount, mintAddress, connection) {
const mintTokenDecimals = await getTokenDecimals(connection, mintAddress);
return convertToLamports(amount, mintTokenDecimals);
}
// src/helpers/accounts.ts
import { PublicKey as PublicKey5 } from "@solana/web3.js";
var SEED = Object.freeze({
POOL_AUTHORITY: "pool_authority",
EVENT_AUTHORITY: "__event_authority",
POOL: "pool",
TOKEN_VAULT: "token_vault",
METADATA: "metadata",
PARTNER_METADATA: "partner_metadata",
CLAIM_FEE_OPERATOR: "cf_operator",
DAMM_V1_MIGRATION_METADATA: "meteora",
DAMM_V2_MIGRATION_METADATA: "damm_v2",
LP_MINT: "lp_mint",
FEE: "fee",
POSITION: "position",
POSITION_NFT_ACCOUNT: "position_nft_account",
LOCK_ESCROW: "lock_escrow",
VIRTUAL_POOL_METADATA: "virtual_pool_metadata",
ESCROW: "escrow",
BASE_LOCKER: "base_locker",
VAULT: "vault"
});
function deriveDbcEventAuthority() {
const [eventAuthority] = PublicKey5.findProgramAddressSync(
[Buffer.from(SEED.EVENT_AUTHORITY)],
DYNAMIC_BONDING_CURVE_PROGRAM_ID
);
return eventAuthority;
}
function deriveDammV1EventAuthority() {
const [eventAuthority] = PublicKey5.findProgramAddressSync(
[Buffer.from(SEED.EVENT_AUTHORITY)],
DAMM_V1_PROGRAM_ID
);
return eventAuthority;
}
function deriveDammV2EventAuthority() {
const [eventAuthority] = PublicKey5.findProgramAddressSync(
[Buffer.from(SEED.EVENT_AUTHORITY)],
DAMM_V2_PROGRAM_ID
);
return eventAuthority;
}
function deriveLockerEventAuthority() {
const [eventAuthority] = PublicKey5.findProgramAddressSync(
[Buffer.from(SEED.EVENT_AUTHORITY)],
LOCKER_PROGRAM_ID
);
return eventAuthority;
}
function deriveDbcPoolAuthority() {
const [poolAuthority] = PublicKey5.findProgramAddressSync(
[Buffer.from(SEED.POOL_AUTHORITY)],
DYNAMIC_BONDING_CURVE_PROGRAM_ID
);
return poolAuthority;
}
function deriveDammV1PoolAuthority() {
const [poolAuthority] = PublicKey5.findProgramAddressSync(
[Buffer.from(SEED.POOL_AUTHORITY)],
DAMM_V1_PROGRAM_ID
);
return poolAuthority;
}
function deriveDammV2PoolAuthority() {
const [poolAuthority] = PublicKey5.findProgramAddressSync(
[Buffer.from(SEED.POOL_AUTHORITY)],
DAMM_V2_PROGRAM_ID
);
return poolAuthority;
}
function deriveDbcPoolAddress(quoteMint, baseMint, config) {
const isQuoteMintBiggerThanBaseMint = new PublicKey5(quoteMint).toBuffer().compare(new Uint8Array(new PublicKey5(baseMint).toBuffer())) > 0;
const [pool] = PublicKey5.findProgramAddressSync(
[
Buffer.from(SEED.POOL),
new PublicKey5(config).toBuffer(),
isQuoteMintBiggerThanBaseMint ? new PublicKey5(quoteMint).toBuffer() : new PublicKey5(baseMint).toBuffer(),
isQuoteMintBiggerThanBaseMint ? new PublicKey5(baseMint).toBuffer() : new PublicKey5(quoteMint).toBuffer()
],
DYNAMIC_BONDING_CURVE_PROGRAM_ID
);
return pool;
}
function deriveDammV1PoolAddress(config, tokenAMint, tokenBMint) {
return PublicKey5.findProgramAddressSync(
[
getFirstKey(tokenAMint, tokenBMint),
getSecondKey(tokenAMint, tokenBMint),
config.toBuffer()
],
DAMM_V1_PROGRAM_ID
)[0];
}
function deriveDammV2PoolAddress(config, tokenAMint, tokenBMint) {
return PublicKey5.findProgramAddressSync(
[
Buffer.from(SEED.POOL),
config.toBuffer(),
getFirstKey(tokenAMint, tokenBMint),
getSecondKey(tokenAMint, tokenBMint)
],
DAMM_V2_PROGRAM_ID
)[0];
}
function deriveMintMetadata(mint) {
const [metadata] = PublicKey5.findProgramAddressSync(
[
Buffer.from(SEED.METADATA),
METAPLEX_PROGRAM_ID.toBuffer(),
mint.toBuffer()
],
METAPLEX_PROGRAM_ID
);
return metadata;
}
function derivePartnerMetadata(feeClaimer) {
const [partnerMetadata] = PublicKey5.findProgramAddressSync(
[Buffer.from(SEED.PARTNER_METADATA), feeClaimer.toBuffer()],
DYNAMIC_BONDING_CURVE_PROGRAM_ID
);
return partnerMetadata;
}
function deriveDbcPoolMetadata(pool) {
return PublicKey5.findProgramAddressSync(
[Buffer.from(SEED.VIRTUAL_POOL_METADATA), pool.toBuffer()],
DYNAMIC_BONDING_CURVE_PROGRAM_ID
)[0];
}
function deriveDammV1MigrationMetadataAddress(virtual_pool) {
return PublicKey5.findProgramAddressSync(
[Buffer.from(SEED.DAMM_V1_MIGRATION_METADATA), virtual_pool.toBuffer()],
DYNAMIC_BONDING_CURVE_PROGRAM_ID
)[0];
}
function deriveDammV2MigrationMetadataAddress(virtual_pool) {
return PublicKey5.findProgramAddressSync(
[Buffer.from(SEED.DAMM_V2_MIGRATION_METADATA), virtual_pool.toBuffer()],
DYNAMIC_BONDING_CURVE_PROGRAM_ID
)[0];
}
function deriveDbcTokenVaultAddress(pool, mint) {
const [tokenVault] = PublicKey5.findProgramAddressSync(
[Buffer.from(SEED.TOKEN_VAULT), mint.toBuffer(), pool.toBuffer()],
DYNAM