UNPKG

testsetset

Version:

A Typescript SDK for interacting with the Dynamic Bonding Curve on Meteora.

1,443 lines (1,431 loc) 604 kB
// 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