@symmetry-hq/baskets-sdk
Version:
Software Development Kit for interacting with Symmetry Baskets Program
659 lines (658 loc) • 43.1 kB
JavaScript
"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;