UNPKG

@mercurial-finance/dynamic-amm-sdk

Version:

Mercurial Vaults SDK is a typescript library that allows you to interact with Mercurial v2's AMM.

111 lines 6.03 kB
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; import { Connection, PublicKey, Keypair } from '@solana/web3.js'; import BN from 'bn.js'; import { Wallet, AnchorProvider } from '@coral-xyz/anchor'; import AmmImpl from '../amm'; import { PROGRAM_ID, SEEDS } from '../amm/constants'; import { getAssociatedTokenAccount, derivePoolAddressWithConfig as deriveConstantProductPoolAddressWithConfig, } from '../amm/utils'; import fs from 'fs'; function loadKeypairFromFile(filename) { const secret = JSON.parse(fs.readFileSync(filename).toString()); const secretKey = Uint8Array.from(secret); return Keypair.fromSecretKey(secretKey); } const mainnetConnection = new Connection('https://api.devnet.solana.com'); const payerKP = loadKeypairFromFile('~/.config/solana/id.json'); const payerWallet = new Wallet(payerKP); console.log('payer %s', payerKP.publicKey); const provider = new AnchorProvider(mainnetConnection, payerWallet, { commitment: 'confirmed', }); function fromAllocationsToAmount(lpAmount, allocations) { const sumPercentage = allocations.reduce((partialSum, a) => partialSum + a.percentage, 0); if (sumPercentage === 0) { throw Error('sumPercentage is zero'); } let amounts = []; let sum = new BN(0); for (let i = 0; i < allocations.length - 1; i++) { const amount = lpAmount.mul(new BN(allocations[i].percentage)).div(new BN(sumPercentage)); sum = sum.add(amount); amounts.push({ address: allocations[i].address, amount, }); } // the last wallet get remaining amount amounts.push({ address: allocations[allocations.length - 1].address, amount: lpAmount.sub(sum), }); return amounts; } function createPoolAndLockLiquidity(tokenAMint, tokenBMint, tokenAAmount, tokenBAmount, config, allocations) { return __awaiter(this, void 0, void 0, function* () { const programID = new PublicKey(PROGRAM_ID); const poolPubkey = deriveConstantProductPoolAddressWithConfig(tokenAMint, tokenBMint, config, programID); // Create the pool console.log('create pool %s', poolPubkey); let transactions = yield AmmImpl.createPermissionlessConstantProductPoolWithConfig(provider.connection, payerWallet.publicKey, tokenAMint, tokenBMint, tokenAAmount, tokenBAmount, config); for (const transaction of transactions) { transaction.sign(payerWallet.payer); const txHash = yield provider.connection.sendRawTransaction(transaction.serialize()); yield provider.connection.confirmTransaction(txHash, 'finalized'); console.log('transaction %s', txHash); } // Create escrow and lock liquidity const [lpMint] = PublicKey.findProgramAddressSync([Buffer.from(SEEDS.LP_MINT), poolPubkey.toBuffer()], programID); const payerPoolLp = yield getAssociatedTokenAccount(lpMint, payerWallet.publicKey); const payerPoolLpBalance = (yield provider.connection.getTokenAccountBalance(payerPoolLp)).value.amount; console.log('payerPoolLpBalance %s', payerPoolLpBalance.toString()); let allocationByAmounts = fromAllocationsToAmount(new BN(payerPoolLpBalance), allocations); const pool = yield AmmImpl.create(provider.connection, poolPubkey); for (const allocation of allocationByAmounts) { console.log('Lock liquidity %s', allocation.address.toString()); let transaction = yield pool.lockLiquidity(allocation.address, allocation.amount, payerWallet.publicKey); transaction.sign(payerWallet.payer); const txHash = yield provider.connection.sendRawTransaction(transaction.serialize()); yield provider.connection.confirmTransaction(txHash, 'finalized'); console.log('transaction %s', txHash); } }); } /** * Example script to create a new pool and lock liquidity to it */ function main() { return __awaiter(this, void 0, void 0, function* () { // 1. Token A/B address of the pool. const tokenAMint = new PublicKey('BjhBG7jkHYMBMos2HtRdFrw8rvSguBe5c3a3EJYXhyUf'); const tokenBMint = new PublicKey('9KMeJp868Pdk8PrJEkwoAHMA1ctdxfVhe2TjeS4BcWjs'); // 2. Configuration address for the pool. It will decide the fees of the pool. const config = new PublicKey('21PjsfQVgrn56jSypUT5qXwwSjwKWvuoBCKbVZrgTLz4'); // 3. Allocation of the locked LP to multiple address. In the below example // 4sBMz7zmDWPzdEnECJW3NA9mEcNwkjYtVnL2KySaWYAf will get 80% of the fee of the locked liquidity // CVV5MxfwA24PsM7iuS2ddssYgySf5SxVJ8PpAwGN2yVy will get 20% of the fee of the locked liquidity let allocations = [ { address: new PublicKey('4sBMz7zmDWPzdEnECJW3NA9mEcNwkjYtVnL2KySaWYAf'), percentage: 80, }, { address: new PublicKey('CVV5MxfwA24PsM7iuS2ddssYgySf5SxVJ8PpAwGN2yVy'), percentage: 20, }, ]; // 4. Amount of token A and B to be deposited to the pool, and will be locked. let tokenAAmount = new BN(100000); let tokenBAmount = new BN(500000); yield createPoolAndLockLiquidity(tokenAMint, tokenBMint, tokenAAmount, tokenBAmount, config, allocations); }); } main(); //# sourceMappingURL=create_pool_and_lock_liquidity.js.map