@symmetry-hq/temp-v3-sdk 0.0.37 → 0.0.39

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -19,3 +19,4 @@ export declare const USDC_DECIMALS = 6;
19
19
  export declare const MAX_SUPPORTED_TOKENS_PER_BASKET: number;
20
20
  export declare const MAX_ORACLES_PER_TOKEN: number;
21
21
  export declare const MAX_EXTRA_DATA_PER_ORACLE: number;
22
+ export declare const LUT_EXTEND_BATCH_SIZE = 20;
@@ -3,7 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.MAX_EXTRA_DATA_PER_ORACLE = exports.MAX_ORACLES_PER_TOKEN = exports.MAX_SUPPORTED_TOKENS_PER_BASKET = exports.USDC_DECIMALS = exports.WSOL_DECIMALS = exports.HUNDRED_PERCENT_BPS = exports.X64 = exports.MAX_TRANSFER_TOKENS = exports.MAX_MANAGERS_PER_BASKET = exports.INTENT_TASK_DATA_SIZE = exports.PYTHNET_CUSTODY_PRICE_USDC_ACCOUNT = exports.PYTHNET_CUSTODY_PRICE_WSOL_ACCOUNT = exports.MINTS = exports.RENT_SYSVAR_ID = exports.ADDRESS_LOOKUP_TABLE_PROGRAM_ID = exports.METADATA_PROGRAM_ID = exports.BASKETS_V3_PROGRAM_ID = exports.PRIORITY_FEE = exports.COMPUTE_UNITS = void 0;
6
+ exports.LUT_EXTEND_BATCH_SIZE = exports.MAX_EXTRA_DATA_PER_ORACLE = exports.MAX_ORACLES_PER_TOKEN = exports.MAX_SUPPORTED_TOKENS_PER_BASKET = exports.USDC_DECIMALS = exports.WSOL_DECIMALS = exports.HUNDRED_PERCENT_BPS = exports.X64 = exports.MAX_TRANSFER_TOKENS = exports.MAX_MANAGERS_PER_BASKET = exports.INTENT_TASK_DATA_SIZE = exports.PYTHNET_CUSTODY_PRICE_USDC_ACCOUNT = exports.PYTHNET_CUSTODY_PRICE_WSOL_ACCOUNT = exports.MINTS = exports.RENT_SYSVAR_ID = exports.ADDRESS_LOOKUP_TABLE_PROGRAM_ID = exports.METADATA_PROGRAM_ID = exports.BASKETS_V3_PROGRAM_ID = exports.PRIORITY_FEE = exports.COMPUTE_UNITS = void 0;
7
7
  const web3_js_1 = require("@solana/web3.js");
8
8
  const decimal_js_1 = __importDefault(require("decimal.js"));
9
9
  exports.COMPUTE_UNITS = 1000000;
@@ -34,3 +34,4 @@ exports.USDC_DECIMALS = 6;
34
34
  exports.MAX_SUPPORTED_TOKENS_PER_BASKET = 100;
35
35
  exports.MAX_ORACLES_PER_TOKEN = 4;
36
36
  exports.MAX_EXTRA_DATA_PER_ORACLE = 4;
37
+ exports.LUT_EXTEND_BATCH_SIZE = 20;
@@ -1,16 +1,14 @@
1
1
  import { Connection, PublicKey, TransactionInstruction, TransactionSignature } from '@solana/web3.js';
2
- import { Basket } from './layouts/basket';
2
+ import { getJupTokenLedgerAndSwapInstructions } from './jup';
3
+ import { Basket, FormattedAccumulatedFees, FormattedAddTokenSettings, FormattedAsset, FormattedAutomationSettings, FormattedBasket, FormattedCreatorSettings, FormattedCustomRebalanceSettings, FormattedDepositsSettings, FormattedFeeSettings, FormattedForceRebalanceSettings, FormattedLookupTables, FormattedLpSettings, FormattedMakeDirectSwapSettings, FormattedManagersSettings, FormattedMetadataSettings, FormattedOracle, FormattedOracleAggregator, FormattedOracleSettings, FormattedScheduleSettings, FormattedUpdateWeightsSettings } from './layouts/basket';
3
4
  import { FormattedGlobalConfig, GlobalConfig } from './layouts/config';
4
- import { OracleInput, EditAddTokenSettings, EditAutomationSettings, EditCreatorSettings, EditCustomRebalanceSettings, EditDepositsSettings, EditFeeSettings, EditForceRebalanceSettings, EditLpSettings, EditMakeDirectSwapSettings, EditManagerSettings, EditMetadataSettings, EditScheduleSettings, EditUpdateWeightsSettings, Intent, MakeDirectSwapInput, Settings, TaskContext, TaskType, UpdateWeightsInput, FormattedIntentStatus, FormattedTaskType, FormattedIntent, FormattedBounty, FormattedBountySchedule, AddOrEditTokenInput } from './layouts/intents/intent';
5
- import { FormattedRebalanceType, FormattedRebalanceAction, FormattedOraclePrice, FormattedTokenAuction, FormattedTaskCompletion, FormattedRebalanceIntent } from './layouts/intents/rebalanceIntent';
6
- import { FormattedCreatorSettings, FormattedManagersSettings, FormattedFeeSettings, FormattedScheduleSettings, FormattedAutomationSettings, FormattedLpSettings, FormattedMetadataSettings, FormattedDepositsSettings, FormattedForceRebalanceSettings, FormattedCustomRebalanceSettings, FormattedAddTokenSettings, FormattedUpdateWeightsSettings, FormattedMakeDirectSwapSettings, FormattedAccumulatedFees, FormattedLookupTables, FormattedAsset, FormattedOracleSettings, FormattedOracleAggregator, FormattedOracle, FormattedBasket } from './layouts/basket';
7
- import { RebalanceIntent } from './layouts/intents/rebalanceIntent';
5
+ import { AddOrEditTokenInput, EditAddTokenSettings, EditAutomationSettings, EditCreatorSettings, EditCustomRebalanceSettings, EditDepositsSettings, EditFeeSettings, EditForceRebalanceSettings, EditLpSettings, EditMakeDirectSwapSettings, EditManagerSettings, EditMetadataSettings, EditScheduleSettings, EditUpdateWeightsSettings, FormattedBounty, FormattedBountySchedule, FormattedIntent, FormattedIntentStatus, FormattedTaskType, Intent, MakeDirectSwapInput, OracleInput, Settings, TaskContext, TaskType, UpdateWeightsInput } from './layouts/intents/intent';
6
+ import { FormattedOraclePrice, FormattedRebalanceAction, FormattedRebalanceIntent, FormattedRebalanceType, FormattedTaskCompletion, FormattedTokenAuction, RebalanceIntent } from './layouts/intents/rebalanceIntent';
7
+ import { FormattedOracleType } from './layouts/oracle';
8
8
  import { BasketFilter } from './states/basket';
9
9
  import { IntentFilter } from './states/intents/intent';
10
10
  import { RebalanceIntentFilter } from './states/intents/rebalanceIntent';
11
- import { TxPayloadBatchSequence, VersionedTxs, Wallet } from './txUtils';
12
- import { FormattedOracleType } from './layouts/oracle';
13
- import { getJupTokenLedgerAndSwapInstructions } from './jup';
11
+ import { BasketCreationTx, TxPayloadBatchSequence, VersionedTxs, Wallet } from './txUtils';
14
12
  export declare class SymmetryCore {
15
13
  private sdkParams;
16
14
  constructor(params: {
@@ -58,7 +56,7 @@ export declare class SymmetryCore {
58
56
  host_management_fee_bps: number;
59
57
  host_performance_fee_bps: number;
60
58
  };
61
- }): Promise<TxPayloadBatchSequence>;
59
+ }): Promise<BasketCreationTx>;
62
60
  editCreatorTx(context: TaskContext, settings: EditCreatorSettings): Promise<TxPayloadBatchSequence>;
63
61
  editManagersTx(context: TaskContext, settings: EditManagerSettings): Promise<TxPayloadBatchSequence>;
64
62
  editScheduleTx(context: TaskContext, settings: EditScheduleSettings): Promise<TxPayloadBatchSequence>;
@@ -164,10 +162,20 @@ export declare class SymmetryCore {
164
162
  keeper: string;
165
163
  rebalance_intent: string;
166
164
  }): Promise<TxPayloadBatchSequence>;
