import BN from 'bn.js'; import { ASSOCIATED_TOKEN_PROGRAM_ID, getAssociatedTokenAddressSync, TOKEN_2022_PROGRAM_ID, TOKEN_PROGRAM_ID } from '@solana/spl-token'; import { AccountMeta, PublicKey, SystemProgram, TransactionInstruction } from '@solana/web3.js'; import { ADDRESS_LOOKUP_TABLE_PROGRAM_ID, BASKETS_V3_PROGRAM_ID, MAX_ORACLES_PER_TOKEN, MAX_SUPPORTED_TOKENS_PER_BASKET, METADATA_PROGRAM_ID } from '../../constants'; import { Basket } from '../../layouts/basket'; import { AuthorityBitmasks, AuthorityBitmasksLayout, AutomationSettings, AutomationSettingsLayout, EditAddTokenDelay, EditAddTokenDelayLayout, EditCreator, EditCreatorLayout, EditMakeDirectSwapDelay, EditMakeDirectSwapDelayLayout, EditUpdateWeightsDelay, EditUpdateWeightsDelayLayout, FeeSettings, FeeSettingsLayout, LpSettings, LpSettingsLayout, MakeDirectSwap, MakeDirectSwapLayout, ManagerSettings, ManagerSettingsLayout, MAX_MANAGERS_PER_BASKET, MetadataParams, MetadataSettings, MetadataSettingsLayout, ScheduleSettings, ScheduleSettingsLayout, UpdateWeights, UpdateWeightsLayout } from '../../layouts/config'; import { DEFAULT_ORACLE_SETTINGS, MAX_ACCOUNTS_PER_ORACLE, ORACLE_TYPES_STRINGS, OracleAggregator, OracleAggregatorLayout, OracleData, Quote, Side } from '../../layouts/oracle'; import { getAta, getBountyVaultPda, getGlobalConfigPda, getIntentPda, getMetadataAccount, serializeString } from '../pda'; import { AddOrEditTokenInput, EditAddTokenSettings, EditAutomationSettings, EditCreatorSettings, EditCustomRebalanceSettings, EditDepositsSettings, EditFeeSettings, EditForceRebalanceSettings, EditLpSettings, EditMakeDirectSwapSettings, EditManagerSettings, EditMetadataSettings, EditScheduleSettings, EditUpdateWeightsSettings, MakeDirectSwapInput, Settings, TaskType, UpdateWeightsInput } from '../../layouts/intents/intent'; import Decimal from 'decimal.js'; import { decimalToFraction } from '../../layouts/fraction'; import { computeTokenMintsHash } from '../../states/basket'; const EDIT_PRIVATE_BASKET_SETTINGS_DISCRIMINATOR = Buffer.from([202,54,138,17,3,104,128,229]); const CREATE_EDIT_BASKET_INTENT_DISCRIMINATOR = Buffer.from([82, 150, 58, 227, 153, 129, 20, 30]); const EDIT_BASKET_DISCRIMINATOR = Buffer.from([156, 31, 4, 39, 248, 29, 55, 220]); const CANCEL_INTENT_DISCRIMINATOR = Buffer.from([181, 103, 27, 100, 84, 89, 70, 236]); export function editPrivateBasketSettingsIx( params: { creator: PublicKey, basket: PublicKey, mint: PublicKey, basketType: number, scheduleBytes: ScheduleSettings, feeSettingsBytes: FeeSettings, managerSettingsBytes: ManagerSettings, automationSettingsBytes: AutomationSettings, lpSettingsBytes: LpSettings, authorityBitmasks: AuthorityBitmasks, metadataParams: MetadataParams, depositsAreAllowed: number, forceRebalanceIsAllowed: number, customRebalanceIsAllowed: number, }): TransactionInstruction { let metadataAccount = getMetadataAccount(params.mint); let globalConfig = getGlobalConfigPda(); let managerSettingsBuffer = Buffer.alloc(ManagerSettingsLayout.span); ManagerSettingsLayout.encode(params.managerSettingsBytes, managerSettingsBuffer); let authorityBitmasksBuffer = Buffer.alloc(AuthorityBitmasksLayout.span); AuthorityBitmasksLayout.encode(params.authorityBitmasks, authorityBitmasksBuffer); let feeSettingsBuffer = Buffer.alloc(FeeSettingsLayout.span); FeeSettingsLayout.encode(params.feeSettingsBytes, feeSettingsBuffer); let scheduleSettingsBuffer = Buffer.alloc(ScheduleSettingsLayout.span); ScheduleSettingsLayout.encode(params.scheduleBytes, scheduleSettingsBuffer); let automationSettingsBuffer = Buffer.alloc(AutomationSettingsLayout.span); AutomationSettingsLayout.encode(params.automationSettingsBytes, automationSettingsBuffer); let lpSettingsBuffer = Buffer.alloc(LpSettingsLayout.span); LpSettingsLayout.encode(params.lpSettingsBytes, lpSettingsBuffer); const data = Buffer.concat([ EDIT_PRIVATE_BASKET_SETTINGS_DISCRIMINATOR, Buffer.from([params.basketType]), managerSettingsBuffer, authorityBitmasksBuffer, feeSettingsBuffer, scheduleSettingsBuffer, automationSettingsBuffer, lpSettingsBuffer, serializeString(params.metadataParams.name), serializeString(params.metadataParams.symbol), serializeString(params.metadataParams.uri), Buffer.from([params.depositsAreAllowed]), Buffer.from([params.forceRebalanceIsAllowed]), Buffer.from([params.customRebalanceIsAllowed]), ]); const keys = [ { pubkey: params.creator, isSigner: true, isWritable: true }, { pubkey: params.basket, isSigner: false, isWritable: true }, { pubkey: metadataAccount, isSigner: false, isWritable: true }, { pubkey: globalConfig, isSigner: false, isWritable: false }, { pubkey: METADATA_PROGRAM_ID, isSigner: false, isWritable: false } ]; return new TransactionInstruction({ keys, programId: BASKETS_V3_PROGRAM_ID, data }); } export function createEditBasketIntentIx(params: { manager: PublicKey; basket: Basket; intent: PublicKey; intentSeedArray: Uint8Array; editType: TaskType; editData: Settings; activationTimestamp: BN; expirationTimestamp: BN; minBounty: BN; maxBounty: BN; tokenProgram? : PublicKey; }): TransactionInstruction { const { manager, basket, intent, intentSeedArray, editType, editData, activationTimestamp, expirationTimestamp, minBounty, maxBounty, tokenProgram, } = params; let globalConfig = getGlobalConfigPda(); let bountyVault = getBountyVaultPda(); let bountyMint = basket.settings.bountyMint; let managerBountyATA = getAta(manager, bountyMint); let bountyVaultATA = getAta(bountyVault, bountyMint); const intentSeedArrayBuf = Buffer.from(intentSeedArray); const editTypeBuf = Buffer.from([editType]); let editDataBuf = Buffer.alloc(260); let additionalAccounts: AccountMeta[] = []; switch (editType) { case TaskType.EditCreator: // 1 let creatorSettings = (editData as EditCreatorSettings); let editCreator: EditCreator = { creator: new PublicKey(creatorSettings.creator), } EditCreatorLayout.encode(editCreator, editDataBuf); break; case TaskType.EditManagerSettings: // 2 let managerSettings = (editData as EditManagerSettings); let managersWeights = managerSettings.managers.map((manager) => manager.fee_split_weight_bps); let managers = managerSettings.managers.map((manager) => new PublicKey(manager.pubkey)); while (managers.length < MAX_MANAGERS_PER_BASKET) { managers.push(PublicKey.default); managersWeights.push(0); } let startIndex = 0; for (let i = 0; i < MAX_MANAGERS_PER_BASKET; i++) { editDataBuf.writeUInt16LE(managersWeights[i], startIndex); if (!managers[i].equals(PublicKey.default)) { additionalAccounts.push({ pubkey: managers[i], isWritable: true, isSigner: false }); } startIndex += 2; } let authorityBitmasks: AuthorityBitmasks = { scheduleAuthorityBitmask: 0, feesAuthorityBitmask: 0, managersAuthorityBitmask: 0, automationAuthorityBitmask: 0, lpAuthorityBitmask: 0, metadataAuthorityBitmask: 0, depositsAuthorityBitmask: 0, forceRebalanceAuthorityBitmask: 0, customRebalanceAuthorityBitmask: 0, addTokenIntentAuthorityBitmask: 0, updateWeightsIntentAuthorityBitmask: 0, makeDirectSwapIntentAuthorityBitmask: 0, extraData: 0, extraData1: 0, extraData2: 0, } for (let i = 0; i < managerSettings.managers.length; i++) { let bitPow = (2 ** i); authorityBitmasks.managersAuthorityBitmask |= managerSettings.managers[i].authorities.managers ? bitPow : 0; authorityBitmasks.feesAuthorityBitmask |= managerSettings.managers[i].authorities.fees ? bitPow : 0; authorityBitmasks.scheduleAuthorityBitmask |= managerSettings.managers[i].authorities.schedule ? bitPow : 0; authorityBitmasks.automationAuthorityBitmask |= managerSettings.managers[i].authorities.automation ? bitPow : 0; authorityBitmasks.lpAuthorityBitmask |= managerSettings.managers[i].authorities.lp ? bitPow : 0; authorityBitmasks.metadataAuthorityBitmask |= managerSettings.managers[i].authorities.metadata ? bitPow : 0; authorityBitmasks.depositsAuthorityBitmask |= managerSettings.managers[i].authorities.deposits ? bitPow : 0; authorityBitmasks.forceRebalanceAuthorityBitmask |= managerSettings.managers[i].authorities.force_rebalance ? bitPow : 0; authorityBitmasks.customRebalanceAuthorityBitmask |= managerSettings.managers[i].authorities.custom_rebalance ? bitPow : 0; authorityBitmasks.addTokenIntentAuthorityBitmask |= managerSettings.managers[i].authorities.add_token ? bitPow : 0; authorityBitmasks.updateWeightsIntentAuthorityBitmask |= managerSettings.managers[i].authorities.update_weights ? bitPow : 0; authorityBitmasks.makeDirectSwapIntentAuthorityBitmask |= managerSettings.managers[i].authorities.make_direct_swap ? bitPow : 0; } let authorityBitmasksBuffer = Buffer.alloc(AuthorityBitmasksLayout.span); AuthorityBitmasksLayout.encode(authorityBitmasks, authorityBitmasksBuffer); editDataBuf.set(authorityBitmasksBuffer, startIndex); startIndex += AuthorityBitmasksLayout.span; let modificationDelayBN = new BN(managerSettings.modification_delay); editDataBuf.writeBigUint64LE(BigInt(modificationDelayBN.toString()), startIndex); startIndex += 8; break; case TaskType.EditFeeSettings: // 3 let feeSettings = (editData as EditFeeSettings); let editFeeSettings: FeeSettings = { hostDepositFeeBps: 0, hostWithdrawFeeBps: 0, hostManagementFeeBps: 0, hostPerformanceFeeBps:0, creatorDepositFeeBps: feeSettings.creator_deposit_fee_bps, creatorWithdrawFeeBps: feeSettings.creator_withdraw_fee_bps, creatorManagementFeeBps: feeSettings.creator_management_fee_bps, creatorPerformanceFeeBps: feeSettings.creator_performance_fee_bps, managersDepositFeeBps: feeSettings.managers_deposit_fee_bps, managersWithdrawFeeBps: feeSettings.managers_withdraw_fee_bps, managersManagementFeeBps: feeSettings.managers_management_fee_bps, managersPerformanceFeeBps: feeSettings.managers_performance_fee_bps, basketDepositFeeBps: feeSettings.basket_deposit_fee_bps, basketWithdrawFeeBps: feeSettings.basket_withdraw_fee_bps, extraData: new Array(32).fill(0), modificationDelay: new BN(feeSettings.modification_delay), } FeeSettingsLayout.encode(editFeeSettings, editDataBuf); break; case TaskType.EditScheduleSettings: // 4 let scheduleSettings = (editData as EditScheduleSettings); let editScheduleSettings: ScheduleSettings = { cycleStartTime: new BN(scheduleSettings.cycle_start_time), cycleDuration: new BN(scheduleSettings.cycle_duration), depositsStart: new BN(scheduleSettings.deposits_start), depositsEnd: new BN(scheduleSettings.deposits_end), automationStart: new BN(scheduleSettings.automation_start), automationEnd: new BN(scheduleSettings.automation_end), managementStart: new BN(scheduleSettings.management_start), managementEnd: new BN(scheduleSettings.management_end), modificationDelay: new BN(scheduleSettings.modification_delay), } ScheduleSettingsLayout.encode(editScheduleSettings, editDataBuf); break; case TaskType.EditAutomationSettings: // 5 let automationSettings = (editData as EditAutomationSettings); let editAutomationSettings: AutomationSettings = { allowAutomation: automationSettings.enabled ? 1 : 0, rebalanceSlippageThresholdBps: automationSettings.rebalance_slippage_threshold_bps, perTradeRebalanceSlippageThresholdBps: automationSettings.per_trade_rebalance_slippage_threshold_bps, rebalanceActivationThresholdAbsBps: automationSettings.rebalance_activation_threshold_abs_bps, rebalanceActivationThresholdRelBps: automationSettings.rebalance_activation_threshold_rel_bps, rebalanceActivationCooldown: new BN(automationSettings.rebalance_activation_cooldown), extraData: new Array(4).fill(PublicKey.default), modificationDelay: new BN(automationSettings.modification_delay), } AutomationSettingsLayout.encode(editAutomationSettings, editDataBuf); break; case TaskType.EditLpSettings: // 6 let lpSettings = (editData as EditLpSettings); let editLpSettings: LpSettings = { allowLp: lpSettings.enabled ? 1 : 0, lpThresholdBps: lpSettings.lp_threshold_bps, extraData: new Array(32).fill(0), modificationDelay: new BN(lpSettings.modification_delay), } LpSettingsLayout.encode(editLpSettings, editDataBuf); break; case TaskType.EditMetadataSettings: // 7 let metadataSettings = (editData as EditMetadataSettings); let editMetadataSettings: MetadataSettings = { symbolLength: metadataSettings.symbol.length, symbol: metadataSettings.symbol.split('').map((char) => char.charCodeAt(0)), nameLength: metadataSettings.name.length, name: metadataSettings.name.split('').map((char) => char.charCodeAt(0)), uriLength: metadataSettings.uri.length, uri: metadataSettings.uri.split('').map((char) => char.charCodeAt(0)), modificationDelay: new BN(metadataSettings.modification_delay), } MetadataSettingsLayout.encode(editMetadataSettings, editDataBuf); break; case TaskType.EditDepositsSettings: // 8 let depositsSettings = (editData as EditDepositsSettings); let editDepositsSettings = depositsSettings.enabled ? 1 : 0 editDataBuf[0] = editDepositsSettings; break; case TaskType.EditForceRebalanceSettings: // 9 let forceRebalanceSettings = (editData as EditForceRebalanceSettings); let editForceRebalanceSettings = forceRebalanceSettings.enabled ? 1 : 0 let editForceRebalanceModificationDelayBN = new BN(forceRebalanceSettings.modification_delay); editDataBuf[0] = editForceRebalanceSettings; editDataBuf.writeBigUint64LE(BigInt(editForceRebalanceModificationDelayBN.toString()), 1); break; case TaskType.EditCustomRebalanceSettings: // 10 let customRebalanceSettings = (editData as EditCustomRebalanceSettings); let editCustomRebalanceSettings = customRebalanceSettings.enabled ? 1 : 0 let editCustomRebalanceModificationDelayBN = new BN(customRebalanceSettings.modification_delay); editDataBuf[0] = editCustomRebalanceSettings; editDataBuf.writeBigUint64LE(BigInt(editCustomRebalanceModificationDelayBN.toString()), 1); break; case TaskType.EditAddTokenDelay: // 11 - 101 let addTokenDelay = (editData as EditAddTokenSettings); let editAddTokenDelay: EditAddTokenDelay = { modificationDelay: new BN(addTokenDelay.modification_delay), } EditAddTokenDelayLayout.encode(editAddTokenDelay, editDataBuf); break; case TaskType.EditUpdateWeightsDelay: // 12 - 102 let updateWeightsDelay = (editData as EditUpdateWeightsSettings); let editUpdateWeightsDelay: EditUpdateWeightsDelay = { modificationDelay: new BN(updateWeightsDelay.modification_delay), } EditUpdateWeightsDelayLayout.encode(editUpdateWeightsDelay, editDataBuf); break; case TaskType.EditMakeDirectSwapDelay: // 13 - 103 let makeDirectSwapDelay = (editData as EditMakeDirectSwapSettings); let editMakeDirectSwapDelay: EditMakeDirectSwapDelay = { modificationDelay: new BN(makeDirectSwapDelay.modification_delay), } EditMakeDirectSwapDelayLayout.encode(editMakeDirectSwapDelay, editDataBuf); break; case TaskType.AddToken: // 14 - 201 let addTokenData = (editData as AddOrEditTokenInput); let oracleDatas: OracleData[] = []; for (let i = 0; i < addTokenData.oracles.length; i++) { let oracleData: OracleData = { oracleSettings: { oracleType: [...ORACLE_TYPES_STRINGS.entries()].find(([, name]) => name === addTokenData.oracles[i].oracle_type)?.[0] ?? 255, numRequiredAccounts: 0, weight: addTokenData.oracles[i].weight, isRequired: addTokenData.oracles[i].is_required ? 1 : 0, confThreshBps: addTokenData.oracles[i].conf_thresh_bps, volatilityThreshBps: addTokenData.oracles[i].volatility_thresh_bps, maxSlippageBps: addTokenData.oracles[i].max_slippage_bps, minLiquidity: new BN(addTokenData.oracles[i].min_liquidity), stalenessThresh: new BN(addTokenData.oracles[i].staleness_thresh), stalenessConfRateBps: addTokenData.oracles[i].staleness_conf_rate_bps, tokenDecimals: addTokenData.oracles[i].token_decimals, twapSecondsAgo: new BN(addTokenData.oracles[i].twap_seconds_ago), twapSecondarySecondsAgo: new BN(addTokenData.oracles[i].twap_secondary_seconds_ago), quote: Quote.Wsol, side: Side.Base, }, accountsToLoadLutIds: new Array(MAX_ACCOUNTS_PER_ORACLE).fill(0), accountsToLoadLutIndices: new Array(MAX_ACCOUNTS_PER_ORACLE).fill(0), } oracleDatas.push(oracleData); } while (oracleDatas.length < MAX_ORACLES_PER_TOKEN) { oracleDatas.push({ oracleSettings: DEFAULT_ORACLE_SETTINGS, accountsToLoadLutIds: new Array(MAX_ACCOUNTS_PER_ORACLE).fill(0), accountsToLoadLutIndices: new Array(MAX_ACCOUNTS_PER_ORACLE).fill(0), }); } let oracleAggregator: OracleAggregator = { numOracles: addTokenData.oracles.length, minOraclesThresh: addTokenData.min_oracles_thresh, oracles: oracleDatas, minConfBps: addTokenData.min_conf_bps, confThreshBps: addTokenData.conf_thresh_bps, confMultiplier: decimalToFraction(new Decimal(addTokenData.conf_multiplier)), } OracleAggregatorLayout.encode(oracleAggregator, editDataBuf); editDataBuf.writeUInt8(addTokenData.active ? 1 : 0, OracleAggregatorLayout.getSpan()); additionalAccounts.push({ pubkey: new PublicKey(addTokenData.token_mint), isWritable: false, isSigner: false }); additionalAccounts.push({ pubkey: getAta(basket.ownAddress, new PublicKey(addTokenData.token_mint), tokenProgram), isWritable: true, isSigner: false }); additionalAccounts.push({ pubkey: basket.lookupTables.active[0], isWritable: true, isSigner: false }); additionalAccounts.push({ pubkey: basket.lookupTables.active[1], isWritable: true, isSigner: false }); for (let i = 0; i < addTokenData.oracles.length; i++) { additionalAccounts.push({ pubkey: new PublicKey(addTokenData.oracles[i].account), isWritable: false, isSigner: false }); } additionalAccounts.push({ pubkey: ADDRESS_LOOKUP_TABLE_PROGRAM_ID, isWritable: false, isSigner: false }); break; case TaskType.UpdateWeights: { // 15 - 202 const updateWeightsData = (editData as UpdateWeightsInput); const weights = updateWeightsData.token_weights.slice(0, MAX_SUPPORTED_TOKENS_PER_BASKET); while (weights.length < MAX_SUPPORTED_TOKENS_PER_BASKET) weights.push({ mint: '', weight_bps: 0 }); let tokenMintsHash = updateWeightsData.token_mints_hash ?? computeTokenMintsHash( basket.composition.slice(0, basket.numTokens) .filter((asset) => asset.active === 1) .map((asset) => asset.mint.toBase58()) ); let updateWeights: UpdateWeights = { tokenWeights: weights.map((weight) => weight.weight_bps), tokenMintsHash: tokenMintsHash, } UpdateWeightsLayout.encode(updateWeights, editDataBuf); break; } case TaskType.MakeDirectSwap: // 16 - 203 let makeDirectSwapData = (editData as MakeDirectSwapInput); let makeDirectSwap: MakeDirectSwap = { fromTokenMint: new PublicKey(makeDirectSwapData.from_token_mint), toTokenMint: new PublicKey(makeDirectSwapData.to_token_mint), amountFrom: new BN(makeDirectSwapData.amount_from), amountTo: new BN(makeDirectSwapData.amount_to), } MakeDirectSwapLayout.encode(makeDirectSwap, editDataBuf); break; default: break; } const activationTimestampBuf = Buffer.from(activationTimestamp.toArray("le", 8)); const expirationTimestampBuf = Buffer.from(expirationTimestamp.toArray("le", 8)); const minBountyBuf = Buffer.from(minBounty.toArray("le", 8)); const maxBountyBuf = Buffer.from(maxBounty.toArray("le", 8)); const data = Buffer.concat([ CREATE_EDIT_BASKET_INTENT_DISCRIMINATOR, intentSeedArrayBuf, editTypeBuf, editDataBuf, activationTimestampBuf, expirationTimestampBuf, minBountyBuf, maxBountyBuf, ]); const keys: AccountMeta[] = [ { pubkey: manager, isSigner: true, isWritable: true }, { pubkey: basket.ownAddress, isSigner: false, isWritable: true }, { pubkey: intent, isSigner: false, isWritable: true }, { pubkey: globalConfig, isSigner: false, isWritable: false }, { pubkey: bountyMint, isSigner: false, isWritable: false }, { pubkey: managerBountyATA, isSigner: false, isWritable: true }, { pubkey: bountyVault, isSigner: false, isWritable: true }, { pubkey: bountyVaultATA, isSigner: false, isWritable: true }, { pubkey: SystemProgram.programId, isSigner: false, isWritable: false }, { pubkey: TOKEN_PROGRAM_ID, isSigner: false, isWritable: false }, { pubkey: TOKEN_2022_PROGRAM_ID, isSigner: false, isWritable: false }, { pubkey: ASSOCIATED_TOKEN_PROGRAM_ID, isSigner: false, isWritable: false }, ]; keys.push(...additionalAccounts); return new TransactionInstruction({ keys, programId: BASKETS_V3_PROGRAM_ID, data, }); } export function executeEditBasketIntentIx(params: { keeper: PublicKey, basket: PublicKey, intent: PublicKey, editType: TaskType, manager: PublicKey, bountyMint: PublicKey, basketMint?: PublicKey, }): TransactionInstruction { const { keeper, basket, basketMint, bountyMint, manager, editType, intent, } = params; let metadataAccount: PublicKey | null = null; if (editType === TaskType.EditMetadataSettings) { if (!basketMint) { throw new Error("basketMint is required for EditMetadataSettings"); } metadataAccount = getMetadataAccount(basketMint); } let globalConfig = getGlobalConfigPda(); let bountyVault = getBountyVaultPda(); let keeperBountyATA = getAta(keeper, bountyMint); let managerBountyATA = getAta(manager, bountyMint); let bountyVaultATA = getAta(bountyVault, bountyMint); // discriminator const data = EDIT_BASKET_DISCRIMINATOR; // accounts const keys = [ { pubkey: keeper, isSigner: true, isWritable: true }, { pubkey: basket, isSigner: false, isWritable: true }, { pubkey: intent, isSigner: false, isWritable: true }, { pubkey: globalConfig, isSigner: false, isWritable: false }, { pubkey: bountyMint, isSigner: false, isWritable: false }, { pubkey: keeperBountyATA, isSigner: false, isWritable: true }, { pubkey: manager, isSigner: false, isWritable: true }, { pubkey: managerBountyATA, isSigner: false, isWritable: true }, { pubkey: bountyVault, isSigner: false, isWritable: true }, { pubkey: bountyVaultATA, isSigner: false, isWritable: true }, { pubkey: SystemProgram.programId, isSigner: false, isWritable: false }, { pubkey: TOKEN_PROGRAM_ID, isSigner: false, isWritable: false }, { pubkey: TOKEN_2022_PROGRAM_ID, isSigner: false, isWritable: false }, { pubkey: ASSOCIATED_TOKEN_PROGRAM_ID, isSigner: false, isWritable: false }, ]; // remaining accounts if(editType === TaskType.EditMetadataSettings){ keys.push({ pubkey: basket, isSigner: false, isWritable: false }); keys.push({ pubkey: metadataAccount!, isSigner: false, isWritable: true }); keys.push({ pubkey: METADATA_PROGRAM_ID, isSigner: false, isWritable: false }); }; return new TransactionInstruction({ keys, programId: BASKETS_V3_PROGRAM_ID, data, }); } export function cancelIntentIx(params: { keeper: PublicKey, basket: PublicKey, intent: PublicKey, editType: TaskType, manager: PublicKey, bountyMint: PublicKey, }): TransactionInstruction { const { keeper, basket, intent, editType, bountyMint, manager } = params; const globalConfig = getGlobalConfigPda(); const bountyVault = getBountyVaultPda(); const keeperBountyATA = getAta(keeper, bountyMint); const managerBountyATA = getAta(manager, bountyMint); const bountyVaultATA = getAta(bountyVault, bountyMint); const keys: AccountMeta[] = [ { pubkey: keeper, isSigner: true, isWritable: true }, { pubkey: basket, isSigner: false, isWritable: true }, { pubkey: intent, isSigner: false, isWritable: true }, { pubkey: globalConfig, isSigner: false, isWritable: false }, { pubkey: bountyMint, isSigner: false, isWritable: false }, { pubkey: keeperBountyATA, isSigner: false, isWritable: true }, { pubkey: manager, isSigner: false, isWritable: true }, { pubkey: managerBountyATA, isSigner: false, isWritable: true }, { pubkey: bountyVault, isSigner: false, isWritable: true }, { pubkey: bountyVaultATA, isSigner: false, isWritable: true }, { pubkey: SystemProgram.programId, isSigner: false, isWritable: false }, { pubkey: TOKEN_PROGRAM_ID, isSigner: false, isWritable: false }, { pubkey: TOKEN_2022_PROGRAM_ID, isSigner: false, isWritable: false }, { pubkey: ASSOCIATED_TOKEN_PROGRAM_ID, isSigner: false, isWritable: false }, ]; return new TransactionInstruction({ keys, programId: BASKETS_V3_PROGRAM_ID, data: CANCEL_INTENT_DISCRIMINATOR, }); }