@symmetry-hq/sdk 1.0.10 → 1.0.12

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.
package/dist/src/index.js CHANGED
@@ -729,6 +729,12 @@ class SymmetryCore {
729
729
  let maxBountyPerTask = parseInt(maxBounty.toString());
730
730
  bountyWsolAmount = maxBountyPerTask + boundBounty;
731
731
  }
732
+ if (editType === intent_1.TaskType.EditAutomationSettings && editData.enabled == true) {
733
+ let bountyBalance = parseInt(vault.settings.bountyBalance.toString());
734
+ let requiredBounty = parseInt(globalConfig.minBountyForVaultAutomation.toString());
735
+ if (bountyBalance < requiredBounty)
736
+ bountyWsolAmount += 2 * requiredBounty - bountyBalance;
737
+ }
732
738
  let wsolIxs = yield (0, txUtils_1.wrapWsolIxs)(this.sdkParams.connection, manager, bountyWsolAmount);
733
739
  let intentSeedArray = web3_js_1.Keypair.generate().publicKey.toBytes();
734
740
  let tokenProgram = undefined;
@@ -1367,6 +1373,16 @@ class SymmetryCore {
1367
1373
  maxBountyPerTask = maxBountyAmount;
1368
1374
  bountyWsolAmount = (0, rebalanceIntent_3.computeRebalanceIntentBountyAmount)(rebalanceIntent_2.RebalanceType.Vault, vault.numTokens, boundBounty, maxBountyPerTask, Math.floor(maxBountyPerTask / bountyPerPriceUpdateTaskDivisor));
1369
1375
  }
1376
+ let isManager = vault.settings.creator.equals(keeper);
1377
+ for (let i = 0; i < vault.settings.managers.managers.length; i++)
1378
+ if (vault.settings.managers.managers[i].equals(keeper))
1379
+ isManager = true;
1380
+ if (isManager) {
1381
+ let bountyBalance = parseInt(vault.settings.bountyBalance.toString());
1382
+ let requiredBounty = parseInt(globalConfig.minBountyForVaultAutomation.toString());
1383
+ if (bountyBalance < requiredBounty)
1384
+ bountyWsolAmount += 2 * requiredBounty - bountyBalance;
1385
+ }
1370
1386
  let wsolIxs = yield (0, txUtils_1.wrapWsolIxs)(this.sdkParams.connection, keeper, bountyWsolAmount);
1371
1387
  const rebalanceIntent = (0, pda_1.getRebalanceIntentPda)(vault.ownAddress, vault.ownAddress);
1372
1388
  let rentPayer = (0, pda_1.getRentPayerPda)();
