UNPKG

@symmetry-hq/baskets-sdk

Version:

Software Development Kit for interacting with Symmetry Baskets Program

622 lines (621 loc) 34.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()); }); }; Object.defineProperty(exports, "__esModule", { value: true }); exports.buildCreateBasketIx = buildCreateBasketIx; exports.buildEditBasketIx = buildEditBasketIx; exports.buildEditManagetIx = buildEditManagetIx; exports.buildCloseBasketIx = buildCloseBasketIx; exports.buildCreateMetadataIx = buildCreateMetadataIx; exports.buildUpdateMetadataIx = buildUpdateMetadataIx; exports.buildSetMetadataIx = buildSetMetadataIx; exports.buildBuyBasketIx = buildBuyBasketIx; exports.buildClaimTokensFromBuyStateIxs = buildClaimTokensFromBuyStateIxs; exports.buildMintFromBuyStateIx = buildMintFromBuyStateIx; exports.buildBuyBasketWithMultipleTokensIx = buildBuyBasketWithMultipleTokensIx; exports.buildBuyBasketWithSingleTokenIx = buildBuyBasketWithSingleTokenIx; exports.buildSellBasketToSingleTokenIx = buildSellBasketToSingleTokenIx; exports.buildSellBasketIx = buildSellBasketIx; exports.buildClaimTokensFromSellStateIxs = buildClaimTokensFromSellStateIxs; exports.buildUpdateCurrentWeightsIx = buildUpdateCurrentWeightsIx; exports.buildWithdrawBeforeRebalanceIx = buildWithdrawBeforeRebalanceIx; exports.buildDepositAfterRebalanceIx = buildDepositAfterRebalanceIx; exports.getSwbFeedsUpdateIxs = getSwbFeedsUpdateIxs; exports.updateOraclesTxs = updateOraclesTxs; const web3_js_1 = require("@solana/web3.js"); const config_1 = require("./config"); const crypto_js_1 = require("crypto-js"); const anchor_1 = require("@coral-xyz/anchor"); const utils_1 = require("./utils"); const splTokenHelpers_1 = require("./splTokenHelpers"); const js_1 = require("@metaplex-foundation/js"); const on_demand_1 = require("@switchboard-xyz/on-demand"); function buildCreateBasketIx(program, tokenList, basketParams) { return __awaiter(this, void 0, void 0, function* () { if (basketParams.composition.length == 0) throw new Error("Empty composition"); if (!basketParams.feeDelegate) basketParams.feeDelegate = basketParams.manager; let assetPool = [0]; let rules = []; let weightSum = 0; basketParams.composition.map(info => weightSum += info.weight); for (let i = 0; i < basketParams.composition.length; i++) { let tokenSettings = tokenList.find(token => token.tokenMint == basketParams.composition[i].token.toBase58()); if (!tokenSettings) throw new Error("Token not supported."); if (tokenSettings.id != 0) assetPool.push(tokenSettings.id); rules.push({ filterBy: config_1.FilterType.Fixed, filterDays: config_1.FilterTime.Day, sortBy: config_1.SortBy.DescendingOrder, totalWeight: Math.floor((basketParams.composition[i].weight * 1000) / weightSum), fixedAsset: tokenSettings.id, numAssets: 1, weightBy: config_1.WeightType.Fixed, weightDays: config_1.WeightTime.Day, weightExpo: 0, excludeAssets: [], ruleAssets: [], }); } let validateBasketParams = Object.assign(Object.assign({}, basketParams), { name: basketParams.name, symbol: basketParams.symbol, uri: basketParams.uri, manager: web3_js_1.PublicKey.default, hostPlatform: web3_js_1.PublicKey.default, hostPlatformFee: 0, activelyManaged: 1, assetPool: assetPool, rules: rules, refilterInterval: 7 * 24 * 3600, reweightInterval: 24 * 3600 }); yield (0, utils_1.validateCreateBasketParams)(validateBasketParams, tokenList, undefined, true); let tokens = rules.map(info => info.fixedAsset); let weights = rules.map(info => new anchor_1.BN(info.totalWeight)); while (tokens.length < 15) tokens.push(0); while (weights.length < 15) weights.push(new anchor_1.BN(0)); let message = basketParams.name + basketParams.symbol + basketParams.uri; let md5 = Array.from(Buffer.from((0, crypto_js_1.MD5)(message).toString(), "hex")); let seedPubkey = web3_js_1.Keypair.generate().publicKey; let [basketToken] = web3_js_1.PublicKey.findProgramAddressSync([Buffer.from("mint"), seedPubkey.toBuffer()], config_1.BASKETS_PROGRAM_ID); let [basketState] = web3_js_1.PublicKey.findProgramAddressSync([Buffer.from("basket"), seedPubkey.toBuffer()], config_1.BASKETS_PROGRAM_ID); if (basketParams.symbol.length < 3) throw new Error("Wrong symbol format"); if (basketParams.name.length < 3) throw new Error("Wrong name format"); const metaplex = js_1.Metaplex.make(program.provider.connection); const metadataAccount = metaplex.nfts().pdas().metadata({ mint: basketToken }); let createInstruction = yield program.methods .createBasket(basketParams.managerFee, basketParams.hostPlatformFee, basketParams.activelyManaged, new anchor_1.BN(basketParams.rebalanceInterval), basketParams.rebalanceThreshold, basketParams.rebalanceSlippage, basketParams.lpOffsetThreshold, [basketParams.disableRebalance ? 1 : 0, basketParams.disableLp ? 1 : 0], basketParams.composition.length, tokens, weights.map(x => x.toNumber()), { name: basketParams.name, symbol: basketParams.symbol, uri: basketParams.uri, }) .accounts({ manager: basketParams.manager, tokenList: config_1.TOKEN_LIST_ADDRESS, fundState: basketState, pdaAccount: config_1.BASKETS_PROGRAM_PDA, fundToken: basketToken, createFeeSweeper: config_1.CREATE_FEE_ACCOUNT, metadataAccount: metadataAccount, metadataProgram: new web3_js_1.PublicKey("metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s"), systemProgram: web3_js_1.SystemProgram.programId, tokenProgram: splTokenHelpers_1.TOKEN_PROGRAM_ID, rent: web3_js_1.SYSVAR_RENT_PUBKEY, host: basketParams.hostPlatform, feeDelegate: basketParams.feeDelegate, seedPubkey: seedPubkey, }) .instruction(); return createInstruction; }); } function buildEditBasketIx(program, tokenList, basketObj, basketParams) { return __awaiter(this, void 0, void 0, function* () { if (basketParams.composition.length == 0) throw new Error("Empty composition"); if (!basketParams.feeDelegate) basketParams.feeDelegate = basketObj.data.feeDelegate; if (!basketParams.composition) { basketParams.composition = []; for (let i = 0; i < basketObj.data.numRuleTokens.toNumber(); i++) if (basketObj.data.ruleTokenWeights[i].toNumber() != 0) basketParams.composition.push({ token: new web3_js_1.PublicKey(tokenList[basketObj.data.ruleTokens[i].toNumber()].tokenMint), weight: basketObj.data.ruleTokenWeights[i].toNumber() }); } let assetPool = [0]; let rules = []; let weightSum = 0; basketParams.composition.map(info => weightSum += info.weight); for (let i = 0; i < basketParams.composition.length; i++) { let tokenSettings = tokenList.find(//@ts-ignore //@ts-ignore token => token.tokenMint == basketParams.composition[i].token.toBase58()); if (!tokenSettings) throw new Error("Token not supported."); if (tokenSettings.id != 0) assetPool.push(tokenSettings.id); rules.push({ filterBy: config_1.FilterType.Fixed, filterDays: config_1.FilterTime.Day, sortBy: config_1.SortBy.DescendingOrder, totalWeight: Math.floor((basketParams.composition[i].weight * 1000) / weightSum), fixedAsset: tokenSettings.id, numAssets: 1, weightBy: config_1.WeightType.Fixed, weightDays: config_1.WeightTime.Day, weightExpo: 0, excludeAssets: [], ruleAssets: [], }); } //@ts-ignore let validateBasketParams = Object.assign(Object.assign({}, basketParams), { name: "", symbol: "", uri: "", manager: web3_js_1.PublicKey.default, hostPlatform: web3_js_1.PublicKey.default, hostPlatformFee: 0, activelyManaged: 1, assetPool: assetPool, rules: rules, refilterInterval: 7 * 24 * 3600, reweightInterval: 24 * 3600 }); yield (0, utils_1.validateCreateBasketParams)(validateBasketParams, tokenList, basketObj.ownAddress, true); let tokens = rules.map(info => info.fixedAsset); let weights = rules.map(info => new anchor_1.BN(info.totalWeight)); while (tokens.length < 15) tokens.push(0); while (weights.length < 15) weights.push(new anchor_1.BN(0)); return yield program.methods .editBasket(basketParams.managerFee, new anchor_1.BN(basketParams.rebalanceInterval), basketParams.rebalanceThreshold, basketParams.rebalanceSlippage, (basketParams.lpOffsetThreshold), [basketParams.disableRebalance ? 1 : 0, basketParams.disableLp ? 1 : 0], rules.length, tokens, weights.map(x => x.toNumber())) .accounts({ fundState: basketObj.ownAddress, manager: basketObj.data.manager, tokenList: config_1.TOKEN_LIST_ADDRESS, feeDelegate: basketParams.feeDelegate, }) .instruction(); }); } function buildEditManagetIx(program, basketState, newManager) { return __awaiter(this, void 0, void 0, function* () { return yield program.methods .editManager(newManager) .accounts({ manager: basketState.data.manager, fundState: basketState.ownAddress, }) .instruction(); }); } function buildCloseBasketIx(program, basketState) { return __awaiter(this, void 0, void 0, function* () { return yield program.methods.closeBasket() .accounts({ manager: basketState.data.manager, fundState: basketState.ownAddress, fundToken: basketState.data.fundToken, pdaAccount: config_1.BASKETS_PROGRAM_PDA, systemProgram: web3_js_1.SystemProgram.programId, tokenProgram: splTokenHelpers_1.TOKEN_PROGRAM_ID }) .instruction(); }); } function buildCreateMetadataIx(program, creator, basket, tokenMint, metadata) { return __awaiter(this, void 0, void 0, function* () { let { symbol, name, uri } = metadata; if (symbol.length < 3 || symbol.length > 10) throw new Error("Wrong symbol format"); if (name.length < 3 || name.length > 60) throw new Error("Wrong name format"); const metaplex = js_1.Metaplex.make(program.provider.connection); const metadataAccount = metaplex.nfts().pdas().metadata({ mint: tokenMint }); return yield program.methods.createFundTokenMintMetadata({ name: name, symbol: symbol, uri: uri, }).accounts({ manager: creator, fundToken: tokenMint, fundState: basket, updateAuthority: config_1.BASKETS_PROGRAM_PDA, metadataAccount: metadataAccount, metadataProgram: new web3_js_1.PublicKey("metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s"), systemProgram: web3_js_1.SystemProgram.programId, rent: web3_js_1.SYSVAR_RENT_PUBKEY, }).instruction(); }); } function buildUpdateMetadataIx(program, creator, basket, tokenMint, metadata) { return __awaiter(this, void 0, void 0, function* () { let { symbol, name, uri } = metadata; if (symbol.length < 3 || symbol.length > 10) throw new Error("Wrong symbol format"); if (name.length < 3 || name.length > 60) throw new Error("Wrong name format"); const metaplex = js_1.Metaplex.make(program.provider.connection); const metadataAccount = metaplex.nfts().pdas().metadata({ mint: tokenMint }); return yield program.methods.updateFundTokenMintMetadata({ name: name, symbol: symbol, uri: uri, }).accounts({ manager: creator, fundToken: tokenMint, fundState: basket, updateAuthority: config_1.BASKETS_PROGRAM_PDA, metadataAccount: metadataAccount, metadataProgram: new web3_js_1.PublicKey("metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s"), systemProgram: web3_js_1.SystemProgram.programId, rent: web3_js_1.SYSVAR_RENT_PUBKEY, }).instruction(); }); } function buildSetMetadataIx(program, basket, metadata) { return __awaiter(this, void 0, void 0, function* () { if (basket.data.symbolLength == 0) return yield buildCreateMetadataIx(program, basket.data.manager, basket.ownAddress, basket.data.fundToken, metadata); else return yield buildUpdateMetadataIx(program, basket.data.manager, basket.ownAddress, basket.data.fundToken, metadata); }); } function buildBuyBasketIx(program, tokenList, user, basketObj, amount) { return __awaiter(this, void 0, void 0, function* () { let buyerUsdcTokenAccount = (0, splTokenHelpers_1.getAssociatedTokenAddressSync)(new web3_js_1.PublicKey(tokenList[0].tokenMint), user, true); let managerUsdcTokenAccount = (0, splTokenHelpers_1.getAssociatedTokenAddressSync)(new web3_js_1.PublicKey(tokenList[0].tokenMint), basketObj.data.feeDelegate.toBase58() == web3_js_1.PublicKey.default.toBase58() ? basketObj.data.manager : basketObj.data.feeDelegate, true); let hostUsdcTokenAccount = (0, splTokenHelpers_1.getAssociatedTokenAddressSync)(new web3_js_1.PublicKey(tokenList[0].tokenMint), basketObj.data.hostPubkey, true); let buyerBasketTokenAccount = (0, splTokenHelpers_1.getAssociatedTokenAddressSync)(basketObj.data.fundToken, user, true); let seedPubkey = web3_js_1.Keypair.generate().publicKey; let [buyState] = web3_js_1.PublicKey.findProgramAddressSync([Buffer.from("buy"), seedPubkey.toBuffer()], config_1.BASKETS_PROGRAM_ID); return yield program.methods .buyFund(new anchor_1.BN(amount * 10 ** tokenList[0].decimals)) .accounts({ buyer: user, fundState: basketObj.ownAddress, fundToken: basketObj.data.fundToken, tokenList: config_1.TOKEN_LIST_ADDRESS, pdaAccount: config_1.BASKETS_PROGRAM_PDA, pdaUsdcAccount: new web3_js_1.PublicKey(tokenList[0].pdaTokenAccount), buyerUsdcAccount: buyerUsdcTokenAccount, managerUsdcAccount: managerUsdcTokenAccount, smfFeeAccount: config_1.BUY_FEE_ACCOUNT, hostUsdcAccount: hostUsdcTokenAccount, buyerFundTokenAccount: buyerBasketTokenAccount, buyState: buyState, systemProgram: web3_js_1.SystemProgram.programId, tokenProgram: splTokenHelpers_1.TOKEN_PROGRAM_ID, rent: web3_js_1.SYSVAR_RENT_PUBKEY, associatedTokenProgram: splTokenHelpers_1.ASSOCIATED_TOKEN_PROGRAM_ID, seedPubkey: seedPubkey, }) .instruction(); }); } function buildClaimTokensFromBuyStateIxs(program, tokenList, feePayer, basketObj, buyStateObj) { return __awaiter(this, void 0, void 0, function* () { let ixs = []; for (let i = 0; i < buyStateObj.data.token.length; i++) { if (parseInt(buyStateObj.data.amountBought[i].toString()) == 0 && i != 0) continue; let tokenId = buyStateObj.data.token[i].toNumber(); let userTokenAccount = (0, splTokenHelpers_1.getAssociatedTokenAddressSync)(new web3_js_1.PublicKey(tokenList[tokenId].tokenMint), buyStateObj.data.buyer, true); ixs.push(yield program.methods .claimTokenFromBuyState(new anchor_1.BN(tokenId)) .accounts({ signer: feePayer, buyer: buyStateObj.data.buyer, fundState: basketObj.ownAddress, buyState: buyStateObj.ownAddress, tokenList: config_1.TOKEN_LIST_ADDRESS, buyerTokenAccount: userTokenAccount, pdaTokenAccount: new web3_js_1.PublicKey(tokenList[tokenId].pdaTokenAccount), pdaAccount: config_1.BASKETS_PROGRAM_PDA, systemProgram: web3_js_1.SystemProgram.programId, tokenProgram: splTokenHelpers_1.TOKEN_PROGRAM_ID, }) .instruction()); } return ixs; }); } function buildMintFromBuyStateIx(program, tokenList, feePayer, basketObj, buyStateObj) { return __awaiter(this, void 0, void 0, function* () { let accounts = []; for (let i = 0; i < basketObj.data.numOfTokens.toNumber(); i++) accounts.push({ pubkey: new web3_js_1.PublicKey(tokenList[basketObj.data.currentCompToken[i].toNumber()].oracleAccount), isSigner: false, isWritable: false, }); return yield program.methods .mintFund() .accounts({ signer: feePayer, buyer: buyStateObj.data.buyer, fundState: basketObj.ownAddress, tokenList: config_1.TOKEN_LIST_ADDRESS, buyState: buyStateObj.ownAddress, oracleSol: new web3_js_1.PublicKey(tokenList[1].oracleAccount), pdaAccount: config_1.BASKETS_PROGRAM_PDA, buyerFundTokenAccount: buyStateObj.data.buyerFundTokenAccount, fundToken: basketObj.data.fundToken, systemProgram: web3_js_1.SystemProgram.programId, tokenProgram: splTokenHelpers_1.TOKEN_PROGRAM_ID }) .remainingAccounts(accounts) .instruction(); }); } function buildBuyBasketWithMultipleTokensIx(program, tokenList, user, basketObj, contribution) { return __awaiter(this, void 0, void 0, function* () { let tokenMints = basketObj.data.currentCompToken.slice(0, basketObj.data.numOfTokens.toNumber()) .map(token => new web3_js_1.PublicKey(tokenList[token.toNumber()].tokenMint)); tokenMints.push(basketObj.data.fundToken); let buyerAtas = tokenMints.map(token => (0, splTokenHelpers_1.getAssociatedTokenAddressSync)(token, user, true)); for (let i = 0; i < contribution.length; i++) { let inBasket = basketObj.data.currentCompToken.find(info => tokenList[info.toNumber()].tokenMint == contribution[i].token.toBase58()); if (!inBasket) throw new Error("Token not present in the current compostion."); } let amountsBN = []; let remainingAccounts = []; for (let i = 0; i < basketObj.data.numOfTokens.toNumber(); i++) { let tokenSettings = tokenList[basketObj.data.currentCompToken[i].toNumber()]; let tokenContribution = contribution.find(info => info.token.toBase58() == tokenSettings.tokenMint); let amount = (tokenContribution) ? tokenContribution.amount : 0; amountsBN.push(new anchor_1.BN(Math.floor(amount * 10 ** tokenSettings.decimals))); remainingAccounts.push({ pubkey: new web3_js_1.PublicKey(tokenSettings.oracleAccount), isSigner: false, isWritable: false, }); remainingAccounts.push({ pubkey: buyerAtas[i], isSigner: false, isWritable: true, }); remainingAccounts.push({ pubkey: new web3_js_1.PublicKey(tokenSettings.pdaTokenAccount), isSigner: false, isWritable: true, }); } let buyerBasketTokenAccount = buyerAtas[buyerAtas.length - 1]; while (amountsBN.length < 20) amountsBN.push(new anchor_1.BN(0)); return yield program.methods .instantMint(amountsBN) .accounts({ authority: user, buyerFundTokenAccount: buyerBasketTokenAccount, fundToken: basketObj.data.fundToken, fundState: basketObj.ownAddress, tokenList: config_1.TOKEN_LIST_ADDRESS, pdaAccount: config_1.BASKETS_PROGRAM_PDA, oracleSol: new web3_js_1.PublicKey(tokenList[1].oracleAccount), tokenProgram: splTokenHelpers_1.TOKEN_PROGRAM_ID, }) .remainingAccounts(remainingAccounts) .instruction(); }); } function buildBuyBasketWithSingleTokenIx(program, tokenList, user, basketObj, contributionToken, contributionAmount) { return __awaiter(this, void 0, void 0, function* () { let tokenSettings = tokenList.find(info => info.tokenMint == contributionToken.toBase58()); if (!tokenSettings || !basketObj.data.currentCompToken.find(x => x.toNumber() == (tokenSettings === null || tokenSettings === void 0 ? void 0 : tokenSettings.id))) throw new Error("Token not present in the current compostion."); let buyerTokenAccount = (0, splTokenHelpers_1.getAssociatedTokenAddressSync)(contributionToken, user, true); let buyerBasketTokenAccount = (0, splTokenHelpers_1.getAssociatedTokenAddressSync)(basketObj.data.fundToken, user, true); let symmetryFeeAccount = (0, splTokenHelpers_1.getAssociatedTokenAddressSync)(contributionToken, config_1.BUY_FEE_WALLET); let hostFeeAccount = (0, splTokenHelpers_1.getAssociatedTokenAddressSync)(contributionToken, basketObj.data.hostPubkey, true); let managerFeeAccount = (0, splTokenHelpers_1.getAssociatedTokenAddressSync)(contributionToken, basketObj.data.manager, true); let remainingAccounts = []; for (let i = 0; i < basketObj.data.numOfTokens.toNumber(); i++) { let tokenSettings = tokenList[basketObj.data.currentCompToken[i].toNumber()]; remainingAccounts.push({ pubkey: new web3_js_1.PublicKey(tokenSettings.oracleAccount), isSigner: false, isWritable: false, }); } return yield program.methods .singleTokenDeposit(tokenSettings === null || tokenSettings === void 0 ? void 0 : tokenSettings.id, new anchor_1.BN(contributionAmount * 10 ** tokenSettings.decimals)) .accounts({ authority: user, fundState: basketObj.ownAddress, fundToken: basketObj.data.fundToken, buyerTokenAccount: buyerTokenAccount, buyerFundTokenAccount: buyerBasketTokenAccount, pdaAccount: config_1.BASKETS_PROGRAM_PDA, pdaTokenAccount: new web3_js_1.PublicKey(tokenSettings.pdaTokenAccount), symmetryFeeAccount: symmetryFeeAccount, hostFeeAccount: hostFeeAccount, managerFeeAccount: managerFeeAccount, oracleAccount: new web3_js_1.PublicKey(tokenSettings.oracleAccount), oracleSol: new web3_js_1.PublicKey(tokenList[1].oracleAccount), tokenList: config_1.TOKEN_LIST_ADDRESS, tokenProgram: splTokenHelpers_1.TOKEN_PROGRAM_ID, }) .remainingAccounts(remainingAccounts) .instruction(); }); } function buildSellBasketToSingleTokenIx(program, tokenList, user, basketObj, withdrawToken, amount) { return __awaiter(this, void 0, void 0, function* () { let tokenSettings = tokenList.find(info => info.tokenMint == withdrawToken.toBase58()); if (!tokenSettings || !basketObj.data.currentCompToken.find(x => x.toNumber() == (tokenSettings === null || tokenSettings === void 0 ? void 0 : tokenSettings.id))) throw new Error("Token not present in the current compostion."); let userBasketTokenAccount = (0, splTokenHelpers_1.getAssociatedTokenAddressSync)(basketObj.data.fundToken, user, true); let userTokenAccount = (0, splTokenHelpers_1.getAssociatedTokenAddressSync)(withdrawToken, user, true); let remainingAccounts = []; for (let i = 0; i < basketObj.data.numOfTokens.toNumber(); i++) { let tokenSettings = tokenList[basketObj.data.currentCompToken[i].toNumber()]; remainingAccounts.push({ pubkey: new web3_js_1.PublicKey(tokenSettings.oracleAccount), isSigner: false, isWritable: false, }); } return yield program.methods .instantBurn(new anchor_1.BN(amount * 10 ** 6), tokenSettings.id) .accounts({ seller: user, pdaAccount: config_1.BASKETS_PROGRAM_PDA, fundState: basketObj.ownAddress, fundToken: basketObj.data.fundToken, sellerFundTokenAccount: userBasketTokenAccount, withdrawTokenMint: withdrawToken, sellerTokenAccount: userTokenAccount, pdaTokenAccount: new web3_js_1.PublicKey(tokenSettings === null || tokenSettings === void 0 ? void 0 : tokenSettings.pdaTokenAccount), tokenList: config_1.TOKEN_LIST_ADDRESS, systemProgram: web3_js_1.SystemProgram.programId, tokenProgram: splTokenHelpers_1.TOKEN_PROGRAM_ID, }) .remainingAccounts(remainingAccounts) .instruction(); }); } function buildSellBasketIx(program, user, basketObj, amount, rebalance) { return __awaiter(this, void 0, void 0, function* () { let userBasketTokenAccount = (0, splTokenHelpers_1.getAssociatedTokenAddressSync)(basketObj.data.fundToken, user, true); let seedPubkey = web3_js_1.Keypair.generate().publicKey; let [sellState] = web3_js_1.PublicKey.findProgramAddressSync([Buffer.from("sell"), seedPubkey.toBuffer()], config_1.BASKETS_PROGRAM_ID); return yield program.methods .sellFund(new anchor_1.BN(amount * 10 ** 6), new anchor_1.BN(rebalance)) .accounts({ seller: user, fundState: basketObj.ownAddress, pdaAccount: config_1.BASKETS_PROGRAM_PDA, newFundState: sellState, sellerFundTokenAccount: userBasketTokenAccount, fundToken: basketObj.data.fundToken, systemProgram: web3_js_1.SystemProgram.programId, tokenProgram: splTokenHelpers_1.TOKEN_PROGRAM_ID, rent: web3_js_1.SYSVAR_RENT_PUBKEY, seedPubkey: seedPubkey, }) .instruction(); }); } function buildClaimTokensFromSellStateIxs(program, tokenList, feePayer, basketObj) { return __awaiter(this, void 0, void 0, function* () { let basketOwner = basketObj.data.manager; let ixs = []; for (let i = 0; i < basketObj.data.numOfTokens.toNumber(); i++) { if (parseInt(basketObj.data.currentCompAmount[i].toString()) == 0 && i != 0) continue; let tokenId = basketObj.data.currentCompToken[i].toNumber(); let userTokenAccount = (0, splTokenHelpers_1.getAssociatedTokenAddressSync)(new web3_js_1.PublicKey(tokenList[tokenId].tokenMint), basketOwner, true); ixs.push(yield program.methods .claimToken(new anchor_1.BN(tokenId)) .accounts({ signer: feePayer, manager: basketOwner, fundState: basketObj.ownAddress, tokenList: config_1.TOKEN_LIST_ADDRESS, sellerTokenAccount: userTokenAccount, pdaTokenAccount: new web3_js_1.PublicKey(tokenList[tokenId].pdaTokenAccount), pdaAccount: config_1.BASKETS_PROGRAM_PDA, systemProgram: web3_js_1.SystemProgram.programId, tokenProgram: splTokenHelpers_1.TOKEN_PROGRAM_ID, }) .instruction()); } return ixs; }); } function buildUpdateCurrentWeightsIx(program, basket, tokenList) { return __awaiter(this, void 0, void 0, function* () { let accounts = []; for (let i = 0; i < basket.data.numOfTokens.toNumber(); i++) accounts.push({ pubkey: new web3_js_1.PublicKey(tokenList[basket.data.currentCompToken[i].toNumber()].oracleAccount), isSigner: false, isWritable: false, }); return yield program.methods .updateCurrentWeights() .accounts({ fundState: basket.ownAddress, tokenList: config_1.TOKEN_LIST_ADDRESS, oracleSol: new web3_js_1.PublicKey(tokenList[1].oracleAccount), }) .remainingAccounts(accounts) .instruction(); }); } function buildWithdrawBeforeRebalanceIx(program, feePayer, basket, tokenList, fromToken, toToken, fromAmount) { return __awaiter(this, void 0, void 0, function* () { return yield program.methods.withdrawBeforeRebalance(fromToken, toToken, new anchor_1.BN(fromAmount)).accounts({ signer: feePayer, basketState: basket.ownAddress, tokenList: config_1.TOKEN_LIST_ADDRESS, oracleSol: new web3_js_1.PublicKey(tokenList[1].oracleAccount), oracleTokenFrom: new web3_js_1.PublicKey(tokenList[fromToken].oracleAccount), oracleTokenTo: new web3_js_1.PublicKey(tokenList[toToken].oracleAccount), pdaAccount: config_1.BASKETS_PROGRAM_PDA, pdaTokenFrom: new web3_js_1.PublicKey(tokenList[fromToken].pdaTokenAccount), pdaTokenTo: new web3_js_1.PublicKey(tokenList[toToken].pdaTokenAccount), signerTokenFrom: (0, splTokenHelpers_1.getAssociatedTokenAddressSync)(new web3_js_1.PublicKey(tokenList[fromToken].tokenMint), feePayer, true), signerTokenTo: (0, splTokenHelpers_1.getAssociatedTokenAddressSync)(new web3_js_1.PublicKey(tokenList[toToken].tokenMint), feePayer, true), fromTokenMint: new web3_js_1.PublicKey(tokenList[fromToken].tokenMint), toTokenMint: new web3_js_1.PublicKey(tokenList[toToken].tokenMint), rebalanceState: web3_js_1.PublicKey.findProgramAddressSync([Buffer.from("flashrebalance")], config_1.BASKETS_PROGRAM_ID)[0], tokenProgram: splTokenHelpers_1.TOKEN_PROGRAM_ID, associatedTokenProgram: splTokenHelpers_1.ASSOCIATED_TOKEN_PROGRAM_ID, systemProgram: web3_js_1.SystemProgram.programId, rent: web3_js_1.SYSVAR_RENT_PUBKEY, instructionsSysvar: web3_js_1.SYSVAR_INSTRUCTIONS_PUBKEY, }).instruction(); }); } function buildDepositAfterRebalanceIx(program, feePayer, basket, tokenList, toToken) { return __awaiter(this, void 0, void 0, function* () { return yield program.methods.depositAfterRebalance().accounts({ signer: feePayer, basketState: basket.ownAddress, tokenList: config_1.TOKEN_LIST_ADDRESS, oracleSol: new web3_js_1.PublicKey(tokenList[1].oracleAccount), oracleTokenTo: new web3_js_1.PublicKey(tokenList[toToken].oracleAccount), pdaAccount: config_1.BASKETS_PROGRAM_PDA, pdaTokenTo: new web3_js_1.PublicKey(tokenList[toToken].pdaTokenAccount), signerTokenTo: (0, splTokenHelpers_1.getAssociatedTokenAddressSync)(new web3_js_1.PublicKey(tokenList[toToken].tokenMint), feePayer, true), rebalanceState: web3_js_1.PublicKey.findProgramAddressSync([Buffer.from("flashrebalance")], config_1.BASKETS_PROGRAM_ID)[0], rebalanceFeeAccount: (0, splTokenHelpers_1.getAssociatedTokenAddressSync)(new web3_js_1.PublicKey(tokenList[toToken].tokenMint), config_1.REBALANCE_FEE_WALLET, true), tokenProgram: splTokenHelpers_1.TOKEN_PROGRAM_ID, systemProgram: web3_js_1.SystemProgram.programId, }).instruction(); }); } function getSwbFeedsUpdateIxs(program_1, payer_1, feeds_1) { return __awaiter(this, arguments, void 0, function* (program, payer, feeds, numSignatures = 2) { let maxUpdates = Math.floor(18 / numSignatures); let ixPromises = []; for (let i = 0; i < feeds.length; i += maxUpdates) { let promise = on_demand_1.PullFeed.fetchUpdateManyIx(program, { feeds: feeds.slice(i, i + maxUpdates), numSignatures: numSignatures, payer: payer, }); ixPromises.push(promise); } return yield Promise.all(ixPromises); }); } function updateOraclesTxs(swbProgram, payer, feeds, lamports) { return __awaiter(this, void 0, void 0, function* () { let res = yield getSwbFeedsUpdateIxs(swbProgram, payer, feeds).catch((e) => { console.log("Couldn't fetch SWB oracle update txs", e.message); return []; }); return res.map(update => { return { payerKey: payer, instructions: [ update[0], web3_js_1.ComputeBudgetProgram.setComputeUnitLimit({ units: config_1.ADDITIONAL_UNITS }), web3_js_1.ComputeBudgetProgram.setComputeUnitPrice({ microLamports: lamports }) ], lookupTables: update[1] }; }); }); }