@symmetry-hq/sdk 1.0.8 → 1.0.9

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/LICENSE ADDED
@@ -0,0 +1,41 @@
1
+ Business Source License 1.1
2
+
3
+ Licensor: Symmetry Protocol
4
+ Licensed Work: @symmetry-hq/sdk
5
+ Change Date: None
6
+ Change License: None
7
+
8
+ Additional Use Grant
9
+
10
+ You may use the Licensed Work in production, including for commercial purposes,
11
+ to build applications, services, and products that integrate with the Symmetry
12
+ Protocol.
13
+
14
+ You may NOT use the Licensed Work to create a competing SDK, library, or
15
+ protocol infrastructure that replicates or substitutes the functionality of the
16
+ Licensed Work or the Symmetry Protocol.
17
+
18
+ Terms
19
+
20
+ The Licensor hereby grants you the right to copy, modify, create derivative
21
+ works, redistribute, and make non-production use of the Licensed Work. The
22
+ Licensor may make an Additional Use Grant, above, permitting limited production
23
+ use.
24
+
25
+ Except for the Additional Use Grant and the right of non-production use, all
26
+ rights in the Licensed Work remain exclusively with the Licensor.
27
+
28
+ If the Licensor specifies a Change Date, the Licensed Work will be made
29
+ available under the Change License on the Change Date. No Change Date has been
30
+ specified for this Licensed Work.
31
+
32
+ Notice
33
+
34
+ Business Source License 1.1 is not an Open Source license. However, the
35
+ Licensed Work may eventually be made available under an Open Source License, as
36
+ stated in this License.
37
+
38
+ For the full text of the Business Source License 1.1, see:
39
+ https://mariadb.com/bsl11/
40
+
41
+ Copyright (c) 2026 Symmetry Protocol. All rights reserved.
package/README.md ADDED
@@ -0,0 +1,742 @@
1
+ # @symmetry-hq/sdk
2
+
3
+ TypeScript SDK for the **Symmetry V3** protocol on Solana — on-chain infrastructure for creating and managing multi-token vaults with automated rebalancing, oracle-based pricing, and permissionless keeper execution.
4
+
5
+ [Documentation](https://docs.symmetry.fi) | [LLMs.txt](https://docs.symmetry.fi/llms.txt) | [App](https://beta.symmetry.fi) | [Discord](https://discord.gg/Bvgt87KTJB)
6
+
7
+ Have questions or need help integrating? [Join our Discord](https://discord.gg/Bvgt87KTJB).
8
+
9
+ ## Installation
10
+
11
+ ```bash
12
+ npm install @symmetry-hq/sdk
13
+ ```
14
+
15
+ ### Peer Dependencies
16
+
17
+ ```bash
18
+ npm install @solana/web3.js @coral-xyz/anchor
19
+ ```
20
+
21
+ ## Quick Start
22
+
23
+ ```typescript
24
+ import { Connection } from "@solana/web3.js";
25
+ import { SymmetryCore } from "@symmetry-hq/sdk";
26
+
27
+ const connection = new Connection("https://api.mainnet-beta.solana.com");
28
+ const sdk = new SymmetryCore({
29
+ connection,
30
+ network: "mainnet",
31
+ priorityFee: 50_000, // optional, micro-lamports (default: 25,000)
32
+ });
33
+
34
+ // Fetch all vaults
35
+ const vaults = await sdk.fetchAllVaults();
36
+
37
+ // Fetch a single vault and load its price
38
+ let vault = await sdk.fetchVault("<VAULT_PUBKEY>");
39
+ vault = await sdk.loadVaultPrice(vault);
40
+ console.log(vault.formatted);
41
+ ```
42
+
43
+ ## Core Concepts
44
+
45
+ ### Vaults
46
+
47
+ A vault is an on-chain account that holds a configurable set of SPL tokens with target weights. Each vault:
48
+
49
+ - Holds multiple SPL tokens with individually configurable target weights
50
+ - Mints its own SPL token — vault token holders have proportional ownership of the underlying tokens
51
+ - Supports multi-source oracle pricing (Pyth, Raydium CPMM; Raydium CLMM and Switchboard are currently disabled) with configurable aggregation
52
+ - Has a flexible fee structure (deposit, withdrawal, management, performance) split across creator, host platform, managers, and protocol. Management and performance fees are currently disabled at the protocol level.
53
+ - Supports up to 100 tokens, 10 managers, and 4 oracle sources per token
54
+
55
+ ### Intents
56
+
57
+ All configuration changes to a vault go through an **intent system**. An intent is an on-chain change request — editing fees, metadata, token composition, weights, etc. — with optional time-locks and bounty incentives for keepers to execute them.
58
+
59
+ ### Rebalance Intents
60
+
61
+ Deposits, withdrawals, and periodic rebalances are processed through the same on-chain flow. They progress through a multi-step auction:
62
+
63
+ 1. **Deposit tokens** — user contributes tokens to the vault
64
+ 2. **Lock deposits** — freezes contributions and starts the process
65
+ 3. **Price updates** — oracle prices are refreshed on-chain
66
+ 4. **Auction** — keepers execute flash swaps to settle the vault toward target weights
67
+ 5. **Mint / Redeem** — vault tokens are minted (deposits) or underlying tokens are released (withdrawals)
68
+ 6. **Claim bounty** — keepers collect their rewards
69
+
70
+ ### Keepers
71
+
72
+ Keepers are off-chain agents that monitor the protocol, execute pending tasks (intents, price updates, auctions), and earn bounties. All keeper operations are permissionless — developers can build custom keeper bots using the SDK's transaction-building methods. The SDK also ships with `KeeperMonitor` and `RebalanceHandler` as reference implementations that work out of the box.
73
+
74
+ ---
75
+
76
+ ## API Reference
77
+
78
+ ### Constructor
79
+
80
+ ```typescript
81
+ const sdk = new SymmetryCore({
82
+ connection: Connection, // Solana RPC connection
83
+ network: "devnet" | "mainnet",
84
+ priorityFee?: number, // compute unit price in micro-lamports (default: 25,000)
85
+ });
86
+ ```
87
+
88
+ ### Configuration
89
+
90
+ #### `setPriorityFee(priorityFee: number): void`
91
+
92
+ Updates the priority fee for all subsequent transactions.
93
+
94
+ #### `fetchGlobalConfig(): Promise<GlobalConfig>`
95
+
96
+ Returns the protocol-wide configuration account (fee limits, bounty settings, rebalance parameters).
97
+
98
+ ---
99
+
100
+ ### Fetching Vaults
101
+
102
+ #### `fetchVault(vaultPubkey: string): Promise<Vault>`
103
+
104
+ Fetch a single vault by its account public key.
105
+
106
+ #### `fetchMultipleVaults(vaultPubkeys: string[]): Promise<Map<string, Vault>>`
107
+
108
+ Batch-fetch multiple vaults. Returns a map keyed by public key.
109
+
110
+ #### `fetchAllVaults(filter?: VaultFilter): Promise<Vault[]>`
111
+
112
+ Fetch all vaults on-chain with an optional role filter:
113
+
114
+ ```typescript
115
+ type VaultFilter = {
116
+ type: "creator" | "host" | "manager";
117
+ pubkey: string;
118
+ };
119
+ ```
120
+
121
+ #### `fetchCreatedVaults(creatorPubkey: string): Promise<Vault[]>`
122
+
123
+ Fetch vaults created by a specific public key.
124
+
125
+ #### `fetchHostedVaults(hostPubkey: string): Promise<Vault[]>`
126
+
127
+ Fetch vaults hosted by a specific public key.
128
+
129
+ #### `fetchManagedVaults(managerPubkey: string): Promise<Vault[]>`
130
+
131
+ Fetch vaults managed by a specific public key.
132
+
133
+ #### `fetchVaultsFromMints(mints: string[]): Promise<Map<string, Vault>>`
134
+
135
+ Look up vaults by their SPL token mint addresses. Returns a map keyed by mint.
136
+
137
+ #### `deriveVaultsByMints(mints: string[]): Promise<Map<string, string>>`
138
+
139
+ Derive vault account addresses from mint addresses without RPC calls. Returns a mint-to-pubkey map.
140
+
141
+ #### `loadVaultPrice(vault: Vault): Promise<Vault>`
142
+
143
+ Loads live oracle prices for all tokens in the vault, computes the vault's total value, and returns the updated object.
144
+
145
+ ---
146
+
147
+ ### Fetching Intents
148
+
149
+ #### `fetchIntent(intentPubkey: string): Promise<Intent>`
150
+
151
+ Fetch a single intent by its public key.
152
+
153
+ #### `fetchMultipleIntents(intentPubkeys: string[]): Promise<Map<string, Intent>>`
154
+
155
+ Batch-fetch multiple intents.
156
+
157
+ #### `fetchAllIntents(filter?: IntentFilter): Promise<Intent[]>`
158
+
159
+ Fetch all intents with an optional filter:
160
+
161
+ ```typescript
162
+ type IntentFilter = {
163
+ type: "manager" | "vault";
164
+ pubkey: string;
165
+ };
166
+ ```
167
+
168
+ #### `fetchCreatedIntents(creatorPubkey: string): Promise<Intent[]>`
169
+
170
+ Fetch intents created by a specific manager.
171
+
172
+ #### `fetchVaultIntents(vaultPubkey: string): Promise<Intent[]>`
173
+
174
+ Fetch all intents for a specific vault.
175
+
176
+ ---
177
+
178
+ ### Fetching Rebalance Intents
179
+
180
+ #### `fetchRebalanceIntent(pubkey: string): Promise<UIRebalanceIntent>`
181
+
182
+ Fetch a single rebalance intent.
183
+
184
+ #### `fetchMultipleRebalanceIntents(pubkeys: string[]): Promise<Map<string, UIRebalanceIntent>>`
185
+
186
+ Batch-fetch multiple rebalance intents.
187
+
188
+ #### `fetchAllRebalanceIntents(filter?: RebalanceIntentFilter): Promise<UIRebalanceIntent[]>`
189
+
190
+ Fetch all rebalance intents with an optional filter:
191
+
192
+ ```typescript
193
+ type RebalanceIntentFilter = {
194
+ type: "owner" | "vault";
195
+ pubkey: string;
196
+ };
197
+ ```
198
+
199
+ #### `fetchOwnerRebalanceIntents(ownerPubkey: string): Promise<UIRebalanceIntent[]>`
200
+
201
+ Fetch rebalance intents owned by a specific public key.
202
+
203
+ #### `fetchVaultRebalanceIntents(vaultPubkey: string): Promise<UIRebalanceIntent[]>`
204
+
205
+ Fetch rebalance intents for a specific vault.
206
+
207
+ ---
208
+
209
+ ### Fetching Fee Accounts
210
+
211
+ #### `fetchWithdrawVaultFees(pubkey: string): Promise<WithdrawVaultFees>`
212
+
213
+ Fetch a single fee withdrawal account.
214
+
215
+ #### `fetchMultipleWithdrawVaultFees(pubkeys: string[]): Promise<Map<string, WithdrawVaultFees>>`
216
+
217
+ Batch-fetch multiple fee withdrawal accounts.
218
+
219
+ #### `fetchAllWithdrawVaultFees(filter?: WithdrawVaultFeesFilter): Promise<WithdrawVaultFees[]>`
220
+
221
+ Fetch all fee withdrawal accounts with an optional filter:
222
+
223
+ ```typescript
224
+ type WithdrawVaultFeesFilter = {
225
+ type: "vault" | "manager" | "creator" | "host" | "symmetry";
226
+ pubkey: string;
227
+ };
228
+ ```
229
+
230
+ Convenience methods: `fetchVaultWithdrawVaultFees`, `fetchManagerWithdrawVaultFees`, `fetchCreatorWithdrawVaultFees`, `fetchHostWithdrawVaultFees`, `fetchSymmetryWithdrawVaultFees`.
231
+
232
+ ---
233
+
234
+ ### Creating Vaults
235
+
236
+ #### `createVaultTx(params): Promise<VaultCreationTx>`
237
+
238
+ Creates a new vault. Returns the vault's token mint, account address, and the transaction payload.
239
+
240
+ The `metadata_uri` is a URL (max 200 chars) pointing to a JSON file describing the vault. It should contain `name` (vault token name), `symbol` (vault token ticker), `description` (vault description), `image` (token image/icon URL), and `cover` (vault cover image URL). You can add any extra fields for your own integrations (social links, website, etc.):
241
+ ```json
242
+ {
243
+ "name": "My Vault",
244
+ "symbol": "MVT",
245
+ "description": "A multi-token vault.",
246
+ "image": "https://arweave.net/token-image-url",
247
+ "cover": "https://arweave.net/cover-image-url"
248
+ }
249
+ ```
250
+
251
+ ```typescript
252
+ const result = await sdk.createVaultTx({
253
+ creator: wallet.publicKey.toBase58(),
254
+ start_price: "1.0", // initial price in USDC
255
+ name: "My Vault",
256
+ symbol: "MVT",
257
+ metadata_uri: "https://arweave.net/your-metadata-json", // URL to JSON with name, symbol, description, image, cover
258
+ host_platform_params: { // optional
259
+ host_pubkey: "<HOST_PUBKEY>",
260
+ host_deposit_fee_bps: 10, // 0.1%
261
+ host_withdraw_fee_bps: 10,
262
+ host_management_fee_bps: 0, // currently disabled in global config
263
+ host_performance_fee_bps: 0, // currently disabled in global config
264
+ },
265
+ });
266
+
267
+ console.log("Vault mint:", result.mint);
268
+ console.log("Vault account:", result.vault);
269
+
270
+ await sdk.signAndSendTxPayloadBatchSequence({
271
+ txPayloadBatchSequence: result,
272
+ wallet,
273
+ });
274
+ ```
275
+
276
+ ---
277
+
278
+ ### Editing Vault Settings
279
+
280
+ All edit methods create an intent that modifies the vault. If the setting has no modification delay and no scheduled activation, the intent is executed immediately in the same transaction.
281
+
282
+ Each method accepts a `TaskContext` and a settings object, returning a `TxPayloadBatchSequence`:
283
+
284
+ ```typescript
285
+ interface TaskContext {
286
+ vault: string; // vault public key
287
+ manager: string; // authorized manager public key
288
+ activation_timestamp?: number; // optional scheduled activation (unix seconds)
289
+ expiration_timestamp?: number; // optional expiration
290
+ min_bounty?: number; // optional min bounty override
291
+ max_bounty?: number; // optional max bounty override
292
+ }
293
+ ```
294
+
295
+ | Method | Settings Type | Description |
296
+ |--------|--------------|-------------|
297
+ | `editCreatorTx` | `EditCreatorSettings` | Transfer vault creator role |
298
+ | `editManagersTx` | `EditManagerSettings` | Edit managers, weights, and authority bitmasks |
299
+ | `editFeesTx` | `EditFeeSettings` | Update fee structure |
300
+ | `editScheduleTx` | `EditScheduleSettings` | Configure repeating time cycles that gate deposits, automation, and management windows |
301
+ | `editAutomationTx` | `EditAutomationSettings` | Configure rebalance automation |
302
+ | `editLpTx` | `EditLpSettings` | Configure LP settings |
303
+ | `editMetadataTx` | `EditMetadataSettings` | Update name, symbol, and metadata URI (JSON with name, symbol, description, image, cover) |
304
+ | `editDepositsTx` | `EditDepositsSettings` | Enable or disable deposits |
305
+ | `editForceRebalanceTx` | `EditForceRebalanceSettings` | Enable or disable force rebalance |
306
+ | `editCustomRebalanceTx` | `EditCustomRebalanceSettings` | Enable or disable custom rebalance |
307
+ | `editAddTokenDelayTx` | `EditAddTokenSettings` | Set time-lock for adding tokens |
308
+ | `editUpdateWeightsDelayTx` | `EditUpdateWeightsSettings` | Set time-lock for weight updates |
309
+ | `editSwapDelayTx` | `EditMakeDirectSwapSettings` | Set time-lock for direct swaps |
310
+
311
+ #### Token Composition
312
+
313
+ #### `addOrEditTokenTx(context: TaskContext, settings: AddOrEditTokenInput): Promise<TxPayloadBatchSequence>`
314
+
315
+ Add a new token to the vault or update an existing token's oracle configuration:
316
+
317
+ ```typescript
318
+ const tx = await sdk.addOrEditTokenTx(
319
+ { vault: "<VAULT_PUBKEY>", manager: "<MANAGER>" },
320
+ {
321
+ token_mint: "<TOKEN_MINT>",
322
+ active: true,
323
+ min_oracles_thresh: 1,
324
+ min_conf_bps: 10,
325
+ conf_thresh_bps: 200,
326
+ conf_multiplier: 1.0,
327
+ oracles: [
328
+ {
329
+ oracle_type: "pyth",
330
+ account_lut_id: 0,
331
+ account_lut_index: 0,
332
+ account: "<PYTH_PRICE_ACCOUNT>",
333
+ weight_bps: 10000,
334
+ is_required: true,
335
+ conf_thresh_bps: 200,
336
+ volatility_thresh_bps: 200,
337
+ max_slippage_bps: 1000,
338
+ min_liquidity: 0,
339
+ staleness_thresh: 120,
340
+ staleness_conf_rate_bps: 50,
341
+ token_decimals: 9,
342
+ twap_seconds_ago: 0,
343
+ twap_secondary_seconds_ago: 0,
344
+ quote_token: "usd",
345
+ },
346
+ ],
347
+ }
348
+ );
349
+ ```
350
+
351
+ #### `updateWeightsTx(context: TaskContext, settings: UpdateWeightsInput): Promise<TxPayloadBatchSequence>`
352
+
353
+ Update target weights for all tokens in the vault:
354
+
355
+ ```typescript
356
+ const tx = await sdk.updateWeightsTx(
357
+ { vault: "<VAULT_PUBKEY>", manager: "<MANAGER>" },
358
+ {
359
+ token_weights: [
360
+ { mint: "<TOKEN_MINT_1>", weight_bps: 5000 },
361
+ { mint: "<TOKEN_MINT_2>", weight_bps: 3000 },
362
+ { mint: "<TOKEN_MINT_3>", weight_bps: 2000 },
363
+ ], // basis points, must sum to 10000
364
+ }
365
+ );
366
+ ```
367
+
368
+ #### `makeDirectSwapTx(context, settings, jup_swap_ix?): Promise<TxPayloadBatchSequence>`
369
+
370
+ Execute a direct token swap within the vault via Jupiter.
371
+
372
+ ---
373
+
374
+ ### Intent Execution & Cancellation
375
+
376
+ #### `executeVaultIntentTx(params): Promise<TxPayloadBatchSequence>`
377
+
378
+ Execute a pending intent after its time-lock has elapsed:
379
+
380
+ ```typescript
381
+ await sdk.executeVaultIntentTx({
382
+ keeper: wallet.publicKey.toBase58(),
383
+ intent: "<INTENT_PUBKEY>",
384
+ });
385
+ ```
386
+
387
+ #### `executeDirectSwapVaultIntentTx(params): Promise<TxPayloadBatchSequence>`
388
+
389
+ Execute a pending direct swap intent with a flash swap:
390
+
391
+ ```typescript
392
+ await sdk.executeDirectSwapVaultIntentTx({
393
+ keeper: wallet.publicKey.toBase58(),
394
+ intent: "<INTENT_PUBKEY>",
395
+ jup_swap_ix: jupiterSwapInstruction,
396
+ jup_address_lookup_table_addresses: [...],
397
+ });
398
+ ```
399
+
400
+ #### `cancelVaultIntentTx(params): Promise<TxPayloadBatchSequence>`
401
+
402
+ Cancel and close an intent account:
403
+
404
+ ```typescript
405
+ await sdk.cancelVaultIntentTx({
406
+ keeper: wallet.publicKey.toBase58(),
407
+ intent: "<INTENT_PUBKEY>",
408
+ });
409
+ ```
410
+
411
+ ---
412
+
413
+ ### Deposits & Withdrawals
414
+
415
+ #### `buyVaultTx(params): Promise<TxPayloadBatchSequence>`
416
+
417
+ Deposit tokens into a vault to receive vault tokens:
418
+
419
+ ```typescript
420
+ const tx = await sdk.buyVaultTx({
421
+ buyer: wallet.publicKey.toBase58(),
422
+ vault_mint: "<VAULT_MINT>",
423
+ contributions: [
424
+ { mint: "So11111111111111111111111111111111111111112", amount: 1_000_000_000 }, // 1 SOL
425
+ { mint: "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v", amount: 100_000_000 }, // 100 USDC
426
+ ],
427
+ rebalance_slippage_bps: 100, // optional (default: 1%)
428
+ per_trade_rebalance_slippage_bps: 100, // optional
429
+ });
430
+
431
+ await sdk.signAndSendTxPayloadBatchSequence({
432
+ txPayloadBatchSequence: tx,
433
+ wallet,
434
+ });
435
+ ```
436
+
437
+ #### `depositTokensTx(params): Promise<TxPayloadBatchSequence>`
438
+
439
+ Add more tokens to an existing deposit before locking:
440
+
441
+ ```typescript
442
+ const tx = await sdk.depositTokensTx({
443
+ buyer: wallet.publicKey.toBase58(),
444
+ contributions: [{ mint: "<MINT>", amount: 500_000_000 }],
445
+ rebalance_intent: "<REBALANCE_INTENT_PUBKEY>",
446
+ });
447
+ ```
448
+
449
+ #### `lockDepositsTx(params): Promise<TxPayloadBatchSequence>`
450
+
451
+ Lock deposits and start the auction process:
452
+
453
+ ```typescript
454
+ const tx = await sdk.lockDepositsTx({
455
+ buyer: wallet.publicKey.toBase58(),
456
+ vault_mint: "<VAULT_MINT>",
457
+ });
458
+ ```
459
+
460
+ #### `sellVaultTx(params): Promise<TxPayloadBatchSequence>`
461
+
462
+ Withdraw from a vault by burning vault tokens:
463
+
464
+ ```typescript
465
+ const tx = await sdk.sellVaultTx({
466
+ seller: wallet.publicKey.toBase58(),
467
+ vault_mint: "<VAULT_MINT>",
468
+ withdraw_amount: 1_000_000, // vault tokens to burn
469
+ keep_tokens: [], // mints to receive directly without rebalancing
470
+ rebalance_slippage_bps: 100,
471
+ });
472
+ ```
473
+
474
+ ---
475
+
476
+ ### Rebalancing
477
+
478
+ #### `rebalanceVaultTx(params): Promise<TxPayloadBatchSequence>`
479
+
480
+ Trigger a rebalance to bring the vault back to its target weights:
481
+
482
+ ```typescript
483
+ const tx = await sdk.rebalanceVaultTx({
484
+ keeper: wallet.publicKey.toBase58(),
485
+ vault_mint: "<VAULT_MINT>",
486
+ rebalance_slippage_bps: 100,
487
+ });
488
+ ```
489
+
490
+ #### `cancelRebalanceIntentTx(params): Promise<TxPayloadBatchSequence>`
491
+
492
+ Cancel an active rebalance intent:
493
+
494
+ ```typescript
495
+ const tx = await sdk.cancelRebalanceIntentTx({
496
+ keeper: wallet.publicKey.toBase58(),
497
+ rebalance_intent: "<REBALANCE_INTENT_PUBKEY>",
498
+ });
499
+ ```
500
+
501
+ ---
502
+
503
+ ### Oracle Price Updates
504
+
505
+ #### `updateTokenPricesTx(params): Promise<TxPayloadBatchSequence>`
506
+
507
+ Refresh on-chain oracle prices for all tokens in a vault during a rebalance:
508
+
509
+ ```typescript
510
+ const tx = await sdk.updateTokenPricesTx({
511
+ keeper: wallet.publicKey.toBase58(),
512
+ vault: "<VAULT_PUBKEY>",
513
+ rebalance_intent: "<REBALANCE_INTENT_PUBKEY>",
514
+ });
515
+ ```
516
+
517
+ #### `updatePythPriceFeedsTx(params): Promise<TxPayloadBatchSequence>`
518
+
519
+ Update specific Pyth price feeds from on-chain price accounts:
520
+
521
+ ```typescript
522
+ const tx = await sdk.updatePythPriceFeedsTx({
523
+ keeper: wallet.publicKey.toBase58(),
524
+ accounts: ["<PYTH_PRICE_ACCOUNT_1>", "<PYTH_PRICE_ACCOUNT_2>"],
525
+ });
526
+ ```
527
+
528
+ ---
529
+
530
+ ### Flash Swaps
531
+
532
+ #### `flashSwapTx(params): Promise<TxPayloadBatchSequence>`
533
+
534
+ Execute an atomic flash swap during rebalance auctions — withdraws tokens from the vault, performs a swap (e.g. via Jupiter), and deposits the result back in a single transaction:
535
+
536
+ ```typescript
537
+ const tx = await sdk.flashSwapTx({
538
+ keeper: wallet.publicKey.toBase58(),
539
+ vault: "<VAULT_PUBKEY>",
540
+ rebalance_intent: "<REBALANCE_INTENT_PUBKEY>",
541
+ mint_in: "<DEPOSIT_TOKEN_MINT>",
542
+ mint_out: "<WITHDRAW_TOKEN_MINT>",
543
+ amount_in: 1_000_000,
544
+ amount_out: 1_000_000,
545
+ jup_swap_ix: jupiterSwapInstruction,
546
+ jup_token_ledger_ix: jupiterTokenLedgerInstruction,
547
+ jup_address_lookup_table_addresses: [...],
548
+ });
549
+ ```
550
+
551
+ ---
552
+
553
+ ### Minting & Redeeming
554
+
555
+ #### `mintTx(params): Promise<TxPayloadBatchSequence>`
556
+
557
+ Mint vault tokens after a deposit completes its auctions:
558
+
559
+ ```typescript
560
+ const tx = await sdk.mintTx({
561
+ keeper: wallet.publicKey.toBase58(),
562
+ rebalance_intent: "<REBALANCE_INTENT_PUBKEY>",
563
+ });
564
+ ```
565
+
566
+ #### `redeemTokensTx(params): Promise<TxPayloadBatchSequence>`
567
+
568
+ Redeem underlying tokens from a completed withdrawal:
569
+
570
+ ```typescript
571
+ const tx = await sdk.redeemTokensTx({
572
+ keeper: wallet.publicKey.toBase58(),
573
+ rebalance_intent: "<REBALANCE_INTENT_PUBKEY>",
574
+ });
575
+ ```
576
+
577
+ ---
578
+
579
+ ### Bounties
580
+
581
+ #### `addBountyTx(params): Promise<TxPayloadBatchSequence>`
582
+
583
+ Add bounty to a vault for incentivizing keeper automation:
584
+
585
+ ```typescript
586
+ const tx = await sdk.addBountyTx({
587
+ keeper: wallet.publicKey.toBase58(),
588
+ vault: "<VAULT_PUBKEY>",
589
+ amount: 100_000_000, // lamports
590
+ });
591
+ ```
592
+
593
+ #### `claimBountyTx(params): Promise<TxPayloadBatchSequence>`
594
+
595
+ Claim bounty rewards after completing rebalance tasks:
596
+
597
+ ```typescript
598
+ const tx = await sdk.claimBountyTx({
599
+ keeper: wallet.publicKey.toBase58(),
600
+ rebalance_intent: "<REBALANCE_INTENT_PUBKEY>",
601
+ });
602
+ ```
603
+
604
+ ---
605
+
606
+ ### Fee Management
607
+
608
+ #### `withdrawVaultFeesTx(params): Promise<TxPayloadBatchSequence>`
609
+
610
+ Withdraw and claim accumulated fees from a vault. Automatically detects which fee types the claimer is authorized to collect (protocol, creator, host, or manager fees):
611
+
612
+ ```typescript
613
+ const tx = await sdk.withdrawVaultFeesTx({
614
+ claimer: wallet.publicKey.toBase58(),
615
+ vault: "<VAULT_PUBKEY>",
616
+ });
617
+ ```
618
+
619
+ #### `claimTokenFeesFromVaultTx(params): Promise<TxPayloadBatchSequence>`
620
+
621
+ Claim remaining fee tokens from an existing `WithdrawVaultFees` account:
622
+
623
+ ```typescript
624
+ const tx = await sdk.claimTokenFeesFromVaultTx({
625
+ claimer: wallet.publicKey.toBase58(),
626
+ withdrawVaultFees: "<WITHDRAW_VAULT_FEES_PUBKEY>",
627
+ });
628
+ ```
629
+
630
+ ---
631
+
632
+ ### Lookup Tables
633
+
634
+ #### `rewriteLookupTablesTx(params): Promise<TxPayloadBatchSequence>`
635
+
636
+ Rebuild address lookup tables for a vault (needed when LUTs are full after adding tokens):
637
+
638
+ ```typescript
639
+ const tx = await sdk.rewriteLookupTablesTx({
640
+ signer: wallet.publicKey.toBase58(),
641
+ vault_mint: "<VAULT_MINT>",
642
+ additional_accounts: ["<ACCOUNT_1>", "<ACCOUNT_2>"],
643
+ });
644
+ ```
645
+
646
+ ---
647
+
648
+ ### Sending Transactions
649
+
650
+ All transaction-building methods return a `TxPayloadBatchSequence`. Batches are sent sequentially; transactions within a batch are sent in parallel.
651
+
652
+ #### `signAndSendTxPayloadBatchSequence(params): Promise<TransactionSignature[][]>`
653
+
654
+ ```typescript
655
+ const signatures = await sdk.signAndSendTxPayloadBatchSequence({
656
+ txPayloadBatchSequence: tx,
657
+ wallet,
658
+ simulateTransactions: false, // optional
659
+ });
660
+ ```
661
+
662
+ #### `signAndSendVersionedTxs(params): Promise<TransactionSignature[][]>`
663
+
664
+ ```typescript
665
+ const signatures = await sdk.signAndSendVersionedTxs({
666
+ versionedTxs,
667
+ wallet,
668
+ });
669
+ ```
670
+
671
+ ---
672
+
673
+ ## Keeper Monitor (Reference Implementation)
674
+
675
+ `KeeperMonitor` is an example keeper implementation included in the SDK. It provides automated monitoring and execution of all pending protocol tasks.
676
+
677
+ ```typescript
678
+ import { KeeperMonitor } from "@symmetry-hq/sdk";
679
+
680
+ const keeper = new KeeperMonitor({
681
+ wallet, // wallet with signing capability
682
+ connection, // Solana RPC connection
683
+ network: "mainnet",
684
+ jupiterApiKey: "<JUP_API_KEY>",
685
+ maxAllowedAccounts: 64,
686
+ priorityFee: 50_000, // optional
687
+ simulateTransactions: false, // optional
688
+ });
689
+
690
+ while (true) {
691
+ await keeper.update();
692
+ await new Promise(r => setTimeout(r, 10_000));
693
+ }
694
+ ```
695
+
696
+ The keeper automatically monitors and executes pending intents, handles the full rebalance lifecycle (price updates, Jupiter flash swaps, minting, redeeming, bounty claims), and manages concurrent task execution.
697
+
698
+ ---
699
+
700
+ ## Standalone Utilities
701
+
702
+ | Export | Description |
703
+ |--------|-------------|
704
+ | `getJupTokenLedgerAndSwapInstructions` | Build Jupiter swap instructions for flash swaps |
705
+ | `getSwapPairs` | Compute required swap pairs for a rebalance intent |
706
+ | `isRebalanceRequired` | Check whether a vault needs rebalancing based on its threshold settings |
707
+
708
+ ---
709
+
710
+ ## Constants
711
+
712
+ | Constant | Value | Description |
713
+ |----------|-------|-------------|
714
+ | `VAULTS_V3_PROGRAM_ID` | `BASKT7aKd8n7ibpUbwLP3Wiyxyi3yoiXsxBk4Hpumate` | Program address |
715
+ | `COMPUTE_UNITS` | `1,000,000` | Default compute unit limit |
716
+ | `PRIORITY_FEE` | `25,000` | Default priority fee (micro-lamports) |
717
+ | `MAX_SUPPORTED_TOKENS_PER_VAULT` | `100` | Max tokens per vault |
718
+ | `MAX_MANAGERS_PER_VAULT` | `10` | Max managers per vault |
719
+ | `MAX_ORACLES_PER_TOKEN` | `4` | Max oracle sources per token |
720
+ | `HUNDRED_PERCENT_BPS` | `10,000` | 100% in basis points |
721
+
722
+ ## Supported Oracles
723
+
724
+ | Type | Enum | Description |
725
+ |------|------|-------------|
726
+ | Pyth | `0` | Pyth Network price feeds via Hermes ([Price Feed IDs](https://docs.pyth.network/price-feeds/core/price-feeds/price-feed-ids)) |
727
+ | Raydium CLMM | `1` | Raydium Concentrated Liquidity AMM TWAP (currently disabled on-chain) |
728
+ | Raydium CPMM | `2` | Raydium Constant Product AMM TWAP |
729
+ | Switchboard | `3` | Switchboard oracle feeds (currently disabled on-chain) |
730
+
731
+ Each token in a vault supports up to 4 oracle sources with configurable aggregation (e.g. weighted percentile).
732
+
733
+ ## Networks
734
+
735
+ | Network | WSOL Mint | USDC Mint |
736
+ |---------|-----------|-----------|
737
+ | `mainnet` | `So11111111111111111111111111111111111111112` | `EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v` |
738
+ | `devnet` | `So11111111111111111111111111111111111111112` | `USDCoctVLVnvTXBEuP9s8hntucdJokbo17RwHuNXemT` |
739
+
740
+ ## License
741
+
742
+ BUSL-1.1 (Business Source License 1.1)
@@ -0,0 +1,11 @@
1
+ import { BN } from '@coral-xyz/anchor';
2
+ import { PublicKey, TransactionInstruction } from '@solana/web3.js';
3
+ export declare function rebalanceSwapIx(params: {
4
+ keeper: PublicKey;
5
+ basket: PublicKey;
6
+ mintFrom: PublicKey;
7
+ mintTo: PublicKey;
8
+ amountIn: BN;
9
+ amountOut: BN;
10
+ mode: number;
11
+ }): TransactionInstruction;
@@ -0,0 +1,42 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.rebalanceSwapIx = rebalanceSwapIx;
4
+ const spl_token_1 = require("@solana/spl-token");
5
+ const web3_js_1 = require("@solana/web3.js");
6
+ const constants_1 = require("../../constants");
7
+ const pda_1 = require("../pda");
8
+ const REBALANCE_SWAP_DISCRIMINATOR = Buffer.from([101, 122, 61, 201, 21, 165, 177, 213]);
9
+ function rebalanceSwapIx(params) {
10
+ const { keeper, basket, mintFrom, mintTo, amountIn, amountOut, mode } = params;
11
+ let rebalanceIntent = (0, pda_1.getRebalanceIntentPda)(basket, keeper); // TODO: incorrect. Pass intent as func param
12
+ let keeperFromATA = (0, pda_1.getAta)(keeper, mintFrom);
13
+ let keeperToATA = (0, pda_1.getAta)(keeper, mintTo);
14
+ let basketFromATA = (0, pda_1.getAta)(basket, mintFrom);
15
+ let basketToATA = (0, pda_1.getAta)(basket, mintTo);
16
+ const keys = [
17
+ { pubkey: params.keeper, isWritable: true, isSigner: true },
18
+ { pubkey: params.basket, isWritable: true, isSigner: false },
19
+ { pubkey: rebalanceIntent, isWritable: true, isSigner: false },
20
+ { pubkey: params.mintFrom, isWritable: false, isSigner: false },
21
+ { pubkey: params.mintTo, isWritable: false, isSigner: false },
22
+ { pubkey: keeperFromATA, isWritable: true, isSigner: false },
23
+ { pubkey: keeperToATA, isWritable: true, isSigner: false },
24
+ { pubkey: basketFromATA, isWritable: true, isSigner: false },
25
+ { pubkey: basketToATA, isWritable: true, isSigner: false },
26
+ { pubkey: (0, pda_1.getGlobalConfigPda)(), isWritable: false, isSigner: false },
27
+ { pubkey: web3_js_1.SystemProgram.programId, isWritable: false, isSigner: false },
28
+ { pubkey: spl_token_1.TOKEN_PROGRAM_ID, isWritable: false, isSigner: false },
29
+ { pubkey: spl_token_1.TOKEN_2022_PROGRAM_ID, isWritable: false, isSigner: false },
30
+ { pubkey: spl_token_1.ASSOCIATED_TOKEN_PROGRAM_ID, isWritable: false, isSigner: false },
31
+ ];
32
+ const discriminator = REBALANCE_SWAP_DISCRIMINATOR;
33
+ const amountInBuffer = Buffer.from(amountIn.toArray("le", 8));
34
+ const amountOutBuffer = Buffer.from(amountOut.toArray("le", 8));
35
+ const modeBuffer = Buffer.from([mode]);
36
+ const data = Buffer.concat([discriminator, amountInBuffer, amountOutBuffer, modeBuffer]);
37
+ return new web3_js_1.TransactionInstruction({
38
+ keys,
39
+ programId: constants_1.BASKETS_V3_PROGRAM_ID,
40
+ data,
41
+ });
42
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@symmetry-hq/sdk",
3
- "version": "1.0.8",
3
+ "version": "1.0.9",
4
4
  "description": "Symmetry V3 SDK",
5
5
  "main": "dist/src/index.js",
6
6
  "types": "dist/src/index.d.ts",
@@ -14,8 +14,8 @@
14
14
  "vaults",
15
15
  "sdk"
16
16
  ],
17
- "author": "Sandstorm",
18
- "license": "ISC",
17
+ "author": "Symmetry Protocol",
18
+ "license": "BUSL-1.1",
19
19
  "dependencies": {
20
20
  "@coral-xyz/borsh": "^0.31.1",
21
21
  "@pythnetwork/hermes-client": "^2.1.0",
@@ -1,32 +0,0 @@
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
- }
@@ -1,278 +0,0 @@
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;