@@ -1538,7 +1554,7 @@ class SymmetryCore {
1538
1554
  payer: keeper,
1539
1555
  instructions: [
1540
1556
  ix,
1541
- web3_js_1.ComputeBudgetProgram.setComputeUnitLimit({ units: constants_1.COMPUTE_UNITS }),
1557
+ web3_js_1.ComputeBudgetProgram.setComputeUnitLimit({ units: 1400000 }),
1542
1558
  web3_js_1.ComputeBudgetProgram.setComputeUnitPrice({ microLamports: this.sdkParams.priorityFee }),
1543
1559
  ],
1544
1560
  lookupTables: [vault.lookupTables.active[0], vault.lookupTables.active[1]],
@@ -0,0 +1,32 @@
1
+ import { Connection, PublicKey } from "@solana/web3.js";
2
+ import { Wallet } from "./txUtils";
3
+ import { Basket, UIRebalanceIntent } from ".";
4
+ export declare class RebalanceHandler {
5
+ private params;
6
+ private intent;
7
+ private basket;
8
+ constructor(params: {
9
+ intent: UIRebalanceIntent;
10
+ basket: Basket;
11
+ wallet: Wallet;
12
+ connection: Connection;
13
+ network: "devnet" | "mainnet";
14
+ jupiterApiKey: string;
15
+ maxAllowedAccounts: number;
16
+ priorityFee?: number;
17
+ simulateTransactions?: boolean;
18
+ });
19
+ delay: (ms: number) => Promise<unknown>;
20
+ refresh(): Promise<void>;
21
+ static run(params: {
22
+ intentPubkey: PublicKey;
23
+ wallet: Wallet;
24
+ connection: Connection;
25
+ network: "devnet" | "mainnet";
26
+ jupiterApiKey: string;
27
+ maxAllowedAccounts: number;
28
+ priorityFee?: number;
29
+ simulateTransactions?: boolean;
30
+ }): Promise<void>;
31
+ private execute;
32
+ }
@@ -0,0 +1,278 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.RebalanceHandler = void 0;
13
+ const web3_js_1 = require("@solana/web3.js");
14
+ const _1 = require(".");
15
+ const rebalanceIntent_1 = require("./states/intents/rebalanceIntent");
16
+ const constants_1 = require("./constants");
17
+ class RebalanceHandler {
18
+ constructor(params) {
19
+ var _a, _b;
20
+ this.delay = (ms) => __awaiter(this, void 0, void 0, function* () { return new Promise(resolve => setTimeout(resolve, ms)); });
21
+ this.params = {
22
+ wallet: params.wallet,
23
+ connection: params.connection,
24
+ symmetryCore: new _1.SymmetryCore({
25
+ connection: params.connection,
26
+ network: params.network,
27
+ priorityFee: (_a = params.priorityFee) !== null && _a !== void 0 ? _a : constants_1.PRIORITY_FEE,
28
+ }),
29
+ network: params.network,
30
+ jupiterApiKey: params.jupiterApiKey,
31
+ maxAllowedAccounts: params.maxAllowedAccounts,
32
+ simulateTransactions: (_b = params.simulateTransactions) !== null && _b !== void 0 ? _b : false,
33
+ };
34
+ this.intent = params.intent;
35
+ this.basket = params.basket;
36
+ }
37
+ refresh() {
38
+ return __awaiter(this, void 0, void 0, function* () {
39
+ this.intent = yield this.params.symmetryCore.fetchRebalanceIntent(this.intent.formatted_data.pubkey);
40
+ this.basket = yield this.params.symmetryCore.fetchBasket(this.intent.formatted_data.basket);
41
+ });
42
+ }
43
+ static run(params) {
44
+ return __awaiter(this, void 0, void 0, function* () {
45
+ var _a;
46
+ let symmetryCore = new _1.SymmetryCore({
47
+ connection: params.connection,
48
+ network: params.network,
49
+ priorityFee: (_a = params.priorityFee) !== null && _a !== void 0 ? _a : constants_1.PRIORITY_FEE,
50
+ });
51
+ let intent = yield symmetryCore.fetchRebalanceIntent(params.intentPubkey.toBase58());
52
+ let basket = yield symmetryCore.fetchBasket(intent.formatted_data.basket);
53
+ let handler = new RebalanceHandler({
54
+ intent, basket,
55
+ wallet: params.wallet,
56
+ connection: params.connection,
57
+ network: params.network,
58
+ jupiterApiKey: params.jupiterApiKey,
59
+ maxAllowedAccounts: params.maxAllowedAccounts,
60
+ simulateTransactions: params.simulateTransactions,
61
+ });
62
+ handler.execute();
63
+ for (let i = 0; i < 20; i++) {
64
+ yield handler.delay(15 * 1000);
65
+ try {
66
+ yield handler.refresh();
67
+ }
68
+ catch (e) {
69
+ break;
70
+ }
71
+ }
72
+ });
73
+ }
74
+ execute() {
75
+ return __awaiter(this, void 0, void 0, function* () {
76
+ var _a, _b;
77
+ console.log("Starting rebalance handler for intent:", this.intent.formatted_data.pubkey);
78
+ let nextCheckTime = 0;
79
+ let numTriesUpdatePrices = 0;
80
+ let numTriesMint = 0;
81
+ let numTriesRedeemTokens = 0;
82
+ let numTriesClaimBounty = 0;
83
+ let rebalancePairs = [];
84
+ let lastJupQuotesUpdate = 0;
85
+ let jupQuotes = [];
86
+ while (true) {
87
+ if (!this.intent)
88
+ break;
89
+ let intent = this.intent.formatted_data;
90
+ let chainData = this.intent.chain_data;
91
+ let now = Date.now() / 1000;
92
+ if (now < nextCheckTime) {
93
+ yield this.delay(Math.min(30 * 1000, Math.max(0, nextCheckTime - now + 0.2) * 1000));
94
+ continue;
95
+ }
96
+ nextCheckTime = now + 35;
97
+ if (intent.current_action == "not_active") {
98
+ console.log("Intent not active, stopping");
99
+ break;
100
+ }
101
+ if (intent.current_action == "deposit_tokens") {
102
+ console.log("Waiting for deposit...");
103
+ continue;
104
+ }
105
+ if (intent.current_action == "update_prices" && intent.last_action_timestamp > now) {
106
+ nextCheckTime = intent.last_action_timestamp;
107
+ continue;
108
+ }
109
+ if (intent.current_action == "update_prices") {
110
+ if (numTriesUpdatePrices >= 3) {
111
+ console.log("Max retries for update_prices");
112
+ break;
113
+ }
114
+ numTriesUpdatePrices += 1;
115
+ try {
116
+ let tx = yield this.params.symmetryCore.updateTokenPricesTx({
117
+ keeper: this.params.wallet.publicKey.toBase58(),
118
+ basket: intent.basket,
119
+ rebalance_intent: intent.pubkey,
120
+ });
121
+ let res = yield this.params.symmetryCore.signAndSendTxPayloadBatchSequence({ txPayloadBatchSequence: tx, wallet: this.params.wallet, simulateTransactions: this.params.simulateTransactions });
122
+ console.log("Update Prices:", res);
123
+ }
124
+ catch (e) {
125
+ if (numTriesUpdatePrices == 3) {
126
+ console.log("Stop - update prices failed:", e);
127
+ }
128
+ }
129
+ continue;
130
+ }
131
+ if (intent.auctions[2].end_time > now) {
132
+ let auction0StartTime = intent.auctions[0].start_time;
133
+ let auction0EndTime = intent.auctions[0].end_time;
134
+ let auction1StartTime = intent.auctions[1].start_time;
135
+ let auction1EndTime = intent.auctions[1].end_time;
136
+ let auction2StartTime = intent.auctions[2].start_time;
137
+ let auction2EndTime = intent.auctions[2].end_time;
138
+ rebalancePairs = (0, rebalanceIntent_1.getSwapPairs)(chainData, this.basket);
139
+ if (Date.now() / 1000 > lastJupQuotesUpdate + 60) {
140
+ let usedValue = new Map();
141
+ jupQuotes = [];
142
+ for (let pair of rebalancePairs) {
143
+ let inValue = (_a = usedValue.get(pair.inMint)) !== null && _a !== void 0 ? _a : 0;
144
+ let outValue = (_b = usedValue.get(pair.outMint)) !== null && _b !== void 0 ? _b : 0;
145
+ let swapValue = Math.min(pair.value - inValue, pair.value - outValue);
146
+ if (swapValue < 0.005) {
147
+ jupQuotes.push(undefined);
148
+ continue;
149
+ }
150
+ usedValue.set(pair.inMint, inValue + swapValue);
151
+ usedValue.set(pair.outMint, outValue + swapValue);
152
+ let res = undefined;
153
+ if (this.params.network == "mainnet")
154
+ try {
155
+ res = Object.assign(Object.assign({}, (yield (0, _1.getJupTokenLedgerAndSwapInstructions)({
156
+ keeper: this.params.wallet.publicKey,
157
+ basketMintIn: new web3_js_1.PublicKey(pair.inMint),
158
+ basketMintOut: new web3_js_1.PublicKey(pair.outMint),
159
+ basketAmountIn: pair.inAmount,
160
+ basketAmountOut: pair.outAmount,
161
+ swapMode: "ioc",
162
+ apiKey: this.params.jupiterApiKey,
163
+ maxJupAccounts: this.params.maxAllowedAccounts,
164
+ }))), { inMint: pair.inMint, outMint: pair.outMint });
165
+ }
166
+ catch (_c) { }
167
+ ;
168
+ jupQuotes.push(res);
169
+ }
170
+ }
171
+ for (let index = 0; index < rebalancePairs.length; index++)
172
+ try {
173
+ let pair = rebalancePairs[index];
174
+ let quote = jupQuotes.find(q => q && q.inMint == pair.inMint && q.outMint == pair.outMint);
175
+ if (!quote)
176
+ continue;
177
+ if (pair.value < 0.005)
178
+ continue;
179
+ let { tokenLedgerInstruction, swapInstruction, addressLookupTableAddresses, quoteResponse } = quote;
180
+ if (!quoteResponse)
181
+ continue;
182
+ console.log(pair, "Jup Quote:", parseFloat(quoteResponse.outAmount), "Requested In:", pair.inAmount);
183
+ if (parseFloat(quoteResponse.outAmount) <= pair.inAmount && this.params.network == "mainnet")
184
+ continue;
185
+ try {
186
+ let tx = yield this.params.symmetryCore.flashSwapTx({
187
+ keeper: this.params.wallet.publicKey.toBase58(),
188
+ basket: this.basket.ownAddress.toBase58(),
189
+ rebalance_intent: intent.pubkey,
190
+ mint_in: pair.inMint,
191
+ mint_out: pair.outMint,
192
+ amount_in: pair.inAmount,
193
+ amount_out: pair.outAmount,
194
+ mode: 2,
195
+ jup_token_ledger_ix: tokenLedgerInstruction,
196
+ jup_swap_ix: swapInstruction,
197
+ jup_address_lookup_table_addresses: addressLookupTableAddresses,
198
+ });
199
+ let res = yield this.params.symmetryCore.signAndSendTxPayloadBatchSequence({ txPayloadBatchSequence: tx, wallet: this.params.wallet, simulateTransactions: this.params.simulateTransactions });
200
+ console.log("Flash Swap:", res);
201
+ rebalancePairs = rebalancePairs.splice(index, 1);
202
+ index -= 1;
203
+ }
204
+ catch (_d) { }
205
+ }
206
+ catch (_e) { }
207
+ nextCheckTime = (Date.now() / 1000) + 10;
208
+ continue;
209
+ }
210
+ if (intent.rebalance_type == "deposit") {
211
+ lastJupQuotesUpdate = 0;
212
+ if (numTriesMint >= 3) {
213
+ console.log("Max retries for mint");
214
+ break;
215
+ }
216
+ numTriesMint += 1;
217
+ try {
218
+ let tx = yield this.params.symmetryCore.mintTx({
219
+ keeper: this.params.wallet.publicKey.toBase58(),
220
+ rebalance_intent: intent.pubkey,
221
+ });
222
+ let res = yield this.params.symmetryCore.signAndSendTxPayloadBatchSequence({ txPayloadBatchSequence: tx, wallet: this.params.wallet, simulateTransactions: this.params.simulateTransactions });
223
+ console.log("Mint:", res);
224
+ }
225
+ catch (e) {
226
+ if (numTriesMint == 3) {
227
+ console.log("Stop - mint failed:", e);
228
+ }
229
+ }
230
+ continue;
231
+ }
232
+ let hasTokens = intent.tokens.find((token) => token.amount > 0);
233
+ if (hasTokens && intent.rebalance_type == "withdraw") {
234
+ if (numTriesRedeemTokens >= 3) {
235
+ console.log("Max retries for redeem");
236
+ break;
237
+ }
238
+ numTriesRedeemTokens += 1;
239
+ try {
240
+ let tx = yield this.params.symmetryCore.redeemTokensTx({
241
+ keeper: this.params.wallet.publicKey.toBase58(),
242
+ rebalance_intent: intent.pubkey,
243
+ });
244
+ let res = yield this.params.symmetryCore.signAndSendTxPayloadBatchSequence({ txPayloadBatchSequence: tx, wallet: this.params.wallet, simulateTransactions: this.params.simulateTransactions });
245
+ console.log("Redeem Tokens:", res);
246
+ }
247
+ catch (e) {
248
+ if (numTriesRedeemTokens == 3) {
249
+ console.log("Stop - redeem failed:", e);
250
+ }
251
+ }
252
+ continue;
253
+ }
254
+ if (numTriesClaimBounty >= 3) {
255
+ console.log("Max retries for claim bounty");
256
+ break;
257
+ }
258
+ numTriesClaimBounty += 1;
259
+ try {
260
+ let tx = yield this.params.symmetryCore.claimBountyTx({
261
+ keeper: this.params.wallet.publicKey.toBase58(),
262
+ rebalance_intent: intent.pubkey,
263
+ });
264
+ let res = yield this.params.symmetryCore.signAndSendTxPayloadBatchSequence({ txPayloadBatchSequence: tx, wallet: this.params.wallet, simulateTransactions: this.params.simulateTransactions });
265
+ console.log("Claim Bounty:", res);
266
+ nextCheckTime = now + 60;
267
+ }
268
+ catch (e) {
269
+ if (numTriesClaimBounty == 3) {
270
+ console.log("Stop - claim bounty failed:", e);
271
+ }
272
+ }
273
+ }
274
+ console.log("Rebalance handler finished for intent:", this.intent.formatted_data.pubkey);
275
+ });
276
+ }
277
+ }
278
+ exports.RebalanceHandler = RebalanceHandler;
@@ -153,23 +153,33 @@ function formatRebalanceIntent(rebalanceIntent, vault) {
153
153
  })),