165
+ addBountyTx(params: {
166
+ keeper: string;
167
+ basket: string;
168
+ amount: number;
169
+ }): Promise<TxPayloadBatchSequence>;
167
170
  claimBasketFeesTx(params: {
168
171
  claimer: string;
169
172
  basket: string;
170
173
  }): Promise<TxPayloadBatchSequence>;
174
+ rewriteLookupTablesTx(params: {
175
+ signer: string;
176
+ basket_mint: string;
177
+ additional_accounts: string[];
178
+ }): Promise<TxPayloadBatchSequence>;
171
179
  signAndSendVersionedTxs(params: {
172
180
  versionedTxs: VersionedTxs;
173
181
  wallet: Wallet;
package/dist/src/index.js CHANGED
@@ -17,29 +17,31 @@ const decimal_js_1 = __importDefault(require("decimal.js"));
17
17
  const anchor_1 = require("@coral-xyz/anchor");
18
18
  const spl_token_1 = require("@solana/spl-token");
19
19
  const web3_js_1 = require("@solana/web3.js");
20
+ const constants_1 = require("./constants");
20
21
  const claimBounty_1 = require("./instructions/automation/claimBounty");
22
+ const flashSwap_1 = require("./instructions/automation/flashSwap");
21
23
  const priceUpdate_1 = require("./instructions/automation/priceUpdate");
22
24
  const rebalanceIntent_1 = require("./instructions/automation/rebalanceIntent");
25
+ const addBounty_1 = require("./instructions/management/addBounty");
23
26
  const admin_1 = require("./instructions/management/admin");
27
+ const claimFees_1 = require("./instructions/management/claimFees");
24
28
  const createBasket_1 = require("./instructions/management/createBasket");
25
29
  const edit_1 = require("./instructions/management/edit");
30
+ const luts_1 = require("./instructions/management/luts");
26
31
  const pda_1 = require("./instructions/pda");
27
32
  const deposit_1 = require("./instructions/user/deposit");
28
33
  const withdraw_1 = require("./instructions/user/withdraw");
34
+ const jup_1 = require("./jup");
35
+ Object.defineProperty(exports, "getJupTokenLedgerAndSwapInstructions", { enumerable: true, get: function () { return jup_1.getJupTokenLedgerAndSwapInstructions; } });
29
36
  const fraction_1 = require("./layouts/fraction");
30
37
  const intent_1 = require("./layouts/intents/intent");
31
38
  Object.defineProperty(exports, "TaskType", { enumerable: true, get: function () { return intent_1.TaskType; } });
32
39
  const rebalanceIntent_2 = require("./layouts/intents/rebalanceIntent");
33
40
  const basket_1 = require("./states/basket");
41
+ const config_1 = require("./states/config");
34
42
  const intent_2 = require("./states/intents/intent");
35
43
  const rebalanceIntent_3 = require("./states/intents/rebalanceIntent");
36
44
  const txUtils_1 = require("./txUtils");
37
- const config_1 = require("./states/config");
38
- const flashSwap_1 = require("./instructions/automation/flashSwap");
39
- const claimFees_1 = require("./instructions/management/claimFees");
40
- const jup_1 = require("./jup");
41
- Object.defineProperty(exports, "getJupTokenLedgerAndSwapInstructions", { enumerable: true, get: function () { return jup_1.getJupTokenLedgerAndSwapInstructions; } });
42
- const constants_1 = require("./constants");
43
45
  class SymmetryCore {
44
46
  constructor(params) {
45
47
  var _a;
@@ -257,7 +259,11 @@ class SymmetryCore {
257
259
  }]] };
258
260
  let versionedTxs = yield (0, txUtils_1.prepareVersionedTxs)(this.sdkParams.connection, txBatchData);
259
261
  let txPayloadBatchSequence = (0, txUtils_1.prepareTxPayloadBatchSequence)(txBatchData, versionedTxs);
260
- return txPayloadBatchSequence;
262
+ return {
263
+ mint: mint.toBase58(),
264
+ basket: basket.toBase58(),
265
+ batches: txPayloadBatchSequence.batches,
266
+ };
261
267
  });
262
268
  }
263
269
  editCreatorTx(context, settings) {
@@ -1068,6 +1074,37 @@ class SymmetryCore {
1068
1074
  return txPayloadBatchSequence;
1069
1075
  });
1070
1076
  }
1077
+ addBountyTx(params) {
1078
+ return __awaiter(this, void 0, void 0, function* () {
1079
+ let keeper = new web3_js_1.PublicKey(params.keeper);
1080
+ let basket = yield this.fetchBasket(params.basket);
1081
+ let globalConfig = yield this.fetchGlobalConfig();
1082
+ let bountyWsolAmount = 0;
1083
+ if (globalConfig.bountyMint.equals(constants_1.MINTS["mainnet"].WSOL)) {
1084
+ bountyWsolAmount = params.amount;
1085
+ }
1086
+ let wsolIxs = yield (0, txUtils_1.wrapWsolIxs)(this.sdkParams.connection, keeper, bountyWsolAmount);
1087
+ let ix = (0, addBounty_1.addBountyIx)({
1088
+ keeper: keeper,
1089
+ basket: basket.ownAddress,
1090
+ bountyMint: basket.settings.bountyMint,
1091
+ amount: params.amount,
1092
+ });
1093
+ let txBatchData = { batches: [[{
1094
+ payer: keeper,
1095
+ instructions: [
1096
+ ...wsolIxs,
1097
+ ix,
1098
+ web3_js_1.ComputeBudgetProgram.setComputeUnitLimit({ units: constants_1.COMPUTE_UNITS }),
1099
+ web3_js_1.ComputeBudgetProgram.setComputeUnitPrice({ microLamports: this.sdkParams.priorityFee }),
1100
+ ],
1101
+ lookupTables: [],
1102
+ }]] };
1103
+ let versionedTxs = yield (0, txUtils_1.prepareVersionedTxs)(this.sdkParams.connection, txBatchData);
1104
+ let txPayloadBatchSequence = (0, txUtils_1.prepareTxPayloadBatchSequence)(txBatchData, versionedTxs);
1105
+ return txPayloadBatchSequence;
1106
+ });
1107
+ }
1071
1108
  claimBasketFeesTx(params) {
1072
1109
  return __awaiter(this, void 0, void 0, function* () {
1073
1110
  let claimer = new web3_js_1.PublicKey(params.claimer);
@@ -1116,6 +1153,85 @@ class SymmetryCore {
1116
1153
  return txPayloadBatchSequence;
1117
1154
  });
1118
1155
  }
1156
+ rewriteLookupTablesTx(params) {
1157
+ return __awaiter(this, void 0, void 0, function* () {
1158
+ const signer = new web3_js_1.PublicKey(params.signer);
1159
+ const basketMint = new web3_js_1.PublicKey(params.basket_mint);
1160
+ const additionalAccounts = params.additional_accounts.map(a => new web3_js_1.PublicKey(a));
1161
+ const basketAddress = (0, pda_1.getBasketState)(basketMint);
1162
+ const basket = yield this.fetchBasket(basketAddress.toBase58());
1163
+ const activeLut0 = basket.lookupTables.active[0];
1164
+ const activeLut1 = basket.lookupTables.active[1];
1165
+ let oldTempLut0 = basket.lookupTables.temp[0];
1166
+ let oldTempLut1 = basket.lookupTables.temp[1];
1167
+ const slot = yield this.sdkParams.connection.getSlot("finalized");
1168
+ const newLut0 = (0, pda_1.getLookupTableAccount)(basketAddress, slot);
1169
+ const newLut1 = (0, pda_1.getLookupTableAccount)(basketAddress, slot - 1);
1170
+ // Step 1: create lookup tables
1171
+ const createIx = (0, luts_1.createBasketLookupTablesInstruction)({
1172
+ signer,
1173
+ basket: basketAddress,
1174
+ oldTempLookupTable0: oldTempLut0,
1175
+ oldTempLookupTable1: oldTempLut1,
1176
+ newTempLookupTable0: newLut0,
1177
+ newTempLookupTable1: newLut1,
1178
+ slot,
1179
+ });
1180
+ const txBatchData = { batches: [
1181
+ [{
1182
+ payer: signer,
1183
+ instructions: [
1184
+ createIx,
1185
+ web3_js_1.ComputeBudgetProgram.setComputeUnitLimit({ units: constants_1.COMPUTE_UNITS }),
1186
+ web3_js_1.ComputeBudgetProgram.setComputeUnitPrice({ microLamports: this.sdkParams.priorityFee }),
1187
+ ],
1188
+ lookupTables: [],
1189
+ }],
1190
+ ] };
1191
+ // Step 2: extend LUTs in batches of ~20
1192
+ const BATCH_SIZE = constants_1.LUT_EXTEND_BATCH_SIZE;
1193
+ for (let i = 0; i < additionalAccounts.length; i += BATCH_SIZE) {
1194
+ const batch = additionalAccounts.slice(i, i + BATCH_SIZE);
1195
+ const extendIx = (0, luts_1.extendBasketLookupTablesIx)({
1196
+ signer,
1197
+ basket: basketAddress,
1198
+ tempLookupTable0: newLut0,
1199
+ tempLookupTable1: newLut1,
1200
+ additionalAccounts: batch,
1201
+ });
1202
+ txBatchData.batches.push([{
1203
+ payer: signer,
1204
+ instructions: [
1205
+ extendIx,
1206
+ web3_js_1.ComputeBudgetProgram.setComputeUnitLimit({ units: constants_1.COMPUTE_UNITS }),
1207
+ web3_js_1.ComputeBudgetProgram.setComputeUnitPrice({ microLamports: this.sdkParams.priorityFee }),
1208
+ ],
1209
+ lookupTables: [],
1210
+ }]);
1211
+ }
1212
+ // Step 3: overwrite active LUTs
1213
+ const overwriteIx = (0, luts_1.overwriteBasketLookupTablesIx)({
1214
+ signer,
1215
+ basket: basketAddress,
1216
+ tempLookupTable0: newLut0,
1217
+ tempLookupTable1: newLut1,
1218
+ activeLookupTable0: activeLut0,
1219
+ activeLookupTable1: activeLut1,
1220
+ });
1221
+ txBatchData.batches.push([{
1222
+ payer: signer,
1223
+ instructions: [
1224
+ overwriteIx,
1225
+ web3_js_1.ComputeBudgetProgram.setComputeUnitLimit({ units: constants_1.COMPUTE_UNITS }),
1226
+ web3_js_1.ComputeBudgetProgram.setComputeUnitPrice({ microLamports: this.sdkParams.priorityFee }),
1227
+ ],
1228
+ lookupTables: [],
1229
+ }]);
1230
+ const versionedTxs = yield (0, txUtils_1.prepareVersionedTxs)(this.sdkParams.connection, txBatchData);
1231
+ const txPayloadBatchSequence = (0, txUtils_1.prepareTxPayloadBatchSequence)(txBatchData, versionedTxs);
1232
+ return txPayloadBatchSequence;
1233
+ });
1234
+ }
1119
1235
  signAndSendVersionedTxs(params) {
1120
1236
  return __awaiter(this, void 0, void 0, function* () {
1121
1237
  let { versionedTxs, wallet } = params;
@@ -12,7 +12,7 @@ function addBountyIx(params) {
12
12
  let bountyVault = (0, pda_1.getBountyVaultPda)();
13
13
  let globalConfig = (0, pda_1.getGlobalConfigPda)();
14
14
  let keeperBountyAta = (0, pda_1.getAta)(keeper, bountyMint);
15
- let bountyVaultAta = (0, pda_1.getAta)(bountyMint, bountyVault);
15
+ let bountyVaultAta = (0, pda_1.getAta)(bountyVault, bountyMint);
16
16
  const data = Buffer.concat([
17
17
  ADD_BOUNTY_DISCRIMINATOR,
18
18
  Buffer.from(new anchor_1.BN(amount).toArray("le", 8)), // u64 LE
@@ -13,6 +13,7 @@ export declare function extendBasketLookupTablesIx(params: {
13
13
  basket: PublicKey;
14
14
  tempLookupTable0: PublicKey;
15
15
  tempLookupTable1: PublicKey;
16
+ additionalAccounts: PublicKey[];
16
17
  }): TransactionInstruction;
17
18
  export declare function overwriteBasketLookupTablesIx(params: {
18
19
  signer: PublicKey;
@@ -14,24 +14,29 @@ const OVERWRITE_BASKET_LOOKUP_TABLES_DISCRIMINATOR = Buffer.from([197, 116, 189,
14
14
  const CLOSE_DEACTIVATED_LOOKUP_TABLE_DISCRIMINATOR = Buffer.from([19, 4, 214, 20, 26, 43, 71, 233]);
15
15
  function createBasketLookupTablesInstruction(params) {
16
16
  const { signer, basket, oldTempLookupTable0, oldTempLookupTable1, newTempLookupTable0, newTempLookupTable1, slot, } = params;
17
- let newTempLookupTableInfo0 = (0, pda_1.getLookupTableInfoAccount)(newTempLookupTable0);
18
- let newTempLookupTableInfo1 = (0, pda_1.getLookupTableInfoAccount)(newTempLookupTable1);
17
+ const globalConfig = (0, pda_1.getGlobalConfigPda)();
18
+ const hasOldTemp = !oldTempLookupTable0.equals(web3_js_1.PublicKey.default)
19
+ && !oldTempLookupTable1.equals(web3_js_1.PublicKey.default);
19
20
  const data = Buffer.concat([
20
21
  CREATE_BASKET_LOOKUP_TABLES_DISCRIMINATOR,
21
- new anchor_1.BN(slot).toArray("le", 8),
22
+ Buffer.from(new anchor_1.BN(slot).toArray("le", 8)),
22
23
  ]);
23
24
  const keys = [
24
25
  { pubkey: signer, isSigner: true, isWritable: true },
25
26
  { pubkey: basket, isSigner: false, isWritable: true },
26
- { pubkey: oldTempLookupTable0, isSigner: false, isWritable: true },
27
- { pubkey: oldTempLookupTable1, isSigner: false, isWritable: true },
27
+ { pubkey: globalConfig, isSigner: false, isWritable: false },
28
+ { pubkey: hasOldTemp ? oldTempLookupTable0 : constants_1.PYTHNET_CUSTODY_PRICE_USDC_ACCOUNT, isSigner: false, isWritable: true },
29
+ { pubkey: hasOldTemp ? oldTempLookupTable1 : constants_1.PYTHNET_CUSTODY_PRICE_WSOL_ACCOUNT, isSigner: false, isWritable: true },
28
30
  { pubkey: newTempLookupTable0, isSigner: false, isWritable: true },
29
31
  { pubkey: newTempLookupTable1, isSigner: false, isWritable: true },
30
- { pubkey: newTempLookupTableInfo0, isSigner: false, isWritable: true },
31
- { pubkey: newTempLookupTableInfo1, isSigner: false, isWritable: true },
32
- { pubkey: constants_1.ADDRESS_LOOKUP_TABLE_PROGRAM_ID, isSigner: false, isWritable: false },
33
- { pubkey: web3_js_1.SystemProgram.programId, isSigner: false, isWritable: false },
34
32
  ];
33
+ if (hasOldTemp) {
34
+ keys.push({ pubkey: (0, pda_1.getLookupTableInfoAccount)(oldTempLookupTable0), isSigner: false, isWritable: true }, { pubkey: (0, pda_1.getLookupTableInfoAccount)(oldTempLookupTable1), isSigner: false, isWritable: true });
35
+ }
36
+ else {
37
+ keys.push({ pubkey: constants_1.BASKETS_V3_PROGRAM_ID, isSigner: false, isWritable: false }, { pubkey: constants_1.BASKETS_V3_PROGRAM_ID, isSigner: false, isWritable: false });
38
+ }
39
+ keys.push({ pubkey: constants_1.ADDRESS_LOOKUP_TABLE_PROGRAM_ID, isSigner: false, isWritable: false }, { pubkey: web3_js_1.SystemProgram.programId, isSigner: false, isWritable: false });
35
40
  return new web3_js_1.TransactionInstruction({
36
41
  keys,
37
42
  programId: constants_1.BASKETS_V3_PROGRAM_ID,
@@ -46,6 +51,7 @@ function extendBasketLookupTablesIx(params) {
46
51
  { pubkey: params.tempLookupTable1, isWritable: true, isSigner: false },
47
52
  { pubkey: constants_1.ADDRESS_LOOKUP_TABLE_PROGRAM_ID, isWritable: false, isSigner: false },
48
53
  { pubkey: web3_js_1.SystemProgram.programId, isWritable: false, isSigner: false },
54
+ ...params.additionalAccounts.map(pubkey => ({ pubkey, isWritable: false, isSigner: false })),
49
55
  ];
50
56
  return new web3_js_1.TransactionInstruction({
51
57
  keys,
@@ -61,6 +67,9 @@ function overwriteBasketLookupTablesIx(params) {
61
67
  { pubkey: params.tempLookupTable1, isWritable: true, isSigner: false },
62
68
  { pubkey: params.activeLookupTable0, isWritable: true, isSigner: false },
63
69
  { pubkey: params.activeLookupTable1, isWritable: true, isSigner: false },
70
+ { pubkey: (0, pda_1.getLookupTableInfoAccount)(params.activeLookupTable0), isWritable: true, isSigner: false },
71
+ { pubkey: (0, pda_1.getLookupTableInfoAccount)(params.activeLookupTable1), isWritable: true, isSigner: false },
72
+ { pubkey: constants_1.ADDRESS_LOOKUP_TABLE_PROGRAM_ID, isWritable: false, isSigner: false },
64
73
  { pubkey: web3_js_1.SystemProgram.programId, isWritable: false, isSigner: false },
65
74
  ];
66
75
  return new web3_js_1.TransactionInstruction({
@@ -10,6 +10,29 @@ export interface RebalanceIntentFilter {
10
10
  pubkey: string;
11
11
  }
12
12
  export declare function fetchRebalanceIntents(connection: Connection, filter?: RebalanceIntentFilter): Promise<RebalanceIntent[]>;
13
+ /**
14
+ * Returns all valid swap pairs available during the rebalance auction phase.
15
+ *
16
+ * **Swap direction (basket perspective):**
17
+ * - `inMint` / `inAmount`: what the basket is supposed to **receive**.
18
+ * - `outMint` / `outAmount`: what the basket wants to **swap** (give away).
19
+ * So each pair describes an **outMint → inMint** swap. When generating swap
20
+ * transactions, use this direction: swap `outMint` → `inMint` (sell outAmount of
21
+ * outMint, receive inAmount of inMint).
22
+ *
23
+ * Only runs when the rebalance is in Auction action and the current time falls
24
+ * within one of the three auction windows. For the active auction, target amounts
25
+ * are refreshed if they haven't been updated since the auction started.
26
+ *
27
+ * Iterates over completed price-update tokens to compute exchange rates via
28
+ * getSwapAmounts (using time-since-start and auction duration). Pairs with
29
+ * positive in/out amounts are collected and sorted by value descending
30
+ * (highest value first).
31
+ *
32
+ * @param rebalanceIntent - The rebalance intent state
33
+ * @param basket - The basket (used to update target amounts when needed)
34
+ * @returns Array of swap pairs, or empty array when not in auction or outside auction windows
35
+ */
13
36
  export declare function getSwapPairs(rebalanceIntent: RebalanceIntent, basket: Basket): {
14
37
  inMint: string;
15
38
  outMint: string;
@@ -436,6 +436,29 @@ class RebalanceIntentRustClass {
436
436
  }
437
437
  }
438
438
  }
439
+ /**
440
+ * Returns all valid swap pairs available during the rebalance auction phase.
441
+ *
442
+ * **Swap direction (basket perspective):**
443
+ * - `inMint` / `inAmount`: what the basket is supposed to **receive**.
444
+ * - `outMint` / `outAmount`: what the basket wants to **swap** (give away).
445
+ * So each pair describes an **outMint → inMint** swap. When generating swap
446
+ * transactions, use this direction: swap `outMint` → `inMint` (sell outAmount of
447
+ * outMint, receive inAmount of inMint).
448
+ *
449
+ * Only runs when the rebalance is in Auction action and the current time falls
450
+ * within one of the three auction windows. For the active auction, target amounts
451
+ * are refreshed if they haven't been updated since the auction started.
452
+ *
453
+ * Iterates over completed price-update tokens to compute exchange rates via
454
+ * getSwapAmounts (using time-since-start and auction duration). Pairs with
455
+ * positive in/out amounts are collected and sorted by value descending
456
+ * (highest value first).
457
+ *
458
+ * @param rebalanceIntent - The rebalance intent state
459
+ * @param basket - The basket (used to update target amounts when needed)
460
+ * @returns Array of swap pairs, or empty array when not in auction or outside auction windows
461
+ */
439
462
  function getSwapPairs(rebalanceIntent, basket) {
440
463
  let rebalanceIntentRustClass = new RebalanceIntentRustClass(rebalanceIntent);
441
464
  if (rebalanceIntentRustClass.self.currentAction !== rebalanceIntent_1.RebalanceAction.Auction)
@@ -46,6 +46,10 @@ export interface TxPayloadBatch {
46
46
  export interface TxPayloadBatchSequence {
47
47
  batches: TxPayloadBatch[];
48
48
  }
49
+ export interface BasketCreationTx extends TxPayloadBatchSequence {
50
+ mint: string;
51
+ basket: string;
52
+ }
49
53
  export declare function prepareTxPayloadBatchSequence(txBatchData: TxBatchData, versionedTxs?: VersionedTxs): TxPayloadBatchSequence;
50
54
  export declare function delay(ms: number): Promise<void>;
51
55
  export declare function getMultipleAccountsInfoBatched(connection: Connection, pubkeys: PublicKey[]): Promise<Map<string, AccountInfo<Buffer> | null>>;
package/dist/test.js CHANGED
@@ -22,6 +22,7 @@ let connection = new web3_js_1.Connection("https://api.devnet.solana.com");
22
22
  function testStates() {
23
23
  return __awaiter(this, void 0, void 0, function* () {
24
24
  var _a, _b;
25
+ return;
25
26
  let wallet = new anchor_1.Wallet(web3_js_1.Keypair.fromSecretKey(new Uint8Array(kp)));
26
27
  console.log(wallet.publicKey.toBase58());
27
28
  let sdk = new src_1.SymmetryCore({
@@ -45,12 +46,16 @@ function testStates() {
45
46
  let basket = yield sdk.fetchBasket("GrBFFvtdRL25o7gcRnV1kGvz1Qc7iscUmDp1ZvyBSyUa");
46
47
  basket = yield sdk.loadBasketPrice(basket);
47
48
  console.log(basket.formatted);
49
+ // console.log(basket.composition[0].mint.toBase58(), "amount:", basket.composition[0].amount.toString(), "price:", basket.composition[0].price?.price, "value:", basket.composition[0].value);
50
+ // console.log(basket.composition[1].mint.toBase58(), "amount:", basket.composition[1].amount.toString(), "price:", basket.composition[1].price?.price, "value:", basket.composition[1].value);
51
+ // console.log(basket.composition[2].mint.toBase58(), "amount:", basket.composition[2].amount.toString(), "price:", basket.composition[2].price?.price, "value:", basket.composition[2].value);
48
52
  // return;
49
53
  let tests = {
50
54
  createGlobalConfig: false, // TESTED
51
55
  editGlobalConfig: false, // TESTED
52
56
  createBasket: false, // TESTED
53
57
  editPrivateBasketSettings: false, // NOT TESTED
58
+ addBounty: false, // TESTED
54
59
  editCreator: false, // TESTED
55
60
  editManagerSettings: false, // TESTED
56
61
  editFeeSettings: false, // TESTED
@@ -59,20 +64,20 @@ function testStates() {
59
64
  editLpSettings: false, // TESTED
60
65
  editMetadata: false, // TESTED
61
66
  editDepositsSettings: false, // TESTED
62
- editForceRebalanceSettings: false, // NOT TESTED
63
- editCustomRebalanceSettings: false, // NOT TESTED
67
+ editForceRebalanceSettings: false, // TESTED
68
+ editCustomRebalanceSettings: false, // TESTED
64
69
  editAddTokenDelay: false, // NOT TESTED
65
70
  editUpdateWeightsDelay: false, // NOT TESTED
66
71
  editMakeDirectSwapDelay: false, // NOT TESTED
67
72
  addOrEditToken: false, // TESTED
68
73
  updateWeights: false, // NOT TESTED
69
74
  makeDirectSwap: false, // NOT TESTED
70
- executeIntent: false, // NOT TESTED
75
+ executeIntent: false, // TESTED
71
76
  buyBasket: false, // TESTED
72
77
  depositTokens: false, // TESTED
73
78
  lockDeposits: false, // TESTED
74
79
  sellBasket: false, // TESTED
75
- rebalanceBasket: false, // NOT TESTED
80
+ rebalanceBasket: false, // TESTED
76
81
  rebalanceBasketCustom: false, // NOT TESTED
77
82
  startPriceUpdates: false, // TESTED
78
83
  updateTokenPrices: false, // TESTED
@@ -99,6 +104,15 @@ function testStates() {
99
104
  });
100
105
  console.log(resCreateBasket);
101
106
  }
107
+ if (tests.addBounty) {
108
+ let tx = yield sdk.addBountyTx({
109
+ keeper: wallet.publicKey.toBase58(),
110
+ basket: basket.ownAddress.toBase58(),
111
+ amount: 250 * 10 ** 6,
112
+ });
113
+ let res = yield sdk.signAndSendTxPayloadBatchSequence({ txPayloadBatchSequence: tx, wallet });
114
+ console.log(res);
115
+ }
102
116
  let task_context = {
103
117
  basket: basket.ownAddress.toBase58(),
104
118
  manager: wallet.publicKey.toBase58(),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@symmetry-hq/temp-v3-sdk",
3
- "version": "0.0.37",
3
+ "version": "0.0.39",
4
4
  "description": "Symmetry Baskets V3 SDK",
5
5
  "main": "dist/src/index.js",
6
6
  "types": "dist/src/index.d.ts",
package/src/constants.ts CHANGED
@@ -35,3 +35,5 @@ export const USDC_DECIMALS = 6;
35
35
  export const MAX_SUPPORTED_TOKENS_PER_BASKET: number = 100;
36
36
  export const MAX_ORACLES_PER_TOKEN: number = 4;
37
37
  export const MAX_EXTRA_DATA_PER_ORACLE: number = 4;
38
+
39
+ export const LUT_EXTEND_BATCH_SIZE = 20;
package/src/index.ts CHANGED
@@ -1,75 +1,88 @@
1
1
  import Decimal from 'decimal.js';
2
2
 
3
3
  import { BN } from '@coral-xyz/anchor';
4
- import { closeAccount, closeAccountInstructionData, createAssociatedTokenAccountIdempotentInstruction, createAssociatedTokenAccountInstruction, createCloseAccountInstruction, createSyncNativeInstruction } from '@solana/spl-token';
4
+ import {
5
+ closeAccount, closeAccountInstructionData, createAssociatedTokenAccountIdempotentInstruction,
6
+ createAssociatedTokenAccountInstruction, createCloseAccountInstruction,
7
+ createSyncNativeInstruction
8
+ } from '@solana/spl-token';
5
9
  import {
6
10
  ComputeBudgetProgram, Connection, Keypair, PublicKey, TransactionInstruction,
7
11
  TransactionSignature
8
12
  } from '@solana/web3.js';
9
13
 
14
+ import {
15
+ COMPUTE_UNITS, LUT_EXTEND_BATCH_SIZE, MINTS, PRIORITY_FEE, PYTHNET_CUSTODY_PRICE_USDC_ACCOUNT,
16
+ PYTHNET_CUSTODY_PRICE_WSOL_ACCOUNT
17
+ } from './constants';
10
18
  import { claimBountyIx } from './instructions/automation/claimBounty';
19
+ import { flashDepositIx, flashWithdrawIx } from './instructions/automation/flashSwap';
11
20
  import { startPriceUpdatesIx, updateTokenPricesIx } from './instructions/automation/priceUpdate';
12
21
  import {
13
- cancelRebalanceIx,
14
- createRebalanceIntentIx, initRebalanceIntentIx, resizeRebalanceIntentIx
22
+ cancelRebalanceIx, createRebalanceIntentIx, initRebalanceIntentIx, resizeRebalanceIntentIx
15
23
  } from './instructions/automation/rebalanceIntent';
24
+ import { addBountyIx } from './instructions/management/addBounty';
16
25
  import { createGlobalConfigIx, editGlobalConfigIx } from './instructions/management/admin';
26
+ import { claimFeesIx } from './instructions/management/claimFees';
17
27
  import {
18
28
  createBasketIx, createBasketStateAccountIx, resizeBasketStateIx
19
29
  } from './instructions/management/createBasket';
20
30
  import {
21
31
  cancelIntentIx, createEditBasketIntentIx, executeEditBasketIntentIx
22
32
  } from './instructions/management/edit';
33
+ import {
34
+ createBasketLookupTablesInstruction, extendBasketLookupTablesIx, overwriteBasketLookupTablesIx
35
+ } from './instructions/management/luts';
23
36
  import {
24
37
  getAta, getBasketFeesPda, getBasketState, getBasketTokenMintPda, getGlobalConfigPda,
25
- getIntentPda, getRebalanceIntentPda, getRentPayerPda
38
+ getIntentPda, getLookupTableAccount, getRebalanceIntentPda, getRentPayerPda
26
39
  } from './instructions/pda';
27
40
  import { depositTokensIx, lockDepositsIx, mintBasketIx } from './instructions/user/deposit';
28
41
  import { redeemTokensIx } from './instructions/user/withdraw';
29
- import { Basket, BasketLayout } from './layouts/basket';
42
+ import { getJupTokenLedgerAndSwapInstructions } from './jup';
43
+ import {
44
+ Basket, BasketLayout, FormattedAccumulatedFees, FormattedAddTokenSettings, FormattedAsset,
45
+ FormattedAutomationSettings, FormattedBasket, FormattedCreatorSettings,
46
+ FormattedCustomRebalanceSettings, FormattedDepositsSettings, FormattedFeeSettings,
47
+ FormattedForceRebalanceSettings, FormattedLookupTables, FormattedLpSettings,
48
+ FormattedMakeDirectSwapSettings, FormattedManagersSettings, FormattedMetadataSettings,
49
+ FormattedOracle, FormattedOracleAggregator, FormattedOracleSettings, FormattedScheduleSettings,
50
+ FormattedUpdateWeightsSettings
51
+ } from './layouts/basket';
30
52
  import { FormattedGlobalConfig, GlobalConfig, GlobalConfigLayout } from './layouts/config';
31
53
  import { decimalToFraction } from './layouts/fraction';
32
54
  import {
33
- OracleInput, EditAddTokenSettings, EditAutomationSettings, EditCreatorSettings,
34
- EditCustomRebalanceSettings, EditDepositsSettings, EditFeeSettings,
35
- EditForceRebalanceSettings, EditLpSettings, EditMakeDirectSwapSettings,
36
- EditManagerSettings, EditMetadataSettings, EditScheduleSettings,
37
- EditUpdateWeightsSettings, Intent, MakeDirectSwapInput, Settings, TaskContext, TaskType,
38
- UpdateWeightsInput,
39
- FormattedIntentStatus,
40
- FormattedTaskType,
41
- FormattedIntent,
42
- FormattedBounty,
43
- FormattedBountySchedule,
44
- AddOrEditTokenInput,
55
+ AddOrEditTokenInput, EditAddTokenSettings, EditAutomationSettings, EditCreatorSettings,
56
+ EditCustomRebalanceSettings, EditDepositsSettings, EditFeeSettings, EditForceRebalanceSettings,
57
+ EditLpSettings, EditMakeDirectSwapSettings, EditManagerSettings, EditMetadataSettings,
58
+ EditScheduleSettings, EditUpdateWeightsSettings, FormattedBounty, FormattedBountySchedule,
59
+ FormattedIntent, FormattedIntentStatus, FormattedTaskType, Intent, MakeDirectSwapInput,
60
+ OracleInput, Settings, TaskContext, TaskType, UpdateWeightsInput
45
61
  } from './layouts/intents/intent';
46
- import { FormattedRebalanceType, FormattedRebalanceAction, FormattedOraclePrice, FormattedTokenAuction, FormattedTaskCompletion, FormattedRebalanceIntent } from './layouts/intents/rebalanceIntent';
47
62
  import {
48
- FormattedCreatorSettings, FormattedManagersSettings, FormattedFeeSettings,
49
- FormattedScheduleSettings, FormattedAutomationSettings, FormattedLpSettings,
50
- FormattedMetadataSettings, FormattedDepositsSettings, FormattedForceRebalanceSettings,
51
- FormattedCustomRebalanceSettings, FormattedAddTokenSettings, FormattedUpdateWeightsSettings,
52
- FormattedMakeDirectSwapSettings, FormattedAccumulatedFees, FormattedLookupTables, FormattedAsset,
53
- FormattedOracleSettings, FormattedOracleAggregator, FormattedOracle, FormattedBasket,
54
- } from './layouts/basket';
55
- import { RebalanceIntent, RebalanceType } from './layouts/intents/rebalanceIntent';
63
+ FormattedOraclePrice, FormattedRebalanceAction, FormattedRebalanceIntent,
64
+ FormattedRebalanceType, FormattedTaskCompletion, FormattedTokenAuction, RebalanceIntent,
65
+ RebalanceType
66
+ } from './layouts/intents/rebalanceIntent';
67
+ import { FormattedOracleType } from './layouts/oracle';
56
68
  import {
57
- BasketFilter, computeTokenMintsHash, fetchBaskektsMultiple, fetchBasket, fetchBaskets, loadBasketPrice
69
+ BasketFilter, computeTokenMintsHash, fetchBaskektsMultiple, fetchBasket, fetchBaskets,
70
+ loadBasketPrice
58
71
  } from './states/basket';
59
- import { fetchIntent, fetchIntents, fetchIntentsMultiple, IntentFilter } from './states/intents/intent';
60
- import { computeRebalanceIntentBountyAmount, fetchRebalanceIntent, fetchRebalanceIntents, fetchRebalanceIntentsMultiple, RebalanceIntentFilter } from './states/intents/rebalanceIntent';
72
+ import { fetchGlobalConfig } from './states/config';
73
+ import {
74
+ fetchIntent, fetchIntents, fetchIntentsMultiple, IntentFilter
75
+ } from './states/intents/intent';
76
+ import {
77
+ computeRebalanceIntentBountyAmount, fetchRebalanceIntent, fetchRebalanceIntents,
78
+ fetchRebalanceIntentsMultiple, RebalanceIntentFilter
79
+ } from './states/intents/rebalanceIntent';
61
80
  import {
62
- prepareTxPayloadBatchSequence, prepareVersionedTxs,
63
- sendTxPayloadBatchSequence, sendVersionedTxs, signTxPayloadBatchSequence, signVersionedTxs,
64
- TxBatchData, TxPayloadBatchSequence, VersionedTxs, Wallet,
65
- wrapWsolIxs
81
+ BasketCreationTx,
82
+ prepareTxPayloadBatchSequence, prepareVersionedTxs, sendTxPayloadBatchSequence,
83
+ sendVersionedTxs, signTxPayloadBatchSequence, signVersionedTxs, TxBatchData,
84
+ TxPayloadBatchSequence, VersionedTxs, Wallet, wrapWsolIxs
66
85
  } from './txUtils';
67
- import { FormattedOracleType } from './layouts/oracle';
68
- import { fetchGlobalConfig } from './states/config';
69
- import { flashDepositIx, flashWithdrawIx } from './instructions/automation/flashSwap';
70
- import { claimFeesIx } from './instructions/management/claimFees';
71
- import { getJupTokenLedgerAndSwapInstructions } from './jup';
72
- import { COMPUTE_UNITS, MINTS, PRIORITY_FEE } from './constants';
73
86
 
74
87
  export class SymmetryCore {
75
88
 
@@ -242,7 +255,7 @@ export class SymmetryCore {
242
255
  host_management_fee_bps: number,
243
256
  host_performance_fee_bps: number,
244
257
  },
245
- }): Promise<TxPayloadBatchSequence> {
258
+ }): Promise<BasketCreationTx> {
246
259
  const creator = new PublicKey(params.creator);
247
260
  const host = new PublicKey(params.host_platform_params?.host_pubkey ?? params.creator);
248
261
  const hostFees = {
@@ -303,7 +316,11 @@ export class SymmetryCore {
303
316
 
304
317
  let versionedTxs = await prepareVersionedTxs(this.sdkParams.connection, txBatchData);
305
318
  let txPayloadBatchSequence = prepareTxPayloadBatchSequence(txBatchData, versionedTxs);
306
- return txPayloadBatchSequence;
319
+ return {
320
+ mint: mint.toBase58(),
321
+ basket: basket.toBase58(),
322
+ batches: txPayloadBatchSequence.batches,
323
+ };
307
324
  }
308
325
 
309
326
  async editCreatorTx(context: TaskContext, settings: EditCreatorSettings): Promise<TxPayloadBatchSequence> {
@@ -1215,6 +1232,44 @@ export class SymmetryCore {
1215
1232
  return txPayloadBatchSequence;
1216
1233
  }
1217
1234
 
1235
+ async addBountyTx(params: {
1236
+ keeper: string,
1237
+ basket: string,
1238
+ amount: number,
1239
+ }): Promise<TxPayloadBatchSequence> {
1240
+ let keeper = new PublicKey(params.keeper);
1241
+ let basket = await this.fetchBasket(params.basket);
1242
+ let globalConfig = await this.fetchGlobalConfig();
1243
+ let bountyWsolAmount = 0;
1244
+ if (globalConfig.bountyMint.equals(MINTS["mainnet"].WSOL)) {
1245
+ bountyWsolAmount = params.amount;
1246
+ }
1247
+ let wsolIxs = await wrapWsolIxs(
1248
+ this.sdkParams.connection,
1249
+ keeper,
1250
+ bountyWsolAmount,
1251
+ );
1252
+ let ix = addBountyIx({
1253
+ keeper: keeper,
1254
+ basket: basket.ownAddress,
1255
+ bountyMint: basket.settings.bountyMint,
1256
+ amount: params.amount,
1257
+ });
1258
+ let txBatchData: TxBatchData = {batches: [[{
1259
+ payer: keeper,
1260
+ instructions: [
1261
+ ...wsolIxs,
1262
+ ix,
1263
+ ComputeBudgetProgram.setComputeUnitLimit({units: COMPUTE_UNITS}),
1264
+ ComputeBudgetProgram.setComputeUnitPrice({microLamports: this.sdkParams.priorityFee}),
1265
+ ],
1266
+ lookupTables: [],
1267
+ }]]};
1268
+ let versionedTxs = await prepareVersionedTxs(this.sdkParams.connection, txBatchData);
1269
+ let txPayloadBatchSequence = prepareTxPayloadBatchSequence(txBatchData, versionedTxs);
1270
+ return txPayloadBatchSequence;
1271
+ }
1272
+
1218
1273
  async claimBasketFeesTx(params: {
1219
1274
  claimer: string,
1220
1275
  basket: string,
@@ -1265,6 +1320,98 @@ export class SymmetryCore {
1265
1320
  return txPayloadBatchSequence;
1266
1321
  }
1267
1322
 
1323
+ async rewriteLookupTablesTx(params: {
1324
+ signer: string,
1325
+ basket_mint: string,
1326
+ additional_accounts: string[],
1327
+ }): Promise<TxPayloadBatchSequence> {
1328
+ const signer = new PublicKey(params.signer);
1329
+ const basketMint = new PublicKey(params.basket_mint);
1330
+ const additionalAccounts = params.additional_accounts.map(a => new PublicKey(a));
1331
+
1332
+ const basketAddress = getBasketState(basketMint);
1333
+ const basket = await this.fetchBasket(basketAddress.toBase58());
1334
+
1335
+ const activeLut0 = basket.lookupTables.active[0];
1336
+ const activeLut1 = basket.lookupTables.active[1];
1337
+ let oldTempLut0 = basket.lookupTables.temp[0];
1338
+ let oldTempLut1 = basket.lookupTables.temp[1];
1339
+
1340
+ const slot = await this.sdkParams.connection.getSlot("finalized");
1341
+ const newLut0 = getLookupTableAccount(basketAddress, slot);
1342
+ const newLut1 = getLookupTableAccount(basketAddress, slot - 1);
1343
+
1344
+ // Step 1: create lookup tables
1345
+ const createIx = createBasketLookupTablesInstruction({
1346
+ signer,
1347
+ basket: basketAddress,
1348
+ oldTempLookupTable0: oldTempLut0,
1349
+ oldTempLookupTable1: oldTempLut1,
1350
+ newTempLookupTable0: newLut0,
1351
+ newTempLookupTable1: newLut1,
1352
+ slot,
1353
+ });
1354
+
1355
+ const txBatchData: TxBatchData = { batches: [
1356
+ [{
1357
+ payer: signer,
1358
+ instructions: [
1359
+ createIx,
1360
+ ComputeBudgetProgram.setComputeUnitLimit({ units: COMPUTE_UNITS }),
1361
+ ComputeBudgetProgram.setComputeUnitPrice({ microLamports: this.sdkParams.priorityFee }),
1362
+ ],
1363
+ lookupTables: [],
1364
+ }],
1365
+ ]};
1366
+
1367
+ // Step 2: extend LUTs in batches of ~20
1368
+ const BATCH_SIZE = LUT_EXTEND_BATCH_SIZE;
1369
+ for (let i = 0; i < additionalAccounts.length; i += BATCH_SIZE) {
1370
+ const batch = additionalAccounts.slice(i, i + BATCH_SIZE);
1371
+ const extendIx = extendBasketLookupTablesIx({
1372
+ signer,
1373
+ basket: basketAddress,
1374
+ tempLookupTable0: newLut0,
1375
+ tempLookupTable1: newLut1,
1376
+ additionalAccounts: batch,
1377
+ });
1378
+ txBatchData.batches.push([{
1379
+ payer: signer,
1380
+ instructions: [
1381
+ extendIx,
1382
+ ComputeBudgetProgram.setComputeUnitLimit({ units: COMPUTE_UNITS }),
1383
+ ComputeBudgetProgram.setComputeUnitPrice({ microLamports: this.sdkParams.priorityFee }),
1384
+ ],
1385
+ lookupTables: [],
1386
+ }]);
1387
+ }
1388
+
1389
+ // Step 3: overwrite active LUTs
1390
+ const overwriteIx = overwriteBasketLookupTablesIx({
1391
+ signer,
1392
+ basket: basketAddress,
1393
+ tempLookupTable0: newLut0,
1394
+ tempLookupTable1: newLut1,
1395
+ activeLookupTable0: activeLut0,
1396
+ activeLookupTable1: activeLut1,
1397
+ });
1398
+
1399
+ txBatchData.batches.push([{
1400
+ payer: signer,
1401
+ instructions: [
1402
+ overwriteIx,
1403
+ ComputeBudgetProgram.setComputeUnitLimit({ units: COMPUTE_UNITS }),
1404
+ ComputeBudgetProgram.setComputeUnitPrice({ microLamports: this.sdkParams.priorityFee }),
1405
+ ],
1406
+ lookupTables: [],
1407
+ }]);
1408
+
1409
+ const versionedTxs = await prepareVersionedTxs(this.sdkParams.connection, txBatchData);
1410
+ const txPayloadBatchSequence = prepareTxPayloadBatchSequence(txBatchData, versionedTxs);
1411
+ return txPayloadBatchSequence;
1412
+ }
1413
+
1414
+
1268
1415
  async signAndSendVersionedTxs(params: {
1269
1416
  versionedTxs: VersionedTxs,
1270
1417
  wallet: Wallet,
@@ -26,7 +26,7 @@ export function addBountyIx(params: {
26
26
  let bountyVault = getBountyVaultPda();
27
27
  let globalConfig = getGlobalConfigPda();
28
28
  let keeperBountyAta = getAta(keeper, bountyMint);
29
- let bountyVaultAta = getAta(bountyMint, bountyVault);
29
+ let bountyVaultAta = getAta(bountyVault, bountyMint);
30
30
 
31
31
  const data = Buffer.concat([
32
32
  ADD_BOUNTY_DISCRIMINATOR,
@@ -1,8 +1,11 @@
1
1
  import { BN, Program } from '@coral-xyz/anchor';
2
- import { PublicKey, SystemProgram, TransactionInstruction } from '@solana/web3.js';
3
- import { ADDRESS_LOOKUP_TABLE_PROGRAM_ID, BASKETS_V3_PROGRAM_ID } from '../../constants';
4
- import { getLookupTableInfoAccount } from '../pda';
2
+ import { AccountMeta, PublicKey, SystemProgram, TransactionInstruction } from '@solana/web3.js';
5
3
 
4
+ import {
5
+ ADDRESS_LOOKUP_TABLE_PROGRAM_ID, BASKETS_V3_PROGRAM_ID, PYTHNET_CUSTODY_PRICE_USDC_ACCOUNT,
6
+ PYTHNET_CUSTODY_PRICE_WSOL_ACCOUNT
7
+ } from '../../constants';
8
+ import { getGlobalConfigPda, getLookupTableInfoAccount } from '../pda';
6
9
 
7
10
  const CREATE_BASKET_LOOKUP_TABLES_DISCRIMINATOR = Buffer.from([227,98,152,128,87,46,244,99]);
8
11
  const EXTEND_BASKET_LOOKUP_TABLES_DISCRIMINATOR = Buffer.from([98, 129, 153, 127, 181, 160, 117, 74]);
@@ -29,32 +32,48 @@ export function createBasketLookupTablesInstruction(params: {
29
32
  slot,
30
33
  } = params;
31
34
 
32
- let newTempLookupTableInfo0 = getLookupTableInfoAccount(newTempLookupTable0);
33
- let newTempLookupTableInfo1 = getLookupTableInfoAccount(newTempLookupTable1);
35
+ const globalConfig = getGlobalConfigPda();
36
+ const hasOldTemp = !oldTempLookupTable0.equals(PublicKey.default)
37
+ && !oldTempLookupTable1.equals(PublicKey.default);
34
38
 
35
39
  const data = Buffer.concat([
36
40
  CREATE_BASKET_LOOKUP_TABLES_DISCRIMINATOR,
37
- new BN(slot).toArray("le", 8),
41
+ Buffer.from(new BN(slot).toArray("le", 8)),
38
42
  ]);
39
43
 
40
- const keys = [
44
+ const keys: AccountMeta[] = [
41
45
  { pubkey: signer, isSigner: true, isWritable: true },
42
46
  { pubkey: basket, isSigner: false, isWritable: true },
43
- { pubkey: oldTempLookupTable0, isSigner: false, isWritable: true },
44
- { pubkey: oldTempLookupTable1, isSigner: false, isWritable: true },
47
+ { pubkey: globalConfig, isSigner: false, isWritable: false },
48
+ { pubkey: hasOldTemp ? oldTempLookupTable0 : PYTHNET_CUSTODY_PRICE_USDC_ACCOUNT, isSigner: false, isWritable: true },
49
+ { pubkey: hasOldTemp ? oldTempLookupTable1 : PYTHNET_CUSTODY_PRICE_WSOL_ACCOUNT, isSigner: false, isWritable: true },
45
50
  { pubkey: newTempLookupTable0, isSigner: false, isWritable: true },
46
51
  { pubkey: newTempLookupTable1, isSigner: false, isWritable: true },
47
- { pubkey: newTempLookupTableInfo0, isSigner: false, isWritable: true },
48
- { pubkey: newTempLookupTableInfo1, isSigner: false, isWritable: true },
52
+ ];
53
+
54
+ if (hasOldTemp) {
55
+ keys.push(
56
+ { pubkey: getLookupTableInfoAccount(oldTempLookupTable0), isSigner: false, isWritable: true },
57
+ { pubkey: getLookupTableInfoAccount(oldTempLookupTable1), isSigner: false, isWritable: true },
58
+ );
59
+ }
60
+ else {
61
+ keys.push(
62
+ { pubkey: BASKETS_V3_PROGRAM_ID, isSigner: false, isWritable: false },
63
+ { pubkey: BASKETS_V3_PROGRAM_ID, isSigner: false, isWritable: false },
64
+ );
65
+ }
66
+
67
+ keys.push(
49
68
  { pubkey: ADDRESS_LOOKUP_TABLE_PROGRAM_ID, isSigner: false, isWritable: false },
50
69
  { pubkey: SystemProgram.programId, isSigner: false, isWritable: false },
51
- ];
70
+ );
52
71
 
53
- return new TransactionInstruction({
54
- keys,
55
- programId: BASKETS_V3_PROGRAM_ID,
56
- data,
57
- });
72
+ return new TransactionInstruction({
73
+ keys,
74
+ programId: BASKETS_V3_PROGRAM_ID,
75
+ data,
76
+ });
58
77
  }
59
78
 
60
79
  export function extendBasketLookupTablesIx(
@@ -63,6 +82,7 @@ export function extendBasketLookupTablesIx(
63
82
  basket: PublicKey;
64
83
  tempLookupTable0: PublicKey;
65
84
  tempLookupTable1: PublicKey;
85
+ additionalAccounts: PublicKey[];
66
86
  }): TransactionInstruction {
67
87
 
68
88
  const keys = [
@@ -72,6 +92,7 @@ export function extendBasketLookupTablesIx(
72
92
  { pubkey: params.tempLookupTable1, isWritable: true, isSigner: false },
73
93
  { pubkey: ADDRESS_LOOKUP_TABLE_PROGRAM_ID, isWritable: false, isSigner: false },
74
94
  { pubkey: SystemProgram.programId, isWritable: false, isSigner: false },
95
+ ...params.additionalAccounts.map(pubkey => ({pubkey, isWritable: false, isSigner: false})),
75
96
  ];
76
97
 
77
98
  return new TransactionInstruction({
@@ -99,6 +120,9 @@ export function overwriteBasketLookupTablesIx(
99
120
  { pubkey: params.tempLookupTable1, isWritable: true, isSigner: false },
100
121
  { pubkey: params.activeLookupTable0, isWritable: true, isSigner: false },
101
122
  { pubkey: params.activeLookupTable1, isWritable: true, isSigner: false },
123
+ { pubkey: getLookupTableInfoAccount(params.activeLookupTable0), isWritable: true, isSigner: false },
124
+ { pubkey: getLookupTableInfoAccount(params.activeLookupTable1), isWritable: true, isSigner: false },
125
+ { pubkey: ADDRESS_LOOKUP_TABLE_PROGRAM_ID, isWritable: false, isSigner: false },
102
126
  { pubkey: SystemProgram.programId, isWritable: false, isSigner: false },
103
127
  ];
104
128
 
@@ -493,7 +493,29 @@ class RebalanceIntentRustClass {
493
493
  }
494
494
  }
495
495
 
496
-
496
+ /**
497
+ * Returns all valid swap pairs available during the rebalance auction phase.
498
+ *
499
+ * **Swap direction (basket perspective):**
500
+ * - `inMint` / `inAmount`: what the basket is supposed to **receive**.
501
+ * - `outMint` / `outAmount`: what the basket wants to **swap** (give away).
502
+ * So each pair describes an **outMint → inMint** swap. When generating swap
503
+ * transactions, use this direction: swap `outMint` → `inMint` (sell outAmount of
504
+ * outMint, receive inAmount of inMint).
505
+ *
506
+ * Only runs when the rebalance is in Auction action and the current time falls
507
+ * within one of the three auction windows. For the active auction, target amounts
508
+ * are refreshed if they haven't been updated since the auction started.
509
+ *
510
+ * Iterates over completed price-update tokens to compute exchange rates via
511
+ * getSwapAmounts (using time-since-start and auction duration). Pairs with
512
+ * positive in/out amounts are collected and sorted by value descending
513
+ * (highest value first).
514
+ *
515
+ * @param rebalanceIntent - The rebalance intent state
516
+ * @param basket - The basket (used to update target amounts when needed)
517
+ * @returns Array of swap pairs, or empty array when not in auction or outside auction windows
518
+ */
497
519
  export function getSwapPairs(
498
520
  rebalanceIntent: RebalanceIntent,
499
521
  basket: Basket,
package/src/txUtils.ts CHANGED
@@ -93,6 +93,11 @@ export interface TxPayloadBatchSequence {
93
93
  batches: TxPayloadBatch[];
94
94
  }
95
95
 
96
+ export interface BasketCreationTx extends TxPayloadBatchSequence {
97
+ mint: string;
98
+ basket: string;
99
+ }
100
+
96
101
  export function prepareTxPayloadBatchSequence(
97
102
  txBatchData: TxBatchData,
98
103
  versionedTxs?: VersionedTxs,
package/test.ts CHANGED
@@ -17,6 +17,7 @@ let jupApiKey = "";
17
17
  let connection = new Connection("https://api.devnet.solana.com");
18
18
 
19
19
  async function testStates() {
20
+ return;
20
21
  let wallet = new Wallet(Keypair.fromSecretKey(new Uint8Array(kp)));
21
22
  console.log(wallet.publicKey.toBase58());
22
23
 
@@ -44,6 +45,9 @@ async function testStates() {
44
45
  let basket = await sdk.fetchBasket("GrBFFvtdRL25o7gcRnV1kGvz1Qc7iscUmDp1ZvyBSyUa");
45
46
  basket = await sdk.loadBasketPrice(basket);
46
47
  console.log(basket.formatted);
48
+ // console.log(basket.composition[0].mint.toBase58(), "amount:", basket.composition[0].amount.toString(), "price:", basket.composition[0].price?.price, "value:", basket.composition[0].value);
49
+ // console.log(basket.composition[1].mint.toBase58(), "amount:", basket.composition[1].amount.toString(), "price:", basket.composition[1].price?.price, "value:", basket.composition[1].value);
50
+ // console.log(basket.composition[2].mint.toBase58(), "amount:", basket.composition[2].amount.toString(), "price:", basket.composition[2].price?.price, "value:", basket.composition[2].value);
47
51
  // return;
48
52
 
49
53
  let tests = {
@@ -53,6 +57,7 @@ async function testStates() {
53
57
 
54
58
  createBasket: false, // TESTED
55
59
  editPrivateBasketSettings: false, // NOT TESTED
60
+ addBounty: false, // TESTED
56
61
 
57
62
  editCreator: false, // TESTED
58
63
  editManagerSettings: false, // TESTED
@@ -62,8 +67,8 @@ async function testStates() {
62
67
  editLpSettings: false, // TESTED
63
68
  editMetadata: false, // TESTED
64
69
  editDepositsSettings: false, // TESTED
65
- editForceRebalanceSettings: false, // NOT TESTED
66
- editCustomRebalanceSettings: false, // NOT TESTED
70
+ editForceRebalanceSettings: false, // TESTED
71
+ editCustomRebalanceSettings: false, // TESTED
67
72
  editAddTokenDelay: false, // NOT TESTED
68
73
  editUpdateWeightsDelay: false, // NOT TESTED
69
74
  editMakeDirectSwapDelay: false, // NOT TESTED
@@ -72,7 +77,7 @@ async function testStates() {
72
77
  updateWeights: false, // NOT TESTED
73
78
  makeDirectSwap: false, // NOT TESTED
74
79
 
75
- executeIntent: false, // NOT TESTED
80
+ executeIntent: false, // TESTED
76
81
 
77
82
  buyBasket: false, // TESTED
78
83
  depositTokens: false, // TESTED
@@ -80,7 +85,7 @@ async function testStates() {
80
85
 
81
86
  sellBasket: false, // TESTED
82
87
 
83
- rebalanceBasket: false, // NOT TESTED
88
+ rebalanceBasket: false, // TESTED
84
89
  rebalanceBasketCustom: false, // NOT TESTED
85
90
 
86
91
  startPriceUpdates: false, // TESTED
@@ -113,6 +118,16 @@ async function testStates() {
113
118
  console.log(resCreateBasket);
114
119
  }
115
120
 
121
+ if (tests.addBounty) {
122
+ let tx = await sdk.addBountyTx({
123
+ keeper: wallet.publicKey.toBase58(),
124
+ basket: basket.ownAddress.toBase58(),
125
+ amount: 250 * 10 ** 6,
126
+ });
127
+ let res = await sdk.signAndSendTxPayloadBatchSequence({txPayloadBatchSequence: tx, wallet});
128
+ console.log(res);
129
+ }
130
+
116
131
  let task_context: TaskContext = {
117
132
  basket: basket.ownAddress.toBase58(),
118
133
  manager: wallet.publicKey.toBase58(),