UNPKG

@symmetry-hq/baskets-sdk

Version:

Software Development Kit for interacting with Symmetry Baskets Program

659 lines (658 loc) 43.1 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()); }); }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.Basket = void 0; const anchor_1 = require("@coral-xyz/anchor"); const web3_js_1 = require("@solana/web3.js"); const basketsIDL_1 = require("./basketsIDL"); const config_1 = require("./config"); const utils_1 = require("./utils"); const splTokenHelpers_1 = require("./splTokenHelpers"); const nodewallet_1 = __importDefault(require("@coral-xyz/anchor/dist/cjs/nodewallet")); const instructionsBuilder_1 = require("./instructionsBuilder"); class Basket { constructor(ownAddress, basketData) { this.ownAddress = ownAddress; this.data = basketData; } static loadFromRawData(program, rawData) { return new Basket(rawData.pubkey, program.coder.accounts.decode("fundState", rawData.account.data)); } static loadFromPubkey(program, basketState) { return __awaiter(this, void 0, void 0, function* () { let basketData = yield program.account.fundState.fetch(basketState, "confirmed"); return new Basket(basketState, //@ts-ignore basketData); }); } static getCompositionAndPrice(connection_1, pubkey_1) { return __awaiter(this, arguments, void 0, function* (connection, pubkey, getPrice = false) { var _a, _b; let provider = new anchor_1.AnchorProvider(connection, new nodewallet_1.default(web3_js_1.Keypair.generate()), { skipPreflight: true, preflightCommitment: "recent", commitment: "processed", }); let program = new anchor_1.Program(basketsIDL_1.IDL, provider); let accounts = [pubkey, config_1.TOKEN_LIST_ADDRESS]; let accountsInfo = yield connection.getMultipleAccountsInfo(accounts, "confirmed"); //@ts-ignore let basketData = yield program.coder.accounts.decode("fundState", (_a = accountsInfo[0]) === null || _a === void 0 ? void 0 : _a.data); //@ts-ignore let tokenList = yield program.coder.accounts.decode("tokenList", (_b = accountsInfo[1]) === null || _b === void 0 ? void 0 : _b.data); let supply = parseInt(basketData.supplyOutstanding.toString()) / 10 ** 6; let mint = basketData.fundToken.toBase58(); let tokenIds = basketData.currentCompToken .slice(0, parseInt(basketData.numOfTokens.toString())).map((x) => parseInt(x.toString())); let tokenAmounts = basketData.currentCompAmount .slice(0, parseInt(basketData.numOfTokens.toString())) .map((x, id) => parseInt(x.toString()) / 10 ** tokenList.list[tokenIds[id]].decimals); let tokenMints = tokenIds.map((x) => tokenList.list[x].tokenMint.toBase58()); let price = undefined; let tvl = undefined; if (getPrice) { let oraclePrices = yield (0, utils_1.rawOraclePrices)(connection, tokenList.list.slice(0, parseInt(tokenList.numTokens.toString()))); tvl = 0; for (let i = 0; i < tokenAmounts.length; i++) tvl += oraclePrices[tokenIds[i]] * tokenAmounts[i]; price = tvl / supply; } let result = { price: price, supply: supply, tvl: tvl, mint: mint, composition: tokenAmounts.map((_, id) => { return { mint: tokenMints[id], amount: tokenAmounts[id], }; }) }; return result; }); } static create(program_1, connection_1, wallet_1, tokenList_1, lookups_1, basketParams_1) { return __awaiter(this, arguments, void 0, function* (program, connection, wallet, tokenList, lookups, basketParams, lamports = config_1.ADDITIONAL_FEE) { let createData = yield (0, instructionsBuilder_1.buildCreateBasketIx)(program, tokenList, basketParams); let blockhash = (yield connection.getLatestBlockhash("confirmed")).blockhash; let V0Create = new web3_js_1.VersionedTransaction(new web3_js_1.TransactionMessage({ payerKey: wallet.publicKey, recentBlockhash: blockhash, instructions: [ createData, web3_js_1.ComputeBudgetProgram.setComputeUnitLimit({ units: config_1.ADDITIONAL_UNITS }), web3_js_1.ComputeBudgetProgram.setComputeUnitPrice({ microLamports: lamports }) ] }).compileToV0Message(lookups)); let signedTransactions = yield (0, utils_1.signVersionedTransactions)(wallet, [V0Create]); let resultCreate = yield (0, utils_1.sendSignedTransactions)(connection, signedTransactions, 1); console.log("Create Tx:", resultCreate[0]); return yield Basket .loadFromPubkey(program, createData.keys[2].pubkey); }); } update(program) { return __awaiter(this, void 0, void 0, function* () { //@ts-ignore this.data = yield program.account.fundState.fetch(this.ownAddress, "confirmed"); }); } editManager(program_1, connection_1, wallet_1, newManager_1) { return __awaiter(this, arguments, void 0, function* (program, connection, wallet, newManager, lamports = config_1.ADDITIONAL_FEE) { let editManager = new web3_js_1.Transaction(); editManager.instructions = [ yield (0, instructionsBuilder_1.buildEditManagetIx)(program, this, newManager), web3_js_1.ComputeBudgetProgram.setComputeUnitLimit({ units: config_1.ADDITIONAL_UNITS }), web3_js_1.ComputeBudgetProgram.setComputeUnitPrice({ microLamports: lamports }) ]; let signedTransactions = yield (0, utils_1.signTransactionsWithWallet)(connection, wallet, [{ transaction: editManager, signers: [] }]); let resultEdit = yield (0, utils_1.sendSignedTransactions)(connection, [signedTransactions[0]], 1); return resultEdit[0]; }); } edit(program_1, connection_1, wallet_1, tokenList_1, lookups_1, basketParams_1) { return __awaiter(this, arguments, void 0, function* (program, connection, wallet, tokenList, lookups, basketParams, lamports = config_1.ADDITIONAL_FEE) { let blockhash = (yield connection.getLatestBlockhash("confirmed")).blockhash; let V0Create = new web3_js_1.VersionedTransaction(new web3_js_1.TransactionMessage({ payerKey: wallet.publicKey, recentBlockhash: blockhash, instructions: [ yield (0, instructionsBuilder_1.buildEditBasketIx)(program, tokenList, this, basketParams), web3_js_1.ComputeBudgetProgram.setComputeUnitLimit({ units: config_1.ADDITIONAL_UNITS }), web3_js_1.ComputeBudgetProgram.setComputeUnitPrice({ microLamports: lamports }) ] }).compileToV0Message(lookups)); let signedTransactions = yield (0, utils_1.signVersionedTransactions)(wallet, [V0Create]); let resultEdit = yield (0, utils_1.sendSignedTransactions)(connection, signedTransactions, 1); return resultEdit[0]; }); } setMetaData(program_1, wallet_1, symbol_1, name_1, uri_1) { return __awaiter(this, arguments, void 0, function* (program, wallet, symbol, name, uri, lamports = config_1.ADDITIONAL_FEE) { let transaction = new web3_js_1.Transaction(); transaction.instructions = [ yield (0, instructionsBuilder_1.buildSetMetadataIx)(program, this, { symbol: symbol, name: name, uri: uri }), web3_js_1.ComputeBudgetProgram.setComputeUnitLimit({ units: config_1.ADDITIONAL_UNITS }), web3_js_1.ComputeBudgetProgram.setComputeUnitPrice({ microLamports: lamports }) ]; let signedTransactions = yield (0, utils_1.signTransactionsWithWallet)(program.provider.connection, wallet, [{ transaction: transaction, signers: [] }]); return (yield (0, utils_1.sendSignedTransactions)(program.provider.connection, signedTransactions, 1))[0]; }); } close(program_1, wallet_1) { return __awaiter(this, arguments, void 0, function* (program, wallet, lamports = config_1.ADDITIONAL_FEE) { let transaction = new web3_js_1.Transaction(); transaction.instructions = [ yield (0, instructionsBuilder_1.buildCloseBasketIx)(program, this), web3_js_1.ComputeBudgetProgram.setComputeUnitLimit({ units: config_1.ADDITIONAL_UNITS }), web3_js_1.ComputeBudgetProgram.setComputeUnitPrice({ microLamports: lamports }) ]; let signedTransactions = yield (0, utils_1.signTransactionsWithWallet)(program.provider.connection, wallet, [{ transaction: transaction, signers: [] }]); return (yield (0, utils_1.sendSignedTransactions)(program.provider.connection, signedTransactions, 1))[0]; }); } getSwbFeeds(tokenList) { let oracles = []; for (let i = 0; i < this.data.numOfTokens.toNumber(); i++) if (tokenList[this.data.currentCompToken[i].toNumber()].oracleType == "SwbOnDemand") oracles.push(new web3_js_1.PublicKey(tokenList[this.data.currentCompToken[i].toNumber()].oracleAccount)); return oracles; } rebalanceFromUsdcTransactionData(program_1, wallet_1, pda_1, basketState_1, tokenList_1, rebalanceFeeAccount_1, jupSwapData_1) { return __awaiter(this, arguments, void 0, function* (program, wallet, pda, basketState, tokenList, rebalanceFeeAccount, jupSwapData, lamports = config_1.ADDITIONAL_FEE) { let tokenId = jupSwapData.toTokenId; let ix = (jupSwapData.type == "Simple") ? yield program.methods .rebalanceBuy(jupSwapData.toTokenId, new anchor_1.BN(jupSwapData.fromAmount), jupSwapData.dataLength, Array.from(jupSwapData.data)) .accounts({ signer: wallet.publicKey, fundState: basketState, tokenList: config_1.TOKEN_LIST_ADDRESS, oracleSol: new web3_js_1.PublicKey(tokenList[1].oracleAccount), oracleToken: new web3_js_1.PublicKey(tokenList[tokenId].oracleAccount), oracleUsdc: new web3_js_1.PublicKey(tokenList[0].oracleAccount), pdaAccount: pda, pdaTokenAccount: new web3_js_1.PublicKey(tokenList[tokenId].pdaTokenAccount), pdaUsdcAccount: new web3_js_1.PublicKey(tokenList[0].pdaTokenAccount), rebalanceFeeAccount: rebalanceFeeAccount, tokenProgram: splTokenHelpers_1.TOKEN_PROGRAM_ID, }) .remainingAccounts(jupSwapData.accounts) .instruction() : yield program.methods .rebalanceBuyTransitive(jupSwapData.toTokenId, new anchor_1.BN(jupSwapData.fromAmount), jupSwapData.firstIxEnd, jupSwapData.dataLength, jupSwapData.firstIxAccounts, Array.from(jupSwapData.data)) .accounts({ signer: wallet.publicKey, fundState: basketState, tokenList: config_1.TOKEN_LIST_ADDRESS, oracleSol: new web3_js_1.PublicKey(tokenList[1].oracleAccount), oracleToken: new web3_js_1.PublicKey(tokenList[tokenId].oracleAccount), oracleUsdc: new web3_js_1.PublicKey(tokenList[0].oracleAccount), pdaAccount: pda, pdaTokenAccount: new web3_js_1.PublicKey(tokenList[tokenId].pdaTokenAccount), pdaMidAccount: new web3_js_1.PublicKey(jupSwapData.midTokenPda), pdaUsdcAccount: new web3_js_1.PublicKey(tokenList[0].pdaTokenAccount), rebalanceFeeAccount: rebalanceFeeAccount, tokenProgram: splTokenHelpers_1.TOKEN_PROGRAM_ID, }) .remainingAccounts(jupSwapData.accounts) .instruction(); let rawData = { payerKey: wallet.publicKey, instructions: [ ix, web3_js_1.ComputeBudgetProgram.setComputeUnitLimit({ units: config_1.ADDITIONAL_UNITS }), web3_js_1.ComputeBudgetProgram.setComputeUnitPrice({ microLamports: lamports }) ], lookupTables: jupSwapData.lookupTableAccounts }; return rawData; }); } rebalanceToUsdcTransactionData(program_1, wallet_1, pda_1, basketState_1, tokenList_1, rebalanceFeeAccount_1, jupSwapData_1) { return __awaiter(this, arguments, void 0, function* (program, wallet, pda, basketState, tokenList, rebalanceFeeAccount, jupSwapData, lamports = config_1.ADDITIONAL_FEE) { let tokenId = jupSwapData.fromTokenId; let ix = (jupSwapData.type == "Simple") ? yield program.methods .rebalanceSell(tokenId, new anchor_1.BN(jupSwapData.fromAmount), jupSwapData.dataLength, Array.from(jupSwapData.data)) .accounts({ signer: wallet.publicKey, fundState: basketState, tokenList: config_1.TOKEN_LIST_ADDRESS, oracleSol: new web3_js_1.PublicKey(tokenList[1].oracleAccount), oracleToken: new web3_js_1.PublicKey(tokenList[tokenId].oracleAccount), oracleUsdc: new web3_js_1.PublicKey(tokenList[0].oracleAccount), pdaAccount: pda, pdaTokenAccount: new web3_js_1.PublicKey(tokenList[tokenId].pdaTokenAccount), pdaUsdcAccount: new web3_js_1.PublicKey(tokenList[0].pdaTokenAccount), rebalanceFeeAccount: rebalanceFeeAccount, tokenProgram: splTokenHelpers_1.TOKEN_PROGRAM_ID, }) .remainingAccounts(jupSwapData.accounts) .instruction() : yield program.methods .rebalanceSellTransitive(tokenId, new anchor_1.BN(jupSwapData.fromAmount), jupSwapData.firstIxEnd, jupSwapData.dataLength, jupSwapData.firstIxAccounts, Array.from(jupSwapData.data)) .accounts({ signer: wallet.publicKey, fundState: basketState, tokenList: config_1.TOKEN_LIST_ADDRESS, oracleSol: new web3_js_1.PublicKey(tokenList[1].oracleAccount), oracleToken: new web3_js_1.PublicKey(tokenList[tokenId].oracleAccount), oracleUsdc: new web3_js_1.PublicKey(tokenList[0].oracleAccount), pdaAccount: pda, pdaTokenAccount: new web3_js_1.PublicKey(tokenList[tokenId].pdaTokenAccount), pdaMidAccount: new web3_js_1.PublicKey(jupSwapData.midTokenPda), pdaUsdcAccount: new web3_js_1.PublicKey(tokenList[0].pdaTokenAccount), rebalanceFeeAccount: rebalanceFeeAccount, tokenProgram: splTokenHelpers_1.TOKEN_PROGRAM_ID, }) .remainingAccounts(jupSwapData.accounts) .instruction(); let rawData = { payerKey: wallet.publicKey, instructions: [ ix, web3_js_1.ComputeBudgetProgram.setComputeUnitLimit({ units: config_1.ADDITIONAL_UNITS }), web3_js_1.ComputeBudgetProgram.setComputeUnitPrice({ microLamports: lamports }) ], lookupTables: jupSwapData.lookupTableAccounts }; return rawData; }); } getRebalanceInfo(program, tokenList, oraclePriceData, timestamp, forceRebalance = false) { let basketStateData = this.data; let currentCompToken = basketStateData.currentCompToken; let currentCompAmount = basketStateData.currentCompAmount; let targetWeight = basketStateData.targetWeight; let numTokens = parseInt(basketStateData.numOfTokens.toString()); let rebalanceThreshold = basketStateData.rebalanceThreshold; let weightSum = basketStateData.weightSum; let rebalanceInterval = parseInt(basketStateData.rebalanceInterval.toString()); let lastRebalanceTime = basketStateData.lastRebalanceTime; return (0, utils_1.calculateRebalanceAmounts)(program, numTokens, timestamp, Array.from(lastRebalanceTime, x => parseInt(x.toString())), rebalanceInterval, Array.from(currentCompToken, x => parseInt(x.toString())), Array.from(currentCompAmount, x => parseInt(x.toString())), Array.from(targetWeight, x => parseInt(x.toString())), parseInt(weightSum.toString()), tokenList, parseInt(rebalanceThreshold.toString()), oraclePriceData, forceRebalance); } rebalanceFrom(program_1, wallet_1, tokenList_1, jupSwapDatas_1, rebalanceInfos_1, lookups_1) { return __awaiter(this, arguments, void 0, function* (program, wallet, tokenList, jupSwapDatas, rebalanceInfos, lookups, lamports = config_1.ADDITIONAL_FEE) { let ix = yield (0, instructionsBuilder_1.buildUpdateCurrentWeightsIx)(program, this, tokenList); let transactionsData = []; for (let i = rebalanceInfos.length - 1; i >= 0; i--) { if (rebalanceInfos[i].side == config_1.Side.To) continue; let rebalanceData = jupSwapDatas[i]; if (!rebalanceData) continue; let txData = yield this.rebalanceFromUsdcTransactionData(program, wallet, config_1.BASKETS_PROGRAM_PDA, this.ownAddress, tokenList, config_1.REBALANCE_FEE_ACCOUNT, rebalanceData, lamports).catch((e) => { console.log(e.message); return null; }); if (!txData) continue; transactionsData.push(txData); } for (let i = 0; i < transactionsData.length; i++) { transactionsData[i].instructions = [ix, ...transactionsData[i].instructions]; transactionsData[i].lookupTables = [...lookups, ...transactionsData[i].lookupTables]; } return transactionsData; }); } rebalanceTo(program_1, wallet_1, tokenList_1, jupSwapDatas_1, rebalanceInfos_1, lookups_1) { return __awaiter(this, arguments, void 0, function* (program, wallet, tokenList, jupSwapDatas, rebalanceInfos, lookups, lamports = config_1.ADDITIONAL_FEE) { let ix = yield (0, instructionsBuilder_1.buildUpdateCurrentWeightsIx)(program, this, tokenList); let transactionsData = []; for (let i = rebalanceInfos.length - 1; i >= 0; i--) { if (rebalanceInfos[i].side == config_1.Side.From) continue; let rebalanceData = jupSwapDatas[i]; if (!rebalanceData) continue; let txData = yield this.rebalanceToUsdcTransactionData(program, wallet, config_1.BASKETS_PROGRAM_PDA, this.ownAddress, tokenList, config_1.REBALANCE_FEE_ACCOUNT, rebalanceData, lamports).catch((e) => { console.log(e.message); return null; }); if (!txData) continue; transactionsData.push(txData); } for (let i = 0; i < transactionsData.length; i++) { transactionsData[i].instructions = [ix, ...transactionsData[i].instructions]; transactionsData[i].lookupTables = [...lookups, ...transactionsData[i].lookupTables]; } return transactionsData; }); } // async rebalanceSingle( // program: Program<BasketsIDL>, // wallet: Wallet, // tokenList: TokenSettings[], // jupSwapData: JupSwapData, // rebalanceInfo: RebalanceInfo, // lamports: number, // updateOracles: boolean, /// NEED to implement // ): Promise<TransactionSignature> { // let prepareIx = await buildUpdateCurrentWeightsIx(program, this, tokenList); // let txData = (rebalanceInfo.side == Side.To) ? // await this.rebalanceToUsdcTransactionData( // program, // wallet, // BASKETS_PROGRAM_PDA, // this.ownAddress, // tokenList, // REBALANCE_FEE_ACCOUNT, // jupSwapData, // lamports, // ) : // await this.rebalanceFromUsdcTransactionData( // program, // wallet, // BASKETS_PROGRAM_PDA, // this.ownAddress, // tokenList, // REBALANCE_FEE_ACCOUNT, // jupSwapData, // lamports, // ); // txData.instructions = [prepareIx, ...txData.instructions]; // const lookupTableAccount1 = ( // await program.provider.connection.getAddressLookupTable(BASKETS_LOOKUP_TABLE_1) // ).value; // const lookupTableAccount2 = ( // await program.provider.connection.getAddressLookupTable(BASKETS_LOOKUP_TABLE_2) // ).value; // //@ts-ignore // txData.lookupTables.push(lookupTableAccount1); // //@ts-ignore // txData.lookupTables.push(lookupTableAccount2); // let blockhash = (await program.provider.connection.getLatestBlockhash()).blockhash; // let signedTransactions = await signVersionedTransactions( // wallet, // [new VersionedTransaction( // new TransactionMessage({ // payerKey: txData.payerKey, // recentBlockhash: blockhash, // instructions: txData.instructions, // }).compileToV0Message(txData.lookupTables) // )] // ).catch(e => { console.log(e); }); // let txs = await sendSignedTransactions( // program.provider.connection, //@ts-ignore // signedTransactions, // 1 // ).catch((e) => {console.log(e); return [""]}); // return txs[0]; // } // async sellBasketToSingleToken( // program: Program<BasketsIDL>, // wallet: Wallet, // tokenList: TokenSettings[], // withdrawToken: PublicKey, // amount: number, // lamports: number, // updateOracles: boolean, /// NEED to implement // ): Promise<TransactionSignature> { // let transaction = new Transaction(); // transaction.instructions = [ // await buildSellBasketToSingleTokenIx(program, tokenList, wallet.publicKey, this, withdrawToken, amount), // ComputeBudgetProgram.setComputeUnitLimit({units: ADDITIONAL_UNITS}), // ComputeBudgetProgram.setComputeUnitPrice({microLamports: lamports}) // ]; // let signedTransactions = await signTransactionsWithWallet( // program.provider.connection, // wallet, // [{transaction: transaction, signers:[]}] // ); // let txs = await sendSignedTransactions( // program.provider.connection, // signedTransactions, // 1, // ); // return txs[0]; // } computeOutputAmountWithSingleToken(oraclePrices, tokenList, withdrawToken, burnAmount) { return __awaiter(this, void 0, void 0, function* () { let tokenIndex = -1; for (let i = 0; i < this.data.currentCompToken.length; i++) if (parseInt(this.data.currentCompToken[i].toString()) == withdrawToken.id) { tokenIndex = i; break; } if (tokenIndex == -1) throw new Error("Token not in composition"); let withdrawTokenPrice = oraclePrices[withdrawToken.id]; let withdrawWorth = 0; let basketWorth = 0; for (let i = 0; i < parseInt(this.data.numOfTokens.toString()); i++) { let tokenPrice = oraclePrices[parseInt(this.data.currentCompToken[i].toString())]; basketWorth += tokenPrice * parseInt(this.data.currentCompAmount[i].toString()) / 10 ** tokenList[parseInt(this.data.currentCompToken[i].toString())].decimals; let allocation = (parseInt(this.data.currentCompAmount[i].toString()) * burnAmount * 10 ** 6 / parseInt(this.data.supplyOutstanding.toString())); withdrawWorth += tokenPrice * allocation / 10 ** tokenList[parseInt(this.data.currentCompToken[i].toString())].decimals; } let targetValueBefore = basketWorth * parseInt(this.data.targetWeight[tokenIndex].toString()) / parseInt(this.data.weightSum.toString()); let valueBefore = withdrawTokenPrice * parseInt(this.data.currentCompAmount[tokenIndex].toString()) / 10 ** withdrawToken.decimals; let valueToRebalance = 0; if (valueBefore <= targetValueBefore) valueToRebalance = withdrawWorth; else { let valueToTgtWeight = (valueBefore - targetValueBefore) * parseInt(this.data.weightSum.toString()) / (parseInt(this.data.weightSum.toString()) - parseInt(this.data.targetWeight[tokenIndex].toString())); if (valueToTgtWeight < withdrawWorth) { valueToRebalance = withdrawWorth - valueToTgtWeight; } } let tokenAmount = 0; tokenAmount += (withdrawWorth - valueToRebalance) / withdrawTokenPrice; let penalty = valueToRebalance * 300 / 10000; tokenAmount += (valueToRebalance - penalty) / withdrawTokenPrice; if (tokenAmount > parseInt(this.data.currentCompAmount[tokenIndex].toString()) / 10 ** withdrawToken.decimals) tokenAmount = parseInt(this.data.currentCompAmount[tokenIndex].toString()) / 10 ** withdrawToken.decimals; return tokenAmount; }); } sell(program_1, wallet_1, amount_1, rebalance_1) { return __awaiter(this, arguments, void 0, function* (program, wallet, amount, rebalance, lamports = config_1.ADDITIONAL_FEE) { let sellBasketData = yield (0, instructionsBuilder_1.buildSellBasketIx)(program, wallet.publicKey, this, amount, rebalance); let transaction = new web3_js_1.Transaction(); transaction.instructions = [ sellBasketData, web3_js_1.ComputeBudgetProgram.setComputeUnitLimit({ units: config_1.ADDITIONAL_UNITS }), web3_js_1.ComputeBudgetProgram.setComputeUnitPrice({ microLamports: lamports }) ]; let signedTransactions = yield (0, utils_1.signTransactionsWithWallet)(program.provider.connection, wallet, [{ transaction: transaction, signers: [] }]); yield (0, utils_1.sendSignedTransactions)(program.provider.connection, signedTransactions, 1); return yield Basket.loadFromPubkey(program, sellBasketData.keys[3].pubkey); }); } claimTokens(program_1, wallet_1, tokenList_1) { return __awaiter(this, arguments, void 0, function* (program, wallet, tokenList, lamports = config_1.ADDITIONAL_FEE) { yield this.update(program); let basketOwner = this.data.manager; let connection = program.provider.connection; let transactions = []; let claimTokensIxs = yield (0, instructionsBuilder_1.buildClaimTokensFromSellStateIxs)(program, tokenList, wallet.publicKey, this); let ixId = 0; for (let i = 0; i < parseInt(this.data.numOfTokens.toString()); i++) { if (parseInt(this.data.currentCompAmount[i].toString()) == 0 && i != 0) continue; let transaction = new web3_js_1.Transaction(); let tokenId = parseInt(this.data.currentCompToken[i].toString()); let userTokenAccount = (0, splTokenHelpers_1.getAssociatedTokenAddressSync)(new web3_js_1.PublicKey(tokenList[tokenId].tokenMint), basketOwner, true); let infoAta = yield connection.getAccountInfo(userTokenAccount, "confirmed"); if (!infoAta) transaction.add(yield (0, splTokenHelpers_1.createAssociatedTokenAccountInstruction)(wallet.publicKey, userTokenAccount, basketOwner, new web3_js_1.PublicKey(tokenList[tokenId].tokenMint))); transaction.instructions = [ ...transaction.instructions, claimTokensIxs[ixId], web3_js_1.ComputeBudgetProgram.setComputeUnitLimit({ units: config_1.ADDITIONAL_UNITS }), web3_js_1.ComputeBudgetProgram.setComputeUnitPrice({ microLamports: lamports }) ]; transactions.push(transaction); ixId = ixId + 1; } let signedTransactions = yield (0, utils_1.signTransactionsWithWallet)(connection, wallet, transactions.map(transaction => { return { transaction: transaction, signers: [] }; })); return yield (0, utils_1.sendSignedTransactions)(connection, signedTransactions); }); } removeDust(program, wallet, tokenList, oraclePriceData, lamports, updateOracles) { return __awaiter(this, void 0, void 0, function* () { let preTransactions = []; let swapTransactions = []; for (let j = parseInt(this.data.numOfTokens.toString()) - 1; j > 0; j--) { let token = parseInt(this.data.currentCompToken[j].toString()); let decimals = tokenList[token].decimals; let amount = parseInt(this.data.currentCompAmount[j].toString()); let weight = parseInt(this.data.targetWeight[j].toString()); let price = oraclePriceData[token]; let value = (amount / 10 ** decimals) * price; if (value > 0.005 || weight != 0) continue; let transaction = new web3_js_1.Transaction(); let instructions = []; let fromTokenAccount = (0, splTokenHelpers_1.getAssociatedTokenAddressSync)(new web3_js_1.PublicKey(tokenList[0].tokenMint), wallet.publicKey, true); let toTokenAccount = (0, splTokenHelpers_1.getAssociatedTokenAddressSync)(new web3_js_1.PublicKey(tokenList[token].tokenMint), wallet.publicKey, true); const info = yield program.provider.connection.getAccountInfo(toTokenAccount, "confirmed"); if (!info) { instructions.push((0, splTokenHelpers_1.createAssociatedTokenAccountInstruction)(wallet.publicKey, toTokenAccount, wallet.publicKey, new web3_js_1.PublicKey(tokenList[token].tokenMint))); } let swapFeeAccount = (0, splTokenHelpers_1.getAssociatedTokenAddressSync)(new web3_js_1.PublicKey(tokenList[token].tokenMint), config_1.SWAP_FEE_ACCOUNT); const info2 = yield program.provider.connection.getAccountInfo(swapFeeAccount, "confirmed"); if (!info2) { instructions.push((0, splTokenHelpers_1.createAssociatedTokenAccountInstruction)(wallet.publicKey, swapFeeAccount, config_1.SWAP_FEE_ACCOUNT, new web3_js_1.PublicKey(tokenList[token].tokenMint))); } let hostFeeAccount = (0, splTokenHelpers_1.getAssociatedTokenAddressSync)(new web3_js_1.PublicKey(tokenList[token].tokenMint), this.data.hostPubkey, true); const info3 = yield program.provider.connection.getAccountInfo(hostFeeAccount, "confirmed"); if (!info3) { instructions.push((0, splTokenHelpers_1.createAssociatedTokenAccountInstruction)(wallet.publicKey, hostFeeAccount, this.data.hostPubkey, new web3_js_1.PublicKey(tokenList[token].tokenMint))); } let managerFeeAccount = (0, splTokenHelpers_1.getAssociatedTokenAddressSync)(new web3_js_1.PublicKey(tokenList[token].tokenMint), this.data.manager, true); const info4 = yield program.provider.connection.getAccountInfo(managerFeeAccount, "confirmed"); if (!info4 && managerFeeAccount.toBase58() != hostFeeAccount.toBase58()) { instructions.push((0, splTokenHelpers_1.createAssociatedTokenAccountInstruction)(wallet.publicKey, managerFeeAccount, this.data.manager, new web3_js_1.PublicKey(tokenList[token].tokenMint))); } if (instructions.length > 0) { transaction.add(...instructions); transaction = transaction.add(web3_js_1.ComputeBudgetProgram.setComputeUnitLimit({ units: config_1.ADDITIONAL_UNITS })).add(web3_js_1.ComputeBudgetProgram.setComputeUnitPrice({ microLamports: lamports })); preTransactions.push(transaction); } let usdcAmount = Math.max(Math.floor(1.1 * value * 10 ** 6), 50); swapTransactions.push(new web3_js_1.Transaction() .add(yield program.methods.liquidityProvision(new anchor_1.BN(0), new anchor_1.BN(token), new anchor_1.BN(usdcAmount), new anchor_1.BN(amount)) .accounts({ buyer: program.provider.publicKey, fundState: this.ownAddress, pdaAccount: config_1.BASKETS_PROGRAM_PDA, pdaFromTokenAccount: new web3_js_1.PublicKey(tokenList[0].pdaTokenAccount), buyerFromTokenAccount: fromTokenAccount, pdaToTokenAccount: new web3_js_1.PublicKey(tokenList[token].pdaTokenAccount), buyerToTokenAccount: toTokenAccount, oracleSol: new web3_js_1.PublicKey(tokenList[1].oracleAccount), swapFeeAccount: (0, splTokenHelpers_1.getAssociatedTokenAddressSync)(new web3_js_1.PublicKey(tokenList[token].tokenMint), config_1.SWAP_FEE_ACCOUNT), hostFeeAccount: (0, splTokenHelpers_1.getAssociatedTokenAddressSync)(new web3_js_1.PublicKey(tokenList[token].tokenMint), this.data.hostPubkey, true), managerFeeAccount: (0, splTokenHelpers_1.getAssociatedTokenAddressSync)(new web3_js_1.PublicKey(tokenList[token].tokenMint), this.data.manager, true), tokenList: config_1.TOKEN_LIST_ADDRESS, curveData: config_1.CURVE_DATA_ADDRESS, tokenProgram: splTokenHelpers_1.TOKEN_PROGRAM_ID }) .remainingAccounts(this.data.currentCompToken.map(x => { return { pubkey: new web3_js_1.PublicKey(tokenList[parseInt(x.toString())].oracleAccount), isSigner: false, isWritable: false, }; })) .instruction()) .add(web3_js_1.ComputeBudgetProgram.setComputeUnitLimit({ units: config_1.ADDITIONAL_UNITS })).add(web3_js_1.ComputeBudgetProgram.setComputeUnitPrice({ microLamports: lamports }))); } let transactions = [...preTransactions, ...swapTransactions]; let signedTransactions = yield (0, utils_1.signTransactionsWithWallet)(program.provider.connection, wallet, transactions.map(transaction => { return { transaction: transaction, signers: [] }; })); let _ = yield (0, utils_1.sendSignedTransactions)(program.provider.connection, signedTransactions.slice(0, preTransactions.length)); return yield (0, utils_1.sendSignedTransactions)(program.provider.connection, signedTransactions.slice(preTransactions.length, signedTransactions.length), swapTransactions.length); }); } liquidityProvision(program_1, wallet_1, tokenList_1, fromToken_1, toToken_1, fromAmount_1) { return __awaiter(this, arguments, void 0, function* (program, wallet, tokenList, fromToken, toToken, fromAmount, lamports = config_1.ADDITIONAL_FEE) { let preTransactions = []; let swapTransactions = []; let transaction = new web3_js_1.Transaction(); let instructions = []; let fromTokenAccount = (0, splTokenHelpers_1.getAssociatedTokenAddressSync)(new web3_js_1.PublicKey(tokenList[fromToken].tokenMint), wallet.publicKey, true); let toTokenAccount = (0, splTokenHelpers_1.getAssociatedTokenAddressSync)(new web3_js_1.PublicKey(tokenList[toToken].tokenMint), wallet.publicKey, true); const info = yield program.provider.connection.getAccountInfo(toTokenAccount, "confirmed"); if (!info) { instructions.push((0, splTokenHelpers_1.createAssociatedTokenAccountInstruction)(wallet.publicKey, toTokenAccount, wallet.publicKey, new web3_js_1.PublicKey(tokenList[toToken].tokenMint))); } let swapFeeAccount = (0, splTokenHelpers_1.getAssociatedTokenAddressSync)(new web3_js_1.PublicKey(tokenList[toToken].tokenMint), config_1.SWAP_FEE_ACCOUNT); const info2 = yield program.provider.connection.getAccountInfo(swapFeeAccount, "confirmed"); if (!info2) { instructions.push((0, splTokenHelpers_1.createAssociatedTokenAccountInstruction)(wallet.publicKey, swapFeeAccount, config_1.SWAP_FEE_ACCOUNT, new web3_js_1.PublicKey(tokenList[toToken].tokenMint))); } let hostFeeAccount = (0, splTokenHelpers_1.getAssociatedTokenAddressSync)(new web3_js_1.PublicKey(tokenList[toToken].tokenMint), this.data.hostPubkey, true); const info3 = yield program.provider.connection.getAccountInfo(hostFeeAccount, "confirmed"); if (!info3) { instructions.push((0, splTokenHelpers_1.createAssociatedTokenAccountInstruction)(wallet.publicKey, hostFeeAccount, this.data.hostPubkey, new web3_js_1.PublicKey(tokenList[toToken].tokenMint))); } let managerFeeAccount = (0, splTokenHelpers_1.getAssociatedTokenAddressSync)(new web3_js_1.PublicKey(tokenList[toToken].tokenMint), this.data.manager, true); const info4 = yield program.provider.connection.getAccountInfo(managerFeeAccount, "confirmed"); if (!info4 && managerFeeAccount.toBase58() != hostFeeAccount.toBase58()) { instructions.push((0, splTokenHelpers_1.createAssociatedTokenAccountInstruction)(wallet.publicKey, managerFeeAccount, this.data.manager, new web3_js_1.PublicKey(tokenList[toToken].tokenMint))); } if (instructions.length > 0) { transaction.add(...instructions); transaction = transaction.add(web3_js_1.ComputeBudgetProgram.setComputeUnitLimit({ units: config_1.ADDITIONAL_UNITS })).add(web3_js_1.ComputeBudgetProgram.setComputeUnitPrice({ microLamports: lamports })); preTransactions.push(transaction); } swapTransactions.push(new web3_js_1.Transaction() .add(yield program.methods.liquidityProvision(new anchor_1.BN(fromToken), new anchor_1.BN(toToken), new anchor_1.BN(Math.floor(fromAmount * 10 ** tokenList[fromToken].decimals)), new anchor_1.BN(0)) .accounts({ buyer: program.provider.publicKey, fundState: this.ownAddress, pdaAccount: config_1.BASKETS_PROGRAM_PDA, pdaFromTokenAccount: new web3_js_1.PublicKey(tokenList[fromToken].pdaTokenAccount), buyerFromTokenAccount: fromTokenAccount, pdaToTokenAccount: new web3_js_1.PublicKey(tokenList[toToken].pdaTokenAccount), buyerToTokenAccount: toTokenAccount, oracleSol: new web3_js_1.PublicKey(tokenList[1].oracleAccount), swapFeeAccount: (0, splTokenHelpers_1.getAssociatedTokenAddressSync)(new web3_js_1.PublicKey(tokenList[toToken].tokenMint), config_1.SWAP_FEE_ACCOUNT), hostFeeAccount: (0, splTokenHelpers_1.getAssociatedTokenAddressSync)(new web3_js_1.PublicKey(tokenList[toToken].tokenMint), this.data.hostPubkey, true), managerFeeAccount: (0, splTokenHelpers_1.getAssociatedTokenAddressSync)(new web3_js_1.PublicKey(tokenList[toToken].tokenMint), this.data.manager, true), tokenList: config_1.TOKEN_LIST_ADDRESS, curveData: config_1.CURVE_DATA_ADDRESS, tokenProgram: splTokenHelpers_1.TOKEN_PROGRAM_ID }) .remainingAccounts(this.data.currentCompToken .slice(0, parseInt(this.data.numOfTokens.toString())).map(x => { return { pubkey: new web3_js_1.PublicKey(tokenList[parseInt(x.toString())].oracleAccount), isSigner: false, isWritable: false, }; })) .instruction()) .add(web3_js_1.ComputeBudgetProgram.setComputeUnitLimit({ units: config_1.ADDITIONAL_UNITS })).add(web3_js_1.ComputeBudgetProgram.setComputeUnitPrice({ microLamports: lamports }))); let transactions = [...preTransactions, ...swapTransactions]; let signedTransactions = yield (0, utils_1.signTransactionsWithWallet)(program.provider.connection, wallet, transactions.map(transaction => { return { transaction: transaction, signers: [] }; })); let _ = yield (0, utils_1.sendSignedTransactions)(program.provider.connection, signedTransactions.slice(0, preTransactions.length)); return yield (0, utils_1.sendSignedTransactions)(program.provider.connection, signedTransactions.slice(preTransactions.length, signedTransactions.length), swapTransactions.length); }); } } exports.Basket = Basket;