@symmetry-hq/temp-v3-sdk 0.0.62 → 0.0.63
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.d.ts +1 -1
- package/dist/src/index.js +2 -1
- package/dist/src/keeperMonitor.d.ts +31 -1
- package/dist/src/keeperMonitor.js +320 -63
- package/dist/src/keeperRebalaneHandler.d.ts +32 -0
- package/dist/src/keeperRebalaneHandler.js +278 -0
- package/dist/test.js +2 -2
- package/package.json +1 -1
- package/src/index.ts +4 -1
- package/src/keeperMonitor.ts +319 -39
- package/test.ts +2 -3
package/dist/src/index.d.ts
CHANGED
|
@@ -796,4 +796,4 @@ export { FormattedRebalanceType, FormattedRebalanceAction, FormattedOraclePrice,
|
|
|
796
796
|
export { FormattedCreatorSettings, FormattedManagersSettings, FormattedFeeSettings, FormattedScheduleSettings, FormattedAutomationSettings, FormattedLpSettings, FormattedMetadataSettings, FormattedDepositsSettings, FormattedForceRebalanceSettings, FormattedCustomRebalanceSettings, FormattedAddTokenSettings, FormattedUpdateWeightsSettings, FormattedMakeDirectSwapSettings, FormattedAccumulatedFees, FormattedLookupTables, FormattedAsset, FormattedOracleSettings, FormattedOracleAggregator, FormattedOracle, FormattedOracleType, FormattedBasket, };
|
|
797
797
|
export { EditCreatorSettings, EditManagerSettings, EditFeeSettings, EditScheduleSettings, EditAutomationSettings, EditLpSettings, EditMetadataSettings, EditDepositsSettings, EditForceRebalanceSettings, EditCustomRebalanceSettings, EditAddTokenSettings, EditUpdateWeightsSettings, EditMakeDirectSwapSettings, AddOrEditTokenInput, OracleInput, UpdateWeightsInput, MakeDirectSwapInput, Settings, TaskContext, TaskType, };
|
|
798
798
|
export { getJupTokenLedgerAndSwapInstructions, };
|
|
799
|
-
export { KeeperMonitor } from './keeperMonitor';
|
|
799
|
+
export { KeeperMonitor, RebalanceHandler, } from './keeperMonitor';
|
package/dist/src/index.js
CHANGED
|
@@ -12,7 +12,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
12
12
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
13
13
|
};
|
|
14
14
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
-
exports.KeeperMonitor = exports.getJupTokenLedgerAndSwapInstructions = exports.TaskType = exports.SymmetryCore = void 0;
|
|
15
|
+
exports.RebalanceHandler = exports.KeeperMonitor = exports.getJupTokenLedgerAndSwapInstructions = exports.TaskType = exports.SymmetryCore = void 0;
|
|
16
16
|
const decimal_js_1 = __importDefault(require("decimal.js"));
|
|
17
17
|
const bn_js_1 = __importDefault(require("bn.js"));
|
|
18
18
|
const spl_token_1 = require("@solana/spl-token");
|
|
@@ -2087,3 +2087,4 @@ class SymmetryCore {
|
|
|
2087
2087
|
exports.SymmetryCore = SymmetryCore;
|
|
2088
2088
|
var keeperMonitor_1 = require("./keeperMonitor");
|
|
2089
2089
|
Object.defineProperty(exports, "KeeperMonitor", { enumerable: true, get: function () { return keeperMonitor_1.KeeperMonitor; } });
|
|
2090
|
+
Object.defineProperty(exports, "RebalanceHandler", { enumerable: true, get: function () { return keeperMonitor_1.RebalanceHandler; } });
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import { Connection } from "@solana/web3.js";
|
|
1
|
+
import { Connection, PublicKey } from "@solana/web3.js";
|
|
2
2
|
import { Wallet } from "./txUtils";
|
|
3
|
+
import { Basket, UIRebalanceIntent } from ".";
|
|
3
4
|
export declare class KeeperMonitor {
|
|
4
5
|
private params;
|
|
5
6
|
private intents;
|
|
@@ -20,3 +21,32 @@ export declare class KeeperMonitor {
|
|
|
20
21
|
monitorIntent(pubkey: string): Promise<void>;
|
|
21
22
|
monitorRebalanceIntent(pubkey: string): Promise<void>;
|
|
22
23
|
}
|
|
24
|
+
export declare class RebalanceHandler {
|
|
25
|
+
private params;
|
|
26
|
+
private intent;
|
|
27
|
+
private basket;
|
|
28
|
+
constructor(params: {
|
|
29
|
+
intent: UIRebalanceIntent;
|
|
30
|
+
basket: Basket;
|
|
31
|
+
wallet: Wallet;
|
|
32
|
+
connection: Connection;
|
|
33
|
+
network: "devnet" | "mainnet";
|
|
34
|
+
jupiterApiKey: string;
|
|
35
|
+
maxAllowedAccounts: number;
|
|
36
|
+
priorityFee?: number;
|
|
37
|
+
simulateTransactions?: boolean;
|
|
38
|
+
});
|
|
39
|
+
delay: (ms: number) => Promise<unknown>;
|
|
40
|
+
refresh(): Promise<void>;
|
|
41
|
+
static run(params: {
|
|
42
|
+
intentPubkey: PublicKey;
|
|
43
|
+
wallet: Wallet;
|
|
44
|
+
connection: Connection;
|
|
45
|
+
network: "devnet" | "mainnet";
|
|
46
|
+
jupiterApiKey: string;
|
|
47
|
+
maxAllowedAccounts: number;
|
|
48
|
+
priorityFee?: number;
|
|
49
|
+
simulateTransactions?: boolean;
|
|
50
|
+
}): Promise<void>;
|
|
51
|
+
private execute;
|
|
52
|
+
}
|
|
@@ -9,7 +9,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
9
9
|
});
|
|
10
10
|
};
|
|
11
11
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
-
exports.KeeperMonitor = void 0;
|
|
12
|
+
exports.RebalanceHandler = exports.KeeperMonitor = void 0;
|
|
13
13
|
const web3_js_1 = require("@solana/web3.js");
|
|
14
14
|
const _1 = require(".");
|
|
15
15
|
const rebalanceIntent_1 = require("./states/intents/rebalanceIntent");
|
|
@@ -156,7 +156,7 @@ class KeeperMonitor {
|
|
|
156
156
|
intent: intent.ownAddress.toBase58(),
|
|
157
157
|
});
|
|
158
158
|
let res = yield this.params.symmetryCore.signAndSendTxPayloadBatchSequence({ txPayloadBatchSequence: tx, wallet: this.params.wallet, simulateTransactions: this.params.simulateTransactions });
|
|
159
|
-
console.log("Execute Basket Intent -
|
|
159
|
+
console.log("Execute Basket Intent -", pubkey, " : ", res);
|
|
160
160
|
nextCheckTime = now + 60;
|
|
161
161
|
}
|
|
162
162
|
catch (_a) { }
|
|
@@ -172,12 +172,12 @@ class KeeperMonitor {
|
|
|
172
172
|
intent: intent.ownAddress.toBase58(),
|
|
173
173
|
});
|
|
174
174
|
let res = yield this.params.symmetryCore.signAndSendTxPayloadBatchSequence({ txPayloadBatchSequence: tx, wallet: this.params.wallet, simulateTransactions: this.params.simulateTransactions });
|
|
175
|
-
console.log("Cancel Basket Intent -
|
|
175
|
+
console.log("Cancel Basket Intent -", pubkey, " : ", res);
|
|
176
176
|
nextCheckTime = now + 60;
|
|
177
177
|
}
|
|
178
178
|
catch (e) {
|
|
179
179
|
if (numTries == 4) {
|
|
180
|
-
console.log("Stop monitoring -
|
|
180
|
+
console.log("Stop monitoring -", pubkey, " : ", e);
|
|
181
181
|
}
|
|
182
182
|
}
|
|
183
183
|
continue;
|
|
@@ -186,12 +186,14 @@ class KeeperMonitor {
|
|
|
186
186
|
}
|
|
187
187
|
monitorRebalanceIntent(pubkey) {
|
|
188
188
|
return __awaiter(this, void 0, void 0, function* () {
|
|
189
|
-
var _a, _b;
|
|
189
|
+
var _a, _b, _c, _d, _e;
|
|
190
190
|
let nextCheckTime = 0;
|
|
191
191
|
let numTriesUpdatePrices = 0;
|
|
192
192
|
let numTriesMint = 0;
|
|
193
193
|
let numTriesRedeemTokens = 0;
|
|
194
194
|
let numTriesClaimBounty = 0;
|
|
195
|
+
let lastJupQuotesUpdate = 0;
|
|
196
|
+
let jupQuotes = [];
|
|
195
197
|
while (true) {
|
|
196
198
|
let uiIntent = this.rebalanceIntents.get(pubkey);
|
|
197
199
|
if (!uiIntent)
|
|
@@ -213,7 +215,7 @@ class KeeperMonitor {
|
|
|
213
215
|
continue;
|
|
214
216
|
}
|
|
215
217
|
if (intent.current_action == "update_prices") {
|
|
216
|
-
if (numTriesUpdatePrices >=
|
|
218
|
+
if (numTriesUpdatePrices >= 5)
|
|
217
219
|
break;
|
|
218
220
|
numTriesUpdatePrices += 1;
|
|
219
221
|
try {
|
|
@@ -226,86 +228,90 @@ class KeeperMonitor {
|
|
|
226
228
|
console.log("Update Prices - ", pubkey, " : ", res);
|
|
227
229
|
}
|
|
228
230
|
catch (e) {
|
|
229
|
-
if (numTriesUpdatePrices ==
|
|
231
|
+
if (numTriesUpdatePrices == 4) {
|
|
230
232
|
console.log("Stop monitoring - ", pubkey, " : ", e);
|
|
231
233
|
}
|
|
232
234
|
}
|
|
235
|
+
nextCheckTime += 60;
|
|
233
236
|
continue;
|
|
234
237
|
}
|
|
235
238
|
if (intent.auctions[2].end_time > now) {
|
|
236
239
|
let basket = this.baskets.get(intent.basket);
|
|
237
240
|
if (!basket)
|
|
238
241
|
continue;
|
|
239
|
-
let auction0StartTime = intent.auctions[0].start_time;
|
|
240
|
-
let auction0EndTime = intent.auctions[0].end_time;
|
|
241
|
-
let auction0MidTime = auction0StartTime + (auction0EndTime - auction0StartTime) / 2;
|
|
242
|
-
let auction1StartTime = intent.auctions[1].start_time;
|
|
243
|
-
let auction1EndTime = intent.auctions[1].end_time;
|
|
244
|
-
let auction1MidTime = auction1StartTime + (auction1EndTime - auction1StartTime) / 2;
|
|
245
|
-
let auction2StartTime = intent.auctions[2].start_time;
|
|
246
|
-
let auction2EndTime = intent.auctions[2].end_time;
|
|
247
|
-
let auction2MidTime = auction2StartTime + (auction2EndTime - auction2StartTime) / 2;
|
|
248
|
-
if (now < auction0MidTime + 30) {
|
|
249
|
-
nextCheckTime = auction0MidTime + 30;
|
|
250
|
-
continue;
|
|
251
|
-
}
|
|
252
|
-
if (now >= auction0EndTime) {
|
|
253
|
-
if (now < auction1MidTime + 10) {
|
|
254
|
-
nextCheckTime = auction1MidTime + 10;
|
|
255
|
-
continue;
|
|
256
|
-
}
|
|
257
|
-
if (now >= auction1EndTime)
|
|
258
|
-
if (now < auction2MidTime + 5) {
|
|
259
|
-
nextCheckTime = auction2MidTime + 5;
|
|
260
|
-
continue;
|
|
261
|
-
}
|
|
262
|
-
}
|
|
263
242
|
let pairs = (0, rebalanceIntent_1.getSwapPairs)(chainData, basket);
|
|
264
|
-
|
|
265
|
-
|
|
243
|
+
if (Date.now() / 1000 > lastJupQuotesUpdate + 60) {
|
|
244
|
+
lastJupQuotesUpdate = Date.now() / 1000;
|
|
245
|
+
jupQuotes = [];
|
|
246
|
+
for (let pair of pairs) {
|
|
266
247
|
if (pair.value < 0.005)
|
|
267
248
|
continue;
|
|
268
|
-
|
|
269
|
-
let { tokenLedgerInstruction, swapInstruction, addressLookupTableAddresses, quoteResponse } = this.params.network == "mainnet" ?
|
|
270
|
-
yield (0, _1.getJupTokenLedgerAndSwapInstructions)({
|
|
271
|
-
keeper: this.params.wallet.publicKey,
|
|
272
|
-
basketMintIn: new web3_js_1.PublicKey(pair.inMint),
|
|
273
|
-
basketMintOut: new web3_js_1.PublicKey(pair.outMint),
|
|
274
|
-
basketAmountIn: pair.inAmount,
|
|
275
|
-
basketAmountOut: pair.outAmount,
|
|
276
|
-
swapMode: "ioc",
|
|
277
|
-
apiKey: this.params.jupiterApiKey,
|
|
278
|
-
maxJupAccounts: this.params.maxAllowedAccounts,
|
|
279
|
-
}) : { tokenLedgerInstruction: undefined, swapInstruction: undefined, addressLookupTableAddresses: [], quoteResponse: undefined };
|
|
280
|
-
console.log(pair, "Jup Quote:", parseFloat((_a = quoteResponse === null || quoteResponse === void 0 ? void 0 : quoteResponse.outAmount) !== null && _a !== void 0 ? _a : 0), "Requested In:", pair.inAmount);
|
|
281
|
-
if (this.params.network == "devnet" || parseFloat((_b = quoteResponse === null || quoteResponse === void 0 ? void 0 : quoteResponse.outAmount) !== null && _b !== void 0 ? _b : 0) > pair.inAmount) {
|
|
249
|
+
if (this.params.network == "mainnet")
|
|
282
250
|
try {
|
|
283
|
-
let
|
|
284
|
-
keeper: this.params.wallet.publicKey
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
jup_token_ledger_ix: tokenLedgerInstruction,
|
|
293
|
-
jup_swap_ix: swapInstruction,
|
|
294
|
-
jup_address_lookup_table_addresses: addressLookupTableAddresses,
|
|
251
|
+
let res = yield (0, _1.getJupTokenLedgerAndSwapInstructions)({
|
|
252
|
+
keeper: this.params.wallet.publicKey,
|
|
253
|
+
basketMintIn: new web3_js_1.PublicKey(pair.inMint),
|
|
254
|
+
basketMintOut: new web3_js_1.PublicKey(pair.outMint),
|
|
255
|
+
basketAmountIn: pair.inAmount,
|
|
256
|
+
basketAmountOut: pair.outAmount,
|
|
257
|
+
swapMode: "ioc",
|
|
258
|
+
apiKey: this.params.jupiterApiKey,
|
|
259
|
+
maxJupAccounts: this.params.maxAllowedAccounts,
|
|
295
260
|
});
|
|
296
|
-
|
|
297
|
-
console.log("
|
|
261
|
+
jupQuotes.push(Object.assign(Object.assign({}, res), { inMint: pair.inMint, outMint: pair.outMint }));
|
|
262
|
+
console.log("Fetch new Jup Quote:", pair.inMint, pair.outMint);
|
|
263
|
+
console.log(pair, "Jup Quote:", parseFloat((_b = (_a = res.quoteResponse) === null || _a === void 0 ? void 0 : _a.outAmount) !== null && _b !== void 0 ? _b : 0), "Requested In:", pair.inAmount);
|
|
298
264
|
}
|
|
299
|
-
catch (
|
|
265
|
+
catch (_f) { }
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
for (let index = 0; index < pairs.length; index++)
|
|
269
|
+
try {
|
|
270
|
+
let pair = pairs[index];
|
|
271
|
+
let jupIndex = jupQuotes.findIndex(q => q && q.inMint == pair.inMint && q.outMint == pair.outMint);
|
|
272
|
+
let quote = jupIndex >= 0 ? jupQuotes[jupIndex] : undefined;
|
|
273
|
+
if (!quote && this.params.network == "mainnet")
|
|
274
|
+
continue;
|
|
275
|
+
if (pair.value < 0.005)
|
|
276
|
+
continue;
|
|
277
|
+
let tokenLedgerInstruction = quote === null || quote === void 0 ? void 0 : quote.tokenLedgerInstruction;
|
|
278
|
+
let swapInstruction = quote === null || quote === void 0 ? void 0 : quote.swapInstruction;
|
|
279
|
+
let addressLookupTableAddresses = (_c = quote === null || quote === void 0 ? void 0 : quote.addressLookupTableAddresses) !== null && _c !== void 0 ? _c : [];
|
|
280
|
+
let quoteResponse = quote === null || quote === void 0 ? void 0 : quote.quoteResponse;
|
|
281
|
+
if (this.params.network == "mainnet" && !quoteResponse)
|
|
282
|
+
continue;
|
|
283
|
+
console.log(pair, "Jup Quote:", parseFloat((_d = quoteResponse === null || quoteResponse === void 0 ? void 0 : quoteResponse.outAmount) !== null && _d !== void 0 ? _d : 0), "Requested In:", pair.inAmount);
|
|
284
|
+
let quoteResponseAmount = parseFloat((_e = quoteResponse === null || quoteResponse === void 0 ? void 0 : quoteResponse.outAmount) !== null && _e !== void 0 ? _e : 0);
|
|
285
|
+
if (this.params.network == "mainnet" && quoteResponseAmount * 1.005 <= pair.inAmount)
|
|
286
|
+
continue;
|
|
287
|
+
try {
|
|
288
|
+
let tx = yield this.params.symmetryCore.flashSwapTx({
|
|
289
|
+
keeper: this.params.wallet.publicKey.toBase58(),
|
|
290
|
+
basket: basket.ownAddress.toBase58(),
|
|
291
|
+
rebalance_intent: intent.pubkey,
|
|
292
|
+
mint_in: pair.inMint,
|
|
293
|
+
mint_out: pair.outMint,
|
|
294
|
+
amount_in: pair.inAmount,
|
|
295
|
+
amount_out: pair.outAmount,
|
|
296
|
+
mode: 2,
|
|
297
|
+
jup_token_ledger_ix: tokenLedgerInstruction,
|
|
298
|
+
jup_swap_ix: swapInstruction,
|
|
299
|
+
jup_address_lookup_table_addresses: addressLookupTableAddresses,
|
|
300
|
+
});
|
|
301
|
+
let res = yield this.params.symmetryCore.signAndSendTxPayloadBatchSequence({ txPayloadBatchSequence: tx, wallet: this.params.wallet, simulateTransactions: this.params.simulateTransactions });
|
|
302
|
+
console.log("Flash Swap - ", pubkey, " : ", res);
|
|
303
|
+
jupQuotes = jupQuotes.filter(q => q && (q.inMint != pair.inMint || q.outMint != pair.outMint));
|
|
300
304
|
}
|
|
305
|
+
catch (_g) { }
|
|
301
306
|
}
|
|
302
|
-
catch (
|
|
307
|
+
catch (_h) { }
|
|
303
308
|
nextCheckTime = (Date.now() / 1000) + 8;
|
|
304
309
|
continue;
|
|
305
310
|
}
|
|
306
311
|
if (intent.rebalance_type == "deposit") {
|
|
307
312
|
if (numTriesMint >= 3)
|
|
308
313
|
break;
|
|
314
|
+
lastJupQuotesUpdate = 0;
|
|
309
315
|
numTriesMint += 1;
|
|
310
316
|
try {
|
|
311
317
|
let tx = yield this.params.symmetryCore.mintTx({
|
|
@@ -365,3 +371,254 @@ class KeeperMonitor {
|
|
|
365
371
|
}
|
|
366
372
|
}
|
|
367
373
|
exports.KeeperMonitor = KeeperMonitor;
|
|
374
|
+
class RebalanceHandler {
|
|
375
|
+
constructor(params) {
|
|
376
|
+
var _a, _b;
|
|
377
|
+
this.delay = (ms) => __awaiter(this, void 0, void 0, function* () { return new Promise(resolve => setTimeout(resolve, ms)); });
|
|
378
|
+
this.params = {
|
|
379
|
+
wallet: params.wallet,
|
|
380
|
+
connection: params.connection,
|
|
381
|
+
symmetryCore: new _1.SymmetryCore({
|
|
382
|
+
connection: params.connection,
|
|
383
|
+
network: params.network,
|
|
384
|
+
priorityFee: (_a = params.priorityFee) !== null && _a !== void 0 ? _a : constants_1.PRIORITY_FEE,
|
|
385
|
+
}),
|
|
386
|
+
network: params.network,
|
|
387
|
+
jupiterApiKey: params.jupiterApiKey,
|
|
388
|
+
maxAllowedAccounts: params.maxAllowedAccounts,
|
|
389
|
+
simulateTransactions: (_b = params.simulateTransactions) !== null && _b !== void 0 ? _b : false,
|
|
390
|
+
};
|
|
391
|
+
this.intent = params.intent;
|
|
392
|
+
this.basket = params.basket;
|
|
393
|
+
}
|
|
394
|
+
refresh() {
|
|
395
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
396
|
+
this.intent = yield this.params.symmetryCore.fetchRebalanceIntent(this.intent.formatted_data.pubkey);
|
|
397
|
+
this.basket = yield this.params.symmetryCore.fetchBasket(this.intent.formatted_data.basket);
|
|
398
|
+
});
|
|
399
|
+
}
|
|
400
|
+
static run(params) {
|
|
401
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
402
|
+
var _a;
|
|
403
|
+
let symmetryCore = new _1.SymmetryCore({
|
|
404
|
+
connection: params.connection,
|
|
405
|
+
network: params.network,
|
|
406
|
+
priorityFee: (_a = params.priorityFee) !== null && _a !== void 0 ? _a : constants_1.PRIORITY_FEE,
|
|
407
|
+
});
|
|
408
|
+
let intent = yield symmetryCore.fetchRebalanceIntent(params.intentPubkey.toBase58());
|
|
409
|
+
let basket = yield symmetryCore.fetchBasket(intent.formatted_data.basket);
|
|
410
|
+
let handler = new RebalanceHandler({
|
|
411
|
+
intent, basket,
|
|
412
|
+
wallet: params.wallet,
|
|
413
|
+
connection: params.connection,
|
|
414
|
+
network: params.network,
|
|
415
|
+
jupiterApiKey: params.jupiterApiKey,
|
|
416
|
+
maxAllowedAccounts: params.maxAllowedAccounts,
|
|
417
|
+
simulateTransactions: params.simulateTransactions,
|
|
418
|
+
});
|
|
419
|
+
handler.execute();
|
|
420
|
+
for (let i = 0; i < 20; i++) {
|
|
421
|
+
yield handler.delay(15 * 1000);
|
|
422
|
+
try {
|
|
423
|
+
yield handler.refresh();
|
|
424
|
+
}
|
|
425
|
+
catch (e) {
|
|
426
|
+
handler.intent = undefined;
|
|
427
|
+
break;
|
|
428
|
+
}
|
|
429
|
+
}
|
|
430
|
+
});
|
|
431
|
+
}
|
|
432
|
+
execute() {
|
|
433
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
434
|
+
var _a, _b;
|
|
435
|
+
console.log("Starting rebalance handler for intent:", this.intent.formatted_data.pubkey);
|
|
436
|
+
let nextCheckTime = 0;
|
|
437
|
+
let numTriesUpdatePrices = 0;
|
|
438
|
+
let numTriesMint = 0;
|
|
439
|
+
let numTriesRedeemTokens = 0;
|
|
440
|
+
let numTriesClaimBounty = 0;
|
|
441
|
+
let rebalancePairs = [];
|
|
442
|
+
let lastJupQuotesUpdate = 0;
|
|
443
|
+
let jupQuotes = [];
|
|
444
|
+
while (true) {
|
|
445
|
+
if (!this.intent)
|
|
446
|
+
break;
|
|
447
|
+
let intent = this.intent.formatted_data;
|
|
448
|
+
let chainData = this.intent.chain_data;
|
|
449
|
+
let now = Date.now() / 1000;
|
|
450
|
+
if (now < nextCheckTime) {
|
|
451
|
+
yield this.delay(Math.min(30 * 1000, Math.max(0, nextCheckTime - now + 0.2) * 1000));
|
|
452
|
+
continue;
|
|
453
|
+
}
|
|
454
|
+
nextCheckTime = now + 5;
|
|
455
|
+
if (intent.current_action == "not_active") {
|
|
456
|
+
console.log("Intent not active, stopping");
|
|
457
|
+
break;
|
|
458
|
+
}
|
|
459
|
+
if (intent.current_action == "deposit_tokens") {
|
|
460
|
+
console.log("Waiting for deposit...");
|
|
461
|
+
continue;
|
|
462
|
+
}
|
|
463
|
+
if (intent.current_action == "update_prices" && intent.last_action_timestamp > now) {
|
|
464
|
+
nextCheckTime = intent.last_action_timestamp;
|
|
465
|
+
continue;
|
|
466
|
+
}
|
|
467
|
+
if (intent.current_action == "update_prices") {
|
|
468
|
+
if (numTriesUpdatePrices >= 3) {
|
|
469
|
+
console.log("Max retries for update_prices");
|
|
470
|
+
break;
|
|
471
|
+
}
|
|
472
|
+
numTriesUpdatePrices += 1;
|
|
473
|
+
try {
|
|
474
|
+
let tx = yield this.params.symmetryCore.updateTokenPricesTx({
|
|
475
|
+
keeper: this.params.wallet.publicKey.toBase58(),
|
|
476
|
+
basket: intent.basket,
|
|
477
|
+
rebalance_intent: intent.pubkey,
|
|
478
|
+
});
|
|
479
|
+
let res = yield this.params.symmetryCore.signAndSendTxPayloadBatchSequence({ txPayloadBatchSequence: tx, wallet: this.params.wallet, simulateTransactions: this.params.simulateTransactions });
|
|
480
|
+
console.log("Update Prices:", res);
|
|
481
|
+
}
|
|
482
|
+
catch (e) {
|
|
483
|
+
if (numTriesUpdatePrices == 3) {
|
|
484
|
+
console.log("Stop - update prices failed:", e);
|
|
485
|
+
}
|
|
486
|
+
}
|
|
487
|
+
continue;
|
|
488
|
+
}
|
|
489
|
+
if (intent.auctions[2].end_time > now) {
|
|
490
|
+
rebalancePairs = (0, rebalanceIntent_1.getSwapPairs)(chainData, this.basket);
|
|
491
|
+
if (Date.now() / 1000 > lastJupQuotesUpdate + 60) {
|
|
492
|
+
let usedValue = new Map();
|
|
493
|
+
jupQuotes = [];
|
|
494
|
+
for (let pair of rebalancePairs) {
|
|
495
|
+
let inValue = (_a = usedValue.get(pair.inMint)) !== null && _a !== void 0 ? _a : 0;
|
|
496
|
+
let outValue = (_b = usedValue.get(pair.outMint)) !== null && _b !== void 0 ? _b : 0;
|
|
497
|
+
let swapValue = Math.min(pair.value - inValue, pair.value - outValue);
|
|
498
|
+
if (swapValue < 0.005) {
|
|
499
|
+
jupQuotes.push(undefined);
|
|
500
|
+
continue;
|
|
501
|
+
}
|
|
502
|
+
usedValue.set(pair.inMint, inValue + swapValue);
|
|
503
|
+
usedValue.set(pair.outMint, outValue + swapValue);
|
|
504
|
+
let res = undefined;
|
|
505
|
+
if (this.params.network == "mainnet")
|
|
506
|
+
try {
|
|
507
|
+
res = Object.assign(Object.assign({}, (yield (0, _1.getJupTokenLedgerAndSwapInstructions)({
|
|
508
|
+
keeper: this.params.wallet.publicKey,
|
|
509
|
+
basketMintIn: new web3_js_1.PublicKey(pair.inMint),
|
|
510
|
+
basketMintOut: new web3_js_1.PublicKey(pair.outMint),
|
|
511
|
+
basketAmountIn: pair.inAmount,
|
|
512
|
+
basketAmountOut: pair.outAmount,
|
|
513
|
+
swapMode: "ioc",
|
|
514
|
+
apiKey: this.params.jupiterApiKey,
|
|
515
|
+
maxJupAccounts: this.params.maxAllowedAccounts,
|
|
516
|
+
}))), { inMint: pair.inMint, outMint: pair.outMint });
|
|
517
|
+
}
|
|
518
|
+
catch (_c) { }
|
|
519
|
+
;
|
|
520
|
+
jupQuotes.push(res);
|
|
521
|
+
}
|
|
522
|
+
}
|
|
523
|
+
for (let index = 0; index < rebalancePairs.length; index++)
|
|
524
|
+
try {
|
|
525
|
+
let pair = rebalancePairs[index];
|
|
526
|
+
let quote = jupQuotes.find(q => q && q.inMint == pair.inMint && q.outMint == pair.outMint);
|
|
527
|
+
if (!quote)
|
|
528
|
+
continue;
|
|
529
|
+
if (pair.value < 0.005)
|
|
530
|
+
continue;
|
|
531
|
+
let { tokenLedgerInstruction, swapInstruction, addressLookupTableAddresses, quoteResponse } = quote;
|
|
532
|
+
if (!quoteResponse)
|
|
533
|
+
continue;
|
|
534
|
+
console.log(pair, "Jup Quote:", parseFloat(quoteResponse.outAmount), "Requested In:", pair.inAmount);
|
|
535
|
+
if (parseFloat(quoteResponse.outAmount) <= pair.inAmount && this.params.network == "mainnet")
|
|
536
|
+
continue;
|
|
537
|
+
try {
|
|
538
|
+
let tx = yield this.params.symmetryCore.flashSwapTx({
|
|
539
|
+
keeper: this.params.wallet.publicKey.toBase58(),
|
|
540
|
+
basket: this.basket.ownAddress.toBase58(),
|
|
541
|
+
rebalance_intent: intent.pubkey,
|
|
542
|
+
mint_in: pair.inMint,
|
|
543
|
+
mint_out: pair.outMint,
|
|
544
|
+
amount_in: pair.inAmount,
|
|
545
|
+
amount_out: pair.outAmount,
|
|
546
|
+
mode: 2,
|
|
547
|
+
jup_token_ledger_ix: tokenLedgerInstruction,
|
|
548
|
+
jup_swap_ix: swapInstruction,
|
|
549
|
+
jup_address_lookup_table_addresses: addressLookupTableAddresses,
|
|
550
|
+
});
|
|
551
|
+
let res = yield this.params.symmetryCore.signAndSendTxPayloadBatchSequence({ txPayloadBatchSequence: tx, wallet: this.params.wallet, simulateTransactions: this.params.simulateTransactions });
|
|
552
|
+
console.log("Flash Swap:", res);
|
|
553
|
+
rebalancePairs = rebalancePairs.splice(index, 1);
|
|
554
|
+
index -= 1;
|
|
555
|
+
}
|
|
556
|
+
catch (_d) { }
|
|
557
|
+
}
|
|
558
|
+
catch (_e) { }
|
|
559
|
+
nextCheckTime = (Date.now() / 1000) + 10;
|
|
560
|
+
continue;
|
|
561
|
+
}
|
|
562
|
+
if (intent.rebalance_type == "deposit") {
|
|
563
|
+
if (numTriesMint >= 3)
|
|
564
|
+
break;
|
|
565
|
+
lastJupQuotesUpdate = 0;
|
|
566
|
+
numTriesMint += 1;
|
|
567
|
+
try {
|
|
568
|
+
let tx = yield this.params.symmetryCore.mintTx({
|
|
569
|
+
keeper: this.params.wallet.publicKey.toBase58(),
|
|
570
|
+
rebalance_intent: intent.pubkey,
|
|
571
|
+
});
|
|
572
|
+
let res = yield this.params.symmetryCore.signAndSendTxPayloadBatchSequence({ txPayloadBatchSequence: tx, wallet: this.params.wallet, simulateTransactions: this.params.simulateTransactions });
|
|
573
|
+
console.log("Mint -", res);
|
|
574
|
+
}
|
|
575
|
+
catch (e) {
|
|
576
|
+
if (numTriesMint == 3) {
|
|
577
|
+
console.log("Stop monitoring -", e);
|
|
578
|
+
}
|
|
579
|
+
}
|
|
580
|
+
continue;
|
|
581
|
+
}
|
|
582
|
+
let hasTokens = intent.tokens.find(token => token.amount > 0);
|
|
583
|
+
if (hasTokens && intent.rebalance_type == "withdraw") {
|
|
584
|
+
if (numTriesRedeemTokens >= 3)
|
|
585
|
+
break;
|
|
586
|
+
numTriesRedeemTokens += 1;
|
|
587
|
+
try {
|
|
588
|
+
let tx = yield this.params.symmetryCore.redeemTokensTx({
|
|
589
|
+
keeper: this.params.wallet.publicKey.toBase58(),
|
|
590
|
+
rebalance_intent: intent.pubkey,
|
|
591
|
+
});
|
|
592
|
+
let res = yield this.params.symmetryCore.signAndSendTxPayloadBatchSequence({ txPayloadBatchSequence: tx, wallet: this.params.wallet, simulateTransactions: this.params.simulateTransactions });
|
|
593
|
+
console.log("Redeem Tokens -", res);
|
|
594
|
+
}
|
|
595
|
+
catch (e) {
|
|
596
|
+
if (numTriesRedeemTokens == 3) {
|
|
597
|
+
console.log("Stop monitoring -", e);
|
|
598
|
+
}
|
|
599
|
+
}
|
|
600
|
+
continue;
|
|
601
|
+
}
|
|
602
|
+
if (numTriesClaimBounty >= 3)
|
|
603
|
+
break;
|
|
604
|
+
numTriesClaimBounty += 1;
|
|
605
|
+
try {
|
|
606
|
+
let tx = yield this.params.symmetryCore.claimBountyTx({
|
|
607
|
+
keeper: this.params.wallet.publicKey.toBase58(),
|
|
608
|
+
rebalance_intent: intent.pubkey,
|
|
609
|
+
});
|
|
610
|
+
let res = yield this.params.symmetryCore.signAndSendTxPayloadBatchSequence({ txPayloadBatchSequence: tx, wallet: this.params.wallet, simulateTransactions: this.params.simulateTransactions });
|
|
611
|
+
console.log("Claim Bounty -", res);
|
|
612
|
+
nextCheckTime = now + 60;
|
|
613
|
+
}
|
|
614
|
+
catch (e) {
|
|
615
|
+
if (numTriesClaimBounty == 3) {
|
|
616
|
+
console.log("Stop monitoring -", e);
|
|
617
|
+
}
|
|
618
|
+
}
|
|
619
|
+
continue;
|
|
620
|
+
}
|
|
621
|
+
});
|
|
622
|
+
}
|
|
623
|
+
}
|
|
624
|
+
exports.RebalanceHandler = RebalanceHandler;
|
|
@@ -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;
|
package/dist/test.js
CHANGED
|
@@ -28,7 +28,7 @@ function testStates() {
|
|
|
28
28
|
let sdk = new src_1.SymmetryCore({
|
|
29
29
|
connection: connection,
|
|
30
30
|
network: "mainnet",
|
|
31
|
-
priorityFee:
|
|
31
|
+
priorityFee: 5237,
|
|
32
32
|
});
|
|
33
33
|
let keeperMonitor = new src_1.KeeperMonitor({
|
|
34
34
|
wallet: wallet,
|
|
@@ -37,7 +37,7 @@ function testStates() {
|
|
|
37
37
|
jupiterApiKey: jupApiKey,
|
|
38
38
|
maxAllowedAccounts: 40,
|
|
39
39
|
simulateTransactions: false,
|
|
40
|
-
priorityFee:
|
|
40
|
+
priorityFee: 5237,
|
|
41
41
|
});
|
|
42
42
|
// keeperMonitor.run();
|
|
43
43
|
// return;
|
package/package.json
CHANGED
package/src/index.ts
CHANGED
package/src/keeperMonitor.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Connection, PublicKey } from "@solana/web3.js";
|
|
1
|
+
import { Connection, PublicKey, TransactionInstruction } from "@solana/web3.js";
|
|
2
2
|
import { Wallet } from "./txUtils";
|
|
3
3
|
import { Basket, FormattedRebalanceIntent, getJupTokenLedgerAndSwapInstructions, Intent, SymmetryCore, UIRebalanceIntent } from ".";
|
|
4
4
|
import { getSwapPairs } from "./states/intents/rebalanceIntent";
|
|
@@ -150,7 +150,7 @@ export class KeeperMonitor {
|
|
|
150
150
|
intent: intent.ownAddress!.toBase58(),
|
|
151
151
|
});
|
|
152
152
|
let res = await this.params.symmetryCore.signAndSendTxPayloadBatchSequence({txPayloadBatchSequence: tx, wallet: this.params.wallet, simulateTransactions: this.params.simulateTransactions});
|
|
153
|
-
console.log("Execute Basket Intent -
|
|
153
|
+
console.log("Execute Basket Intent -", pubkey, " : ", res);
|
|
154
154
|
nextCheckTime = now + 60;
|
|
155
155
|
} catch {}
|
|
156
156
|
continue;
|
|
@@ -163,9 +163,9 @@ export class KeeperMonitor {
|
|
|
163
163
|
intent: intent.ownAddress!.toBase58(),
|
|
164
164
|
});
|
|
165
165
|
let res = await this.params.symmetryCore.signAndSendTxPayloadBatchSequence({txPayloadBatchSequence: tx, wallet: this.params.wallet, simulateTransactions: this.params.simulateTransactions});
|
|
166
|
-
console.log("Cancel Basket Intent -
|
|
166
|
+
console.log("Cancel Basket Intent -", pubkey, " : ", res);
|
|
167
167
|
nextCheckTime = now + 60;
|
|
168
|
-
} catch (e) { if (numTries == 4) { console.log("Stop monitoring -
|
|
168
|
+
} catch (e) { if (numTries == 4) { console.log("Stop monitoring -", pubkey, " : ", e); } }
|
|
169
169
|
continue;
|
|
170
170
|
}
|
|
171
171
|
}
|
|
@@ -176,6 +176,16 @@ export class KeeperMonitor {
|
|
|
176
176
|
let numTriesMint = 0;
|
|
177
177
|
let numTriesRedeemTokens = 0;
|
|
178
178
|
let numTriesClaimBounty = 0;
|
|
179
|
+
let lastJupQuotesUpdate = 0;
|
|
180
|
+
let jupQuotes: ({
|
|
181
|
+
inMint: string,
|
|
182
|
+
outMint: string,
|
|
183
|
+
tokenLedgerInstruction: TransactionInstruction,
|
|
184
|
+
swapInstruction: TransactionInstruction,
|
|
185
|
+
addressLookupTableAddresses: PublicKey[],
|
|
186
|
+
quoteResponse: any,
|
|
187
|
+
} | undefined)[] = [];
|
|
188
|
+
|
|
179
189
|
while (true) {
|
|
180
190
|
let uiIntent = this.rebalanceIntents.get(pubkey);
|
|
181
191
|
if (!uiIntent) break;
|
|
@@ -192,7 +202,7 @@ export class KeeperMonitor {
|
|
|
192
202
|
if (intent.current_action == "update_prices" && intent.last_action_timestamp > now)
|
|
193
203
|
{ nextCheckTime = intent.last_action_timestamp; continue; }
|
|
194
204
|
if (intent.current_action == "update_prices") {
|
|
195
|
-
if (numTriesUpdatePrices >=
|
|
205
|
+
if (numTriesUpdatePrices >= 5) break;
|
|
196
206
|
numTriesUpdatePrices += 1; try {
|
|
197
207
|
let tx = await this.params.symmetryCore.updateTokenPricesTx({
|
|
198
208
|
keeper: this.params.wallet.publicKey.toBase58(),
|
|
@@ -201,47 +211,62 @@ export class KeeperMonitor {
|
|
|
201
211
|
});
|
|
202
212
|
let res = await this.params.symmetryCore.signAndSendTxPayloadBatchSequence({txPayloadBatchSequence: tx, wallet: this.params.wallet, simulateTransactions: this.params.simulateTransactions});
|
|
203
213
|
console.log("Update Prices - ", pubkey, " : ", res);
|
|
204
|
-
} catch (e) { if (numTriesUpdatePrices ==
|
|
214
|
+
} catch (e) { if (numTriesUpdatePrices == 4) { console.log("Stop monitoring - ", pubkey, " : ", e); } }
|
|
215
|
+
nextCheckTime += 60;
|
|
205
216
|
continue;
|
|
206
217
|
}
|
|
207
218
|
if (intent.auctions[2].end_time > now) {
|
|
208
219
|
let basket = this.baskets.get(intent.basket);
|
|
209
220
|
if (!basket) continue;
|
|
210
|
-
|
|
211
|
-
let auction0EndTime = intent.auctions[0].end_time;
|
|
212
|
-
let auction0MidTime = auction0StartTime + (auction0EndTime - auction0StartTime) / 2;
|
|
213
|
-
|
|
214
|
-
let auction1StartTime = intent.auctions[1].start_time;
|
|
215
|
-
let auction1EndTime = intent.auctions[1].end_time;
|
|
216
|
-
let auction1MidTime = auction1StartTime + (auction1EndTime - auction1StartTime) / 2;
|
|
217
|
-
|
|
218
|
-
let auction2StartTime = intent.auctions[2].start_time;
|
|
219
|
-
let auction2EndTime = intent.auctions[2].end_time;
|
|
220
|
-
let auction2MidTime = auction2StartTime + (auction2EndTime - auction2StartTime) / 2;
|
|
221
|
-
|
|
222
|
-
if (now < auction0MidTime + 30) { nextCheckTime = auction0MidTime + 30; continue; }
|
|
223
|
-
if (now >= auction0EndTime) {
|
|
224
|
-
if (now < auction1MidTime + 10) { nextCheckTime = auction1MidTime + 10; continue; }
|
|
225
|
-
if (now >= auction1EndTime)
|
|
226
|
-
if (now < auction2MidTime + 5) { nextCheckTime = auction2MidTime + 5; continue; }
|
|
227
|
-
}
|
|
221
|
+
|
|
228
222
|
let pairs = getSwapPairs(chainData, basket!);
|
|
229
|
-
|
|
223
|
+
|
|
224
|
+
if (Date.now() / 1000 > lastJupQuotesUpdate + 60) {
|
|
225
|
+
lastJupQuotesUpdate = Date.now() / 1000;
|
|
226
|
+
jupQuotes = [];
|
|
227
|
+
for (let pair of pairs) {
|
|
228
|
+
if (pair.value < 0.005) continue;
|
|
229
|
+
if (this.params.network == "mainnet") try {
|
|
230
|
+
let res = await getJupTokenLedgerAndSwapInstructions({
|
|
231
|
+
keeper: this.params.wallet.publicKey,
|
|
232
|
+
basketMintIn: new PublicKey(pair.inMint),
|
|
233
|
+
basketMintOut: new PublicKey(pair.outMint),
|
|
234
|
+
basketAmountIn: pair.inAmount,
|
|
235
|
+
basketAmountOut: pair.outAmount,
|
|
236
|
+
swapMode: "ioc",
|
|
237
|
+
apiKey: this.params.jupiterApiKey,
|
|
238
|
+
maxJupAccounts: this.params.maxAllowedAccounts,
|
|
239
|
+
});
|
|
240
|
+
jupQuotes.push({
|
|
241
|
+
...res,
|
|
242
|
+
inMint: pair.inMint,
|
|
243
|
+
outMint: pair.outMint,
|
|
244
|
+
});
|
|
245
|
+
console.log("Fetch new Jup Quote:", pair.inMint, pair.outMint);
|
|
246
|
+
console.log(pair, "Jup Quote:", parseFloat(res.quoteResponse?.outAmount ?? 0), "Requested In:", pair.inAmount);
|
|
247
|
+
} catch {}
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
for (let index = 0; index < pairs.length; index++) try {
|
|
252
|
+
let pair = pairs[index];
|
|
253
|
+
let jupIndex = jupQuotes.findIndex(q => q && q.inMint == pair.inMint && q.outMint == pair.outMint);
|
|
254
|
+
let quote = jupIndex >= 0 ? jupQuotes[jupIndex] : undefined;
|
|
255
|
+
if (!quote && this.params.network == "mainnet") continue;
|
|
230
256
|
if (pair.value < 0.005) continue;
|
|
231
|
-
|
|
232
|
-
let
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
basketAmountOut: pair.outAmount,
|
|
239
|
-
swapMode: "ioc",
|
|
240
|
-
apiKey: this.params.jupiterApiKey,
|
|
241
|
-
maxJupAccounts: this.params.maxAllowedAccounts,
|
|
242
|
-
}) : { tokenLedgerInstruction: undefined, swapInstruction: undefined, addressLookupTableAddresses: [], quoteResponse: undefined };
|
|
257
|
+
|
|
258
|
+
let tokenLedgerInstruction = quote?.tokenLedgerInstruction;
|
|
259
|
+
let swapInstruction = quote?.swapInstruction;
|
|
260
|
+
let addressLookupTableAddresses = quote?.addressLookupTableAddresses ?? [];
|
|
261
|
+
let quoteResponse = quote?.quoteResponse;
|
|
262
|
+
|
|
263
|
+
if (this.params.network == "mainnet" && !quoteResponse) continue;
|
|
243
264
|
console.log(pair, "Jup Quote:", parseFloat(quoteResponse?.outAmount ?? 0), "Requested In:", pair.inAmount);
|
|
244
|
-
|
|
265
|
+
|
|
266
|
+
let quoteResponseAmount = parseFloat(quoteResponse?.outAmount ?? 0);
|
|
267
|
+
if (this.params.network == "mainnet" && quoteResponseAmount * 1.005 <= pair.inAmount)
|
|
268
|
+
continue;
|
|
269
|
+
|
|
245
270
|
try {
|
|
246
271
|
let tx = await this.params.symmetryCore.flashSwapTx({
|
|
247
272
|
keeper: this.params.wallet.publicKey.toBase58(),
|
|
@@ -258,14 +283,15 @@ export class KeeperMonitor {
|
|
|
258
283
|
});
|
|
259
284
|
let res = await this.params.symmetryCore.signAndSendTxPayloadBatchSequence({txPayloadBatchSequence: tx, wallet: this.params.wallet, simulateTransactions: this.params.simulateTransactions});
|
|
260
285
|
console.log("Flash Swap - ", pubkey, " : ", res);
|
|
286
|
+
jupQuotes = jupQuotes.filter(q => q && (q.inMint != pair.inMint || q.outMint != pair.outMint));
|
|
261
287
|
} catch {}
|
|
262
|
-
}
|
|
263
288
|
} catch { }
|
|
264
289
|
nextCheckTime = (Date.now() / 1000) + 8;
|
|
265
290
|
continue;
|
|
266
291
|
}
|
|
267
292
|
if (intent.rebalance_type == "deposit") {
|
|
268
293
|
if (numTriesMint >= 3) break;
|
|
294
|
+
lastJupQuotesUpdate = 0;
|
|
269
295
|
numTriesMint += 1; try {
|
|
270
296
|
let tx = await this.params.symmetryCore.mintTx({
|
|
271
297
|
keeper: this.params.wallet.publicKey.toBase58(),
|
|
@@ -303,3 +329,257 @@ export class KeeperMonitor {
|
|
|
303
329
|
}
|
|
304
330
|
}
|
|
305
331
|
}
|
|
332
|
+
|
|
333
|
+
export class RebalanceHandler {
|
|
334
|
+
private params: {
|
|
335
|
+
wallet: Wallet,
|
|
336
|
+
connection: Connection,
|
|
337
|
+
symmetryCore: SymmetryCore,
|
|
338
|
+
network: "devnet" | "mainnet",
|
|
339
|
+
jupiterApiKey: string;
|
|
340
|
+
maxAllowedAccounts: number;
|
|
341
|
+
simulateTransactions: boolean;
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
private intent: UIRebalanceIntent;
|
|
345
|
+
private basket: Basket;
|
|
346
|
+
|
|
347
|
+
constructor(params: {
|
|
348
|
+
intent: UIRebalanceIntent,
|
|
349
|
+
basket: Basket,
|
|
350
|
+
wallet: Wallet,
|
|
351
|
+
connection: Connection,
|
|
352
|
+
network: "devnet" | "mainnet",
|
|
353
|
+
jupiterApiKey: string,
|
|
354
|
+
maxAllowedAccounts: number,
|
|
355
|
+
priorityFee?: number,
|
|
356
|
+
simulateTransactions?: boolean,
|
|
357
|
+
}) {
|
|
358
|
+
this.params = {
|
|
359
|
+
wallet: params.wallet,
|
|
360
|
+
connection: params.connection,
|
|
361
|
+
symmetryCore: new SymmetryCore({
|
|
362
|
+
connection: params.connection,
|
|
363
|
+
network: params.network,
|
|
364
|
+
priorityFee: params.priorityFee ?? PRIORITY_FEE,
|
|
365
|
+
}),
|
|
366
|
+
network: params.network,
|
|
367
|
+
jupiterApiKey: params.jupiterApiKey,
|
|
368
|
+
maxAllowedAccounts: params.maxAllowedAccounts,
|
|
369
|
+
simulateTransactions: params.simulateTransactions ?? false,
|
|
370
|
+
};
|
|
371
|
+
this.intent = params.intent;
|
|
372
|
+
this.basket = params.basket;
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
delay = async (ms: number) => new Promise(resolve => setTimeout(resolve, ms));
|
|
376
|
+
|
|
377
|
+
async refresh() {
|
|
378
|
+
this.intent = await this.params.symmetryCore.fetchRebalanceIntent(this.intent.formatted_data.pubkey);
|
|
379
|
+
this.basket = await this.params.symmetryCore.fetchBasket(this.intent.formatted_data.basket);
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
static async run(params: {
|
|
383
|
+
intentPubkey: PublicKey,
|
|
384
|
+
wallet: Wallet,
|
|
385
|
+
connection: Connection,
|
|
386
|
+
network: "devnet" | "mainnet",
|
|
387
|
+
jupiterApiKey: string,
|
|
388
|
+
maxAllowedAccounts: number,
|
|
389
|
+
priorityFee?: number,
|
|
390
|
+
simulateTransactions?: boolean,
|
|
391
|
+
}) {
|
|
392
|
+
let symmetryCore = new SymmetryCore({
|
|
393
|
+
connection: params.connection,
|
|
394
|
+
network: params.network,
|
|
395
|
+
priorityFee: params.priorityFee ?? PRIORITY_FEE,
|
|
396
|
+
});
|
|
397
|
+
let intent = await symmetryCore.fetchRebalanceIntent(params.intentPubkey.toBase58());
|
|
398
|
+
let basket = await symmetryCore.fetchBasket(intent.formatted_data.basket);
|
|
399
|
+
let handler = new RebalanceHandler({
|
|
400
|
+
intent, basket,
|
|
401
|
+
wallet: params.wallet,
|
|
402
|
+
connection: params.connection,
|
|
403
|
+
network: params.network,
|
|
404
|
+
jupiterApiKey: params.jupiterApiKey,
|
|
405
|
+
maxAllowedAccounts: params.maxAllowedAccounts,
|
|
406
|
+
simulateTransactions: params.simulateTransactions,
|
|
407
|
+
});
|
|
408
|
+
handler.execute();
|
|
409
|
+
for (let i = 0; i < 20; i++) {
|
|
410
|
+
await handler.delay(15 * 1000);
|
|
411
|
+
try { await handler.refresh(); }
|
|
412
|
+
catch (e) { handler.intent = undefined as any; break;}
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
private async execute() {
|
|
417
|
+
console.log("Starting rebalance handler for intent:", this.intent.formatted_data.pubkey);
|
|
418
|
+
let nextCheckTime = 0;
|
|
419
|
+
let numTriesUpdatePrices = 0;
|
|
420
|
+
let numTriesMint = 0;
|
|
421
|
+
let numTriesRedeemTokens = 0;
|
|
422
|
+
let numTriesClaimBounty = 0;
|
|
423
|
+
let rebalancePairs: {
|
|
424
|
+
inMint: string,
|
|
425
|
+
outMint: string,
|
|
426
|
+
inAmount: number,
|
|
427
|
+
outAmount: number,
|
|
428
|
+
value: number,
|
|
429
|
+
}[] = [];
|
|
430
|
+
let lastJupQuotesUpdate = 0;
|
|
431
|
+
let jupQuotes: ({
|
|
432
|
+
inMint: string,
|
|
433
|
+
outMint: string,
|
|
434
|
+
tokenLedgerInstruction: TransactionInstruction,
|
|
435
|
+
swapInstruction: TransactionInstruction,
|
|
436
|
+
addressLookupTableAddresses: PublicKey[],
|
|
437
|
+
quoteResponse: any,
|
|
438
|
+
}|undefined)[] = [];
|
|
439
|
+
|
|
440
|
+
while (true) {
|
|
441
|
+
if (!this.intent) break;
|
|
442
|
+
let intent = this.intent.formatted_data;
|
|
443
|
+
let chainData = this.intent.chain_data;
|
|
444
|
+
let now = Date.now() / 1000;
|
|
445
|
+
|
|
446
|
+
if (now < nextCheckTime) {
|
|
447
|
+
await this.delay(Math.min(30 * 1000, Math.max(0, nextCheckTime - now + 0.2) * 1000));
|
|
448
|
+
continue;
|
|
449
|
+
}
|
|
450
|
+
nextCheckTime = now + 5;
|
|
451
|
+
|
|
452
|
+
if (intent.current_action == "not_active") { console.log("Intent not active, stopping"); break; }
|
|
453
|
+
if (intent.current_action == "deposit_tokens") { console.log("Waiting for deposit..."); continue; }
|
|
454
|
+
|
|
455
|
+
if (intent.current_action == "update_prices" && intent.last_action_timestamp > now)
|
|
456
|
+
{ nextCheckTime = intent.last_action_timestamp; continue; }
|
|
457
|
+
|
|
458
|
+
if (intent.current_action == "update_prices") {
|
|
459
|
+
if (numTriesUpdatePrices >= 3) { console.log("Max retries for update_prices"); break; }
|
|
460
|
+
numTriesUpdatePrices += 1; try {
|
|
461
|
+
let tx = await this.params.symmetryCore.updateTokenPricesTx({
|
|
462
|
+
keeper: this.params.wallet.publicKey.toBase58(),
|
|
463
|
+
basket: intent.basket,
|
|
464
|
+
rebalance_intent: intent.pubkey,
|
|
465
|
+
});
|
|
466
|
+
let res = await this.params.symmetryCore.signAndSendTxPayloadBatchSequence({txPayloadBatchSequence: tx, wallet: this.params.wallet, simulateTransactions: this.params.simulateTransactions});
|
|
467
|
+
console.log("Update Prices:", res);
|
|
468
|
+
} catch (e) { if (numTriesUpdatePrices == 3) { console.log("Stop - update prices failed:", e); } }
|
|
469
|
+
continue;
|
|
470
|
+
}
|
|
471
|
+
|
|
472
|
+
if (intent.auctions[2].end_time > now) {
|
|
473
|
+
|
|
474
|
+
rebalancePairs = getSwapPairs(chainData, this.basket);
|
|
475
|
+
|
|
476
|
+
if (Date.now() / 1000 > lastJupQuotesUpdate + 60) {
|
|
477
|
+
let usedValue: Map<string, number> = new Map();
|
|
478
|
+
jupQuotes = [];
|
|
479
|
+
for (let pair of rebalancePairs) {
|
|
480
|
+
let inValue = usedValue.get(pair.inMint) ?? 0;
|
|
481
|
+
let outValue = usedValue.get(pair.outMint) ?? 0;
|
|
482
|
+
let swapValue = Math.min(pair.value - inValue, pair.value - outValue);
|
|
483
|
+
if (swapValue < 0.005) {
|
|
484
|
+
jupQuotes.push(undefined);
|
|
485
|
+
continue;
|
|
486
|
+
}
|
|
487
|
+
usedValue.set(pair.inMint, inValue + swapValue);
|
|
488
|
+
usedValue.set(pair.outMint, outValue + swapValue);
|
|
489
|
+
let res = undefined;
|
|
490
|
+
if (this.params.network == "mainnet") try {
|
|
491
|
+
res = {
|
|
492
|
+
...(await getJupTokenLedgerAndSwapInstructions({
|
|
493
|
+
keeper: this.params.wallet.publicKey,
|
|
494
|
+
basketMintIn: new PublicKey(pair.inMint),
|
|
495
|
+
basketMintOut: new PublicKey(pair.outMint),
|
|
496
|
+
basketAmountIn: pair.inAmount,
|
|
497
|
+
basketAmountOut: pair.outAmount,
|
|
498
|
+
swapMode: "ioc",
|
|
499
|
+
apiKey: this.params.jupiterApiKey,
|
|
500
|
+
maxJupAccounts: this.params.maxAllowedAccounts,
|
|
501
|
+
})),
|
|
502
|
+
inMint: pair.inMint,
|
|
503
|
+
outMint: pair.outMint,
|
|
504
|
+
};
|
|
505
|
+
} catch {};
|
|
506
|
+
jupQuotes.push(res);
|
|
507
|
+
}
|
|
508
|
+
}
|
|
509
|
+
|
|
510
|
+
for (let index = 0; index < rebalancePairs.length; index++) try {
|
|
511
|
+
let pair = rebalancePairs[index];
|
|
512
|
+
let quote = jupQuotes.find(q => q && q.inMint == pair.inMint && q.outMint == pair.outMint);
|
|
513
|
+
if (!quote) continue;
|
|
514
|
+
if (pair.value < 0.005) continue;
|
|
515
|
+
let { tokenLedgerInstruction, swapInstruction, addressLookupTableAddresses, quoteResponse } = quote;
|
|
516
|
+
if (!quoteResponse) continue;
|
|
517
|
+
console.log(pair, "Jup Quote:", parseFloat(quoteResponse.outAmount), "Requested In:", pair.inAmount);
|
|
518
|
+
if (parseFloat(quoteResponse.outAmount) <= pair.inAmount && this.params.network == "mainnet")
|
|
519
|
+
continue;
|
|
520
|
+
try {
|
|
521
|
+
let tx = await this.params.symmetryCore.flashSwapTx({
|
|
522
|
+
keeper: this.params.wallet.publicKey.toBase58(),
|
|
523
|
+
basket: this.basket.ownAddress.toBase58(),
|
|
524
|
+
rebalance_intent: intent.pubkey,
|
|
525
|
+
mint_in: pair.inMint,
|
|
526
|
+
mint_out: pair.outMint,
|
|
527
|
+
amount_in: pair.inAmount,
|
|
528
|
+
amount_out: pair.outAmount,
|
|
529
|
+
mode: 2,
|
|
530
|
+
jup_token_ledger_ix: tokenLedgerInstruction,
|
|
531
|
+
jup_swap_ix: swapInstruction,
|
|
532
|
+
jup_address_lookup_table_addresses: addressLookupTableAddresses,
|
|
533
|
+
});
|
|
534
|
+
let res = await this.params.symmetryCore.signAndSendTxPayloadBatchSequence({txPayloadBatchSequence: tx, wallet: this.params.wallet, simulateTransactions: this.params.simulateTransactions});
|
|
535
|
+
console.log("Flash Swap:", res);
|
|
536
|
+
rebalancePairs = rebalancePairs.splice(index, 1);
|
|
537
|
+
index -= 1;
|
|
538
|
+
} catch {}
|
|
539
|
+
} catch { }
|
|
540
|
+
nextCheckTime = (Date.now() / 1000) + 10;
|
|
541
|
+
continue;
|
|
542
|
+
}
|
|
543
|
+
if (intent.rebalance_type == "deposit") {
|
|
544
|
+
if (numTriesMint >= 3) break;
|
|
545
|
+
lastJupQuotesUpdate = 0;
|
|
546
|
+
numTriesMint += 1; try {
|
|
547
|
+
let tx = await this.params.symmetryCore.mintTx({
|
|
548
|
+
keeper: this.params.wallet.publicKey.toBase58(),
|
|
549
|
+
rebalance_intent: intent.pubkey,
|
|
550
|
+
});
|
|
551
|
+
let res = await this.params.symmetryCore.signAndSendTxPayloadBatchSequence({txPayloadBatchSequence: tx, wallet: this.params.wallet, simulateTransactions: this.params.simulateTransactions});
|
|
552
|
+
console.log("Mint -", res);
|
|
553
|
+
} catch (e) { if (numTriesMint == 3) { console.log("Stop monitoring -", e); } }
|
|
554
|
+
continue;
|
|
555
|
+
}
|
|
556
|
+
let hasTokens = intent.tokens.find(token => token.amount > 0);
|
|
557
|
+
if (hasTokens && intent.rebalance_type == "withdraw") {
|
|
558
|
+
if (numTriesRedeemTokens >= 3) break;
|
|
559
|
+
numTriesRedeemTokens += 1; try {
|
|
560
|
+
let tx = await this.params.symmetryCore.redeemTokensTx({
|
|
561
|
+
keeper: this.params.wallet.publicKey.toBase58(),
|
|
562
|
+
rebalance_intent: intent.pubkey,
|
|
563
|
+
});
|
|
564
|
+
let res = await this.params.symmetryCore.signAndSendTxPayloadBatchSequence({txPayloadBatchSequence: tx, wallet: this.params.wallet, simulateTransactions: this.params.simulateTransactions});
|
|
565
|
+
console.log("Redeem Tokens -", res);
|
|
566
|
+
} catch (e) { if (numTriesRedeemTokens == 3) { console.log("Stop monitoring -", e); } }
|
|
567
|
+
continue;
|
|
568
|
+
}
|
|
569
|
+
if (numTriesClaimBounty >= 3) break;
|
|
570
|
+
numTriesClaimBounty += 1; try {
|
|
571
|
+
let tx = await this.params.symmetryCore.claimBountyTx({
|
|
572
|
+
keeper: this.params.wallet.publicKey.toBase58(),
|
|
573
|
+
rebalance_intent: intent.pubkey,
|
|
574
|
+
});
|
|
575
|
+
let res = await this.params.symmetryCore.signAndSendTxPayloadBatchSequence({txPayloadBatchSequence: tx, wallet: this.params.wallet, simulateTransactions: this.params.simulateTransactions});
|
|
576
|
+
console.log("Claim Bounty -", res);
|
|
577
|
+
nextCheckTime = now + 60;
|
|
578
|
+
} catch (e) { if (numTriesClaimBounty == 3) { console.log("Stop monitoring -", e); } }
|
|
579
|
+
continue;
|
|
580
|
+
}
|
|
581
|
+
|
|
582
|
+
}
|
|
583
|
+
}
|
|
584
|
+
|
|
585
|
+
|
package/test.ts
CHANGED
|
@@ -13,7 +13,6 @@ import { getSwapPairs } from "./src/states/intents/rebalanceIntent";
|
|
|
13
13
|
let kp = Array.from(Keypair.generate().secretKey);
|
|
14
14
|
|
|
15
15
|
let jupApiKey = "";
|
|
16
|
-
|
|
17
16
|
let connection = new Connection("https://api.devnet.solana.com");
|
|
18
17
|
|
|
19
18
|
async function testStates() {
|
|
@@ -24,7 +23,7 @@ async function testStates() {
|
|
|
24
23
|
let sdk = new SymmetryCore({
|
|
25
24
|
connection: connection,
|
|
26
25
|
network: "mainnet",
|
|
27
|
-
priorityFee:
|
|
26
|
+
priorityFee: 5237,
|
|
28
27
|
});
|
|
29
28
|
let keeperMonitor = new KeeperMonitor({
|
|
30
29
|
wallet: wallet,
|
|
@@ -33,7 +32,7 @@ async function testStates() {
|
|
|
33
32
|
jupiterApiKey: jupApiKey,
|
|
34
33
|
maxAllowedAccounts: 40,
|
|
35
34
|
simulateTransactions: false,
|
|
36
|
-
priorityFee:
|
|
35
|
+
priorityFee: 5237,
|
|
37
36
|
});
|
|
38
37
|
// keeperMonitor.run();
|
|
39
38
|
// return;
|