UNPKG

@symmetry-hq/liquidity-sdk

Version:

Exchange functionality using symmetry funds liquidity

117 lines (116 loc) 7.89 kB
"use strict"; 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;