@symmetry-hq/liquidity-sdk
Version:
Exchange functionality using symmetry funds liquidity
117 lines (116 loc) • 7.89 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());
});
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.FundError = exports.executeSwap = exports.generateSwapInstruction = void 0;
const anchor_1 = require("@coral-xyz/anchor");
const web3_js_1 = require("@solana/web3.js");
const spl_token_1 = require("@solana/spl-token");
const txHelpers_1 = require("./txHelpers");
const types_1 = require("./types");
function generateSwapInstruction(program, user, tokenListData, routeData, fromTokenAccount, toTokenAccount, slippage = 0.5) {
return __awaiter(this, void 0, void 0, function* () {
let { fromTokenId, toTokenId, fromAmount, toAmount } = routeData;
let minimumReceived = toAmount * (1 - slippage / 100);
return yield program.methods
.liquidityProvision(new anchor_1.BN(fromTokenId), new anchor_1.BN(toTokenId), new anchor_1.BN(Math.floor(fromAmount * 10 ** tokenListData[fromTokenId].decimals)), new anchor_1.BN(Math.floor(minimumReceived * 10 ** tokenListData[toTokenId].decimals)))
.accounts({
buyer: user,
fundState: routeData.swapAccounts.fundState,
pdaAccount: routeData.swapAccounts.authority,
pdaFromTokenAccount: routeData.swapAccounts.source,
buyerFromTokenAccount: fromTokenAccount,
pdaToTokenAccount: routeData.swapAccounts.destination,
buyerToTokenAccount: toTokenAccount,
swapFeeAccount: (0, spl_token_1.getAssociatedTokenAddressSync)(routeData.swapAccounts.fees.feeTokenMint, routeData.swapAccounts.fees.smfWallet),
hostFeeAccount: (0, spl_token_1.getAssociatedTokenAddressSync)(routeData.swapAccounts.fees.feeTokenMint, routeData.swapAccounts.fees.hostWallet),
managerFeeAccount: (0, spl_token_1.getAssociatedTokenAddressSync)(routeData.swapAccounts.fees.feeTokenMint, routeData.swapAccounts.fees.managerWallet),
tokenList: routeData.swapAccounts.tokenList,
curveData: routeData.swapAccounts.curveData,
tokenProgram: spl_token_1.TOKEN_PROGRAM_ID
})
.remainingAccounts(routeData.swapAccounts.remainingAccounts)
.instruction();
});
}
exports.generateSwapInstruction = generateSwapInstruction;
function executeSwap(program, wallet, connection, tokenListData, routeData, userFromTokenAccount, userToTokenAccount, slippage = 0.5) {
return __awaiter(this, void 0, void 0, function* () {
let { preTransaction, postTransaction, fromTokenAccount, toTokenAccount } = yield (0, txHelpers_1.prepareAccounts)(wallet, connection, tokenListData, routeData, userFromTokenAccount, userToTokenAccount);
let mainTransaction = new web3_js_1.Transaction();
let instructions = [];
let swapFeeAccount = (0, spl_token_1.getAssociatedTokenAddressSync)(routeData.swapAccounts.fees.feeTokenMint, types_1.SWAP_FEE_ACCOUNT);
const info2 = yield program.provider.connection.getAccountInfo(swapFeeAccount, "confirmed");
if (!info2) {
instructions.push((0, spl_token_1.createAssociatedTokenAccountInstruction)(wallet.publicKey, swapFeeAccount, types_1.SWAP_FEE_ACCOUNT, routeData.swapAccounts.fees.feeTokenMint));
}
let hostFeeAccount = (0, spl_token_1.getAssociatedTokenAddressSync)(routeData.swapAccounts.fees.feeTokenMint, routeData.swapAccounts.fees.hostWallet);
const info3 = yield program.provider.connection.getAccountInfo(hostFeeAccount, "confirmed");
if (!info3 && routeData.swapAccounts.fees.hostWallet.toBase58() !== types_1.SWAP_FEE_ACCOUNT.toBase58()
&& routeData.swapAccounts.fees.hostWallet.toBase58() !== wallet.publicKey.toBase58()) {
instructions.push((0, spl_token_1.createAssociatedTokenAccountInstruction)(wallet.publicKey, hostFeeAccount, routeData.swapAccounts.fees.hostWallet, routeData.swapAccounts.fees.feeTokenMint));
}
let managerFeeAccount = (0, spl_token_1.getAssociatedTokenAddressSync)(routeData.swapAccounts.fees.feeTokenMint, routeData.swapAccounts.fees.managerWallet);
const info4 = yield program.provider.connection.getAccountInfo(managerFeeAccount, "confirmed");
if (!info4 && routeData.swapAccounts.fees.managerWallet.toBase58() !== types_1.SWAP_FEE_ACCOUNT.toBase58()
&& routeData.swapAccounts.fees.managerWallet.toBase58() !== routeData.swapAccounts.fees.hostWallet.toBase58()
&& routeData.swapAccounts.fees.managerWallet.toBase58() !== wallet.publicKey.toBase58()) {
instructions.push((0, spl_token_1.createAssociatedTokenAccountInstruction)(wallet.publicKey, managerFeeAccount, routeData.swapAccounts.fees.managerWallet, routeData.swapAccounts.fees.feeTokenMint));
}
if (instructions.length > 0) {
preTransaction.add(...instructions);
}
mainTransaction.add(yield generateSwapInstruction(program, wallet.publicKey, tokenListData, routeData, fromTokenAccount, toTokenAccount, slippage));
if (preTransaction.instructions.length > 0) {
preTransaction.add(web3_js_1.ComputeBudgetProgram.setComputeUnitLimit({ units: 1000000 }));
preTransaction.add(web3_js_1.ComputeBudgetProgram.setComputeUnitPrice({ microLamports: 20000 }));
}
if (postTransaction.instructions.length > 0) {
postTransaction.add(web3_js_1.ComputeBudgetProgram.setComputeUnitLimit({ units: 1000000 }));
postTransaction.add(web3_js_1.ComputeBudgetProgram.setComputeUnitPrice({ microLamports: 20000 }));
}
mainTransaction.add(web3_js_1.ComputeBudgetProgram.setComputeUnitLimit({ units: 1000000 }));
mainTransaction.add(web3_js_1.ComputeBudgetProgram.setComputeUnitPrice({ microLamports: 20000 }));
const { txIndex, transactions } = yield (0, txHelpers_1.applyBlockHashAndPartialSign)(connection, wallet, preTransaction, mainTransaction, postTransaction, [], []);
const signedTxs = yield wallet.signAllTransactions(transactions);
let serialized = [];
let err = {};
let txId;
for (let i = 0; i < signedTxs.length; i++) {
serialized.push(signedTxs[i].serialize());
for (let i = 0; i < serialized.length; i++) {
const { signature, response } = yield (0, txHelpers_1.sendAndConfirmTransaction)(connection, serialized[i]);
let failed = false;
if (!signature || !response || response == "Error" || response.meta.err)
failed = true;
if (failed && err.message == undefined) {
if (i != txIndex)
err.message = "Couldn't prepare accounts";
else
err.message = "Swap failed";
err.txId = signature;
}
if (i == txIndex)
txId = signature;
}
}
if (err.message)
throw new FundError(err.message, err.txId);
return txId;
});
}
exports.executeSwap = executeSwap;
class FundError extends Error {
constructor(message, txId = "") {
super(message);
this.txId = txId;
}
}
exports.FundError = FundError;