154
154
  };
155
155
  if (vault) {
156
+ const auctionTokenByMint = new Map(auctionData.tokens.map(token => [token.mint, token]));
157
+ const mintDataTokenByMint = new Map(mintData.tokens.map(token => [token.mint, token]));
156
158
  let minRatio = 1;
157
- for (let i = 0; i < vault.composition.length; i++) {
158
- if (vault.composition[i].amount == 0)
159
+ for (const vaultToken of vault.composition) {
160
+ if (vaultToken.amount == 0)
159
161
  continue;
160
- let ratio = auctionData.tokens[i].amount / vault.composition[i].amount;
162
+ const auctionToken = auctionTokenByMint.get(vaultToken.mint);
163
+ if (!auctionToken)
164
+ continue;
165
+ let ratio = auctionToken.amount / vaultToken.amount;
161
166
  minRatio = Math.min(minRatio, ratio);
162
167
  }
163
168
  let mintValue = 0;
164
169
  let remainingValue = 0;
165
170
  let mintAmount = Math.floor(vault.supply_outstanding * minRatio);
166
- for (let i = 0; i < vault.composition.length; i++) {
167
- let contributionAmount = Math.floor(vault.composition[i].amount * minRatio);
168
- contributionAmount = Math.min(contributionAmount, auctionData.tokens[i].amount);
169
- mintData.tokens[i].contribution_amount = contributionAmount;
170
- mintData.tokens[i].remaining_amount = auctionData.tokens[i].amount - contributionAmount;
171
- mintValue += contributionAmount * auctionData.tokens[i].price;
172
- remainingValue += (auctionData.tokens[i].amount - contributionAmount) * auctionData.tokens[i].price;
171
+ for (const vaultToken of vault.composition) {
172
+ const mint = vaultToken.mint;
173
+ const auctionToken = auctionTokenByMint.get(mint);
174
+ const mintDataToken = mintDataTokenByMint.get(mint);
175
+ if (!auctionToken || !mintDataToken)
176
+ continue;
177
+ let contributionAmount = Math.floor(vaultToken.amount * minRatio);
178
+ contributionAmount = Math.min(contributionAmount, auctionToken.amount);
179
+ mintDataToken.contribution_amount = contributionAmount;
180
+ mintDataToken.remaining_amount = auctionToken.amount - contributionAmount;
181
+ mintValue += contributionAmount * auctionToken.price;
182
+ remainingValue += (auctionToken.amount - contributionAmount) * auctionToken.price;
173
183
  }
174
184
  mintData.mintValue = mintValue;
175
185
  mintData.mintAmount = mintAmount;
@@ -56,10 +56,17 @@ export declare function getMultipleAccountsInfoBatched(connection: Connection, p
56
56
  export declare function getAddressLookupTableAccounts(connection: Connection, keys: PublicKey[]): Promise<Map<string, AddressLookupTableAccount>>;
57
57
  export declare function getMultipleAddressLookupTableAccounts(connection: Connection, batches: PublicKey[][][]): Promise<AddressLookupTableAccount[][][]>;
58
58
  export declare function compileVersionedTransaction(blockhash: string, addressLookupTableAccounts: AddressLookupTableAccount[], payerPubkey: PublicKey, ixs: TransactionInstruction[]): VersionedTransaction;
59
- export declare function sendVersionedTransaction(connection: Connection, tx: VersionedTransaction, blockhash: string, lastValidBlockHeight: number, simulateTransactions: boolean): Promise<TransactionSignature>;
59
+ /**
60
+ * Send + confirm a batch of versioned transactions with parallel rebroadcasting.
61
+ * All txs within each batch are sent and confirmed concurrently.
62
+ * Batches are processed sequentially (batch 1 must all confirm before batch 2 starts).
63
+ */
64
+ export declare function sendVersionedTxs(connection: Connection, versionedTxs: VersionedTxs, simulateTransactions?: boolean, rebroadcastIntervalMs?: number, confirmTimeoutMs?: number): Promise<TransactionSignature[][]>;
65
+ /**
66
+ * Sign + send a TxPayloadBatchSequence using fast parallel rebroadcasting.
67
+ */
68
+ export declare function sendTxPayloadBatchSequence(connection: Connection, txPayloadBatchSequence: TxPayloadBatchSequence, simulateTransactions?: boolean): Promise<TransactionSignature[][]>;
60
69
  export declare function prepareVersionedTxs(connection: Connection, txBatchData: TxBatchData): Promise<VersionedTxs>;
61
- export declare function sendVersionedTxs(connection: Connection, versionedTxs: VersionedTxs, simulateTransactions?: boolean): Promise<TransactionSignature[][]>;
62
70
  export declare function signVersionedTxs(wallet: Wallet, versionedTxs: VersionedTxs): Promise<VersionedTxs>;
63
71
  export declare function signTxPayloadBatchSequence(wallet: Wallet, txPayloadBatchSequence: TxPayloadBatchSequence): Promise<TxPayloadBatchSequence>;
64
- export declare function sendTxPayloadBatchSequence(connection: Connection, txPayloadBatchSequence: TxPayloadBatchSequence, simulateTransactions?: boolean): Promise<TransactionSignature[][]>;
65
72
  export {};