@symmetry-hq/baskets-sdk
Version:
Software Development Kit for interacting with Symmetry Baskets Program
622 lines (621 loc) • 34.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());
});
};
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]
};
});
});
}