@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
JavaScript
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