@symmetry-hq/sdk 1.0.18 → 1.0.20

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.
@@ -356,14 +356,25 @@ function createEditVaultIntentIx(params) {
356
356
  break;
357
357
  case intent_1.TaskType.UpdateWeights: { // 15 - 202
358
358
  const updateWeightsData = editData;
359
- const weights = updateWeightsData.token_weights.slice(0, constants_1.MAX_SUPPORTED_TOKENS_PER_VAULT);
360
- while (weights.length < constants_1.MAX_SUPPORTED_TOKENS_PER_VAULT)
361
- weights.push({ mint: '', weight_bps: 0 });
359
+ const weights = updateWeightsData.token_weights;
362
360
  let tokenMintsHash = (_e = updateWeightsData.token_mints_hash) !== null && _e !== void 0 ? _e : (0, basket_1.computeTokenMintsHash)(vault.composition.slice(0, vault.numTokens)
363
361
  .filter((asset) => asset.active === 1)
364
362
  .map((asset) => asset.mint.toBase58()));
363
+ let tokenWeights = [];
364
+ for (let i = 0; i < constants_1.MAX_SUPPORTED_TOKENS_PER_VAULT; i++) {
365
+ if (i >= vault.numTokens || vault.composition[i].active === 0) {
366
+ tokenWeights.push(0);
367
+ continue;
368
+ }
369
+ let mint = vault.composition[i].mint.toBase58();
370
+ let weight = 0;
371
+ for (let j = 0; j < weights.length; j++)
372
+ if (weights[j].mint === mint)
373
+ weight = weights[j].weight_bps;
374
+ tokenWeights.push(weight);
375
+ }
365
376
  let updateWeights = {
366
- tokenWeights: weights.map((weight) => weight.weight_bps),
377
+ tokenWeights: tokenWeights,
367
378
  tokenMintsHash: tokenMintsHash,
368
379
  };
369
380
  config_1.UpdateWeightsLayout.encode(updateWeights, editDataBuf);
@@ -2,7 +2,7 @@ import BN from 'bn.js';
2
2
  import { Fraction } from './fraction';
3
3
  export declare const MAX_ORACLES_PER_TOKEN = 4;
4
4
  export declare const MAX_ACCOUNTS_PER_ORACLE = 4;
5
- export type FormattedOracleType = "pyth" | "raydium_clmm" | "raydium_cpmm" | "switchboard" | "example";
5
+ export type FormattedOracleType = "pyth" | "raydium_clmm" | "raydium_cpmm" | "lst" | "example";
6
6
  export declare const ORACLE_TYPES_STRINGS: Map<number, FormattedOracleType>;
7
7
  export type FormattedQuote = "usdc" | "wsol" | "usd";
8
8
  export declare const QUOTES_STRINGS: Map<number, FormattedQuote>;
@@ -16,7 +16,7 @@ export declare enum OracleType {
16
16
  Pyth = 0,
17
17
  RaydiumClmm = 1,
18
18
  RaydiumCpmm = 2,
19
- SwitchBoard = 3,
19
+ Lst = 3,
20
20
  Example = 4
21
21
  }
22
22
  export declare enum Quote {
@@ -14,7 +14,7 @@ exports.ORACLE_TYPES_STRINGS = new Map([
14
14
  [0, "pyth"],
15
15
  [1, "raydium_clmm"],
16
16
  [2, "raydium_cpmm"],
17
- [3, "switchboard"],
17
+ [3, "lst"],
18
18
  [255, "example"],
19
19
  ]);
20
20
  exports.QUOTES_STRINGS = new Map([
@@ -33,7 +33,7 @@ var OracleType;
33
33
  OracleType[OracleType["Pyth"] = 0] = "Pyth";
34
34
  OracleType[OracleType["RaydiumClmm"] = 1] = "RaydiumClmm";
35
35
  OracleType[OracleType["RaydiumCpmm"] = 2] = "RaydiumCpmm";
36
- OracleType[OracleType["SwitchBoard"] = 3] = "SwitchBoard";
36
+ OracleType[OracleType["Lst"] = 3] = "Lst";
37
37
  OracleType[OracleType["Example"] = 4] = "Example";
38
38
  })(OracleType || (exports.OracleType = OracleType = {}));
39
39
  ;
@@ -0,0 +1,18 @@
1
+ import BN from 'bn.js';
2
+ import { AccountInfo, PublicKey } from '@solana/web3.js';
3
+ import { OracleSettings } from '../../layouts/oracle';
4
+ import { OraclePrice } from './oracle';
5
+ export declare class StakePool {
6
+ poolMint: PublicKey;
7
+ lamports: BN;
8
+ supply: BN;
9
+ constructor(params: {
10
+ poolMint: PublicKey;
11
+ lamports: BN;
12
+ supply: BN;
13
+ });
14
+ static decode(buf: Buffer, offset?: number): StakePool;
15
+ }
16
+ export declare class LstOracle {
17
+ static fetch(oracleParams: OracleSettings, accountInfos: AccountInfo<Buffer>[], wsolPrice: OraclePrice, usdcPrice: OraclePrice): OraclePrice;
18
+ }
@@ -0,0 +1,58 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.LstOracle = exports.StakePool = void 0;
7
+ const bn_js_1 = __importDefault(require("bn.js"));
8
+ const decimal_js_1 = __importDefault(require("decimal.js"));
9
+ const web3_js_1 = require("@solana/web3.js");
10
+ const constants_1 = require("../../constants");
11
+ const oracle_1 = require("../../layouts/oracle");
12
+ const oracle_2 = require("./oracle");
13
+ // stake pool program IDs (mainnet)
14
+ const STAKE_POOL_PROGRAM_ID = new web3_js_1.PublicKey("SPoo1Ku8WFXoNDMHPsrGSTSG1Y47rzgn41SLUNakuHy");
15
+ const SANCTUM_STAKE_POOL_PROGRAM_ID = new web3_js_1.PublicKey("SP12tWFxD9oJsVWNavTTBZvMbA6gkAmxtVgxdqvyvhY");
16
+ class StakePool {
17
+ constructor(params) {
18
+ this.poolMint = params.poolMint;
19
+ this.lamports = params.lamports;
20
+ this.supply = params.supply;
21
+ }
22
+ static decode(buf, offset = 0) {
23
+ let poolMint = new web3_js_1.PublicKey(buf.subarray(162, 162 + 32));
24
+ let lamports = new bn_js_1.default(buf.subarray(258, 258 + 8), "le");
25
+ let supply = new bn_js_1.default(buf.subarray(266, 266 + 8), "le");
26
+ return new StakePool({
27
+ poolMint,
28
+ lamports,
29
+ supply,
30
+ });
31
+ }
32
+ }
33
+ exports.StakePool = StakePool;
34
+ class LstOracle {
35
+ static fetch(oracleParams, accountInfos, wsolPrice, usdcPrice) {
36
+ //@ts-ignore
37
+ let state = null;
38
+ try {
39
+ const stateAi = accountInfos[0];
40
+ const parsedState = StakePool.decode(stateAi.data, 8);
41
+ state = parsedState;
42
+ }
43
+ catch (error) {
44
+ return new oracle_2.OraclePrice(new decimal_js_1.default(0), new decimal_js_1.default(0), 0);
45
+ }
46
+ let price = new decimal_js_1.default(state.lamports.toString())
47
+ .div(new decimal_js_1.default(state.supply.toString()));
48
+ let quoteDecimals = (oracleParams.quote == oracle_1.Quote.Usdc) ? constants_1.USDC_DECIMALS : ((oracleParams.quote == oracle_1.Quote.Wsol) ? constants_1.WSOL_DECIMALS : 0);
49
+ price = price.mul(decimal_js_1.default.pow(10, quoteDecimals - oracleParams.tokenDecimals));
50
+ let quotePrice = (oracleParams.quote === oracle_1.Quote.Usdc) ? usdcPrice :
51
+ ((oracleParams.quote === oracle_1.Quote.Wsol) ? wsolPrice :
52
+ new oracle_2.OraclePrice(new decimal_js_1.default(1), new decimal_js_1.default(0), 0));
53
+ price = price.mul(quotePrice.price);
54
+ let conf = price.mul(new decimal_js_1.default(oracleParams.confThreshBps)).div(new decimal_js_1.default(constants_1.HUNDRED_PERCENT_BPS));
55
+ return new oracle_2.OraclePrice(price, conf, Date.now(), true);
56
+ }
57
+ }
58
+ exports.LstOracle = LstOracle;
@@ -12,6 +12,7 @@ const constants_2 = require("./constants");
12
12
  const pythOracle_1 = require("./pythOracle");
13
13
  const raydiumClmmOracle_1 = require("./raydiumClmmOracle");
14
14
  const raydiumCpmmOracle_1 = require("./raydiumCpmmOracle");
15
+ const lstOracle_1 = require("./lstOracle");
15
16
  class OraclePrice {
16
17
  constructor(price, conf, updateTime, validated) {
17
18
  this.price = price;
@@ -101,6 +102,8 @@ class PriceAggregator {
101
102
  return raydiumClmmOracle_1.RaydiumCLMMOracle.fetch(settings, loadedAccounts, wsolPrice, usdcPrice);
102
103
  case oracle_1.OracleType.RaydiumCpmm:
103
104
  return raydiumCpmmOracle_1.RaydiumCPMMOracle.fetch(settings, loadedAccounts, wsolPrice, usdcPrice);
105
+ case oracle_1.OracleType.Lst:
106
+ return lstOracle_1.LstOracle.fetch(settings, loadedAccounts, wsolPrice, usdcPrice);
104
107
  default:
105
108
  throw new Error(`Invalid oracle type: ${settings.oracleType}`);
106
109
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@symmetry-hq/sdk",
3
- "version": "1.0.18",
3
+ "version": "1.0.20",
4
4
  "description": "Symmetry V3 SDK",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -442,16 +442,27 @@ export function createEditVaultIntentIx(params: {
442
442
 
443
443
  case TaskType.UpdateWeights: { // 15 - 202
444
444
  const updateWeightsData = (editData as UpdateWeightsInput);
445
- const weights = updateWeightsData.token_weights.slice(0, MAX_SUPPORTED_TOKENS_PER_VAULT);
446
- while (weights.length < MAX_SUPPORTED_TOKENS_PER_VAULT) weights.push({ mint: '', weight_bps: 0 });
447
-
445
+ const weights = updateWeightsData.token_weights;
448
446
  let tokenMintsHash = updateWeightsData.token_mints_hash ?? computeTokenMintsHash(
449
447
  vault.composition.slice(0, vault.numTokens)
450
448
  .filter((asset) => asset.active === 1)
451
449
  .map((asset) => asset.mint.toBase58())
452
450
  );
451
+ let tokenWeights = [];
452
+ for (let i = 0; i < MAX_SUPPORTED_TOKENS_PER_VAULT; i++) {
453
+ if (i >= vault.numTokens || vault.composition[i].active === 0) {
454
+ tokenWeights.push(0);
455
+ continue;
456
+ }
457
+ let mint = vault.composition[i].mint.toBase58();
458
+ let weight = 0;
459
+ for (let j = 0; j < weights.length; j++)
460
+ if (weights[j].mint === mint)
461
+ weight = weights[j].weight_bps;
462
+ tokenWeights.push(weight);
463
+ }
453
464
  let updateWeights: UpdateWeights = {
454
- tokenWeights: weights.map((weight) => weight.weight_bps),
465
+ tokenWeights: tokenWeights,
455
466
  tokenMintsHash: tokenMintsHash,
456
467
  }
457
468
  UpdateWeightsLayout.encode(updateWeights, editDataBuf);
@@ -7,12 +7,12 @@ import { HUNDRED_PERCENT_BPS, USDC_DECIMALS, WSOL_DECIMALS } from '../constants'
7
7
  export const MAX_ORACLES_PER_TOKEN = 4;
8
8
  export const MAX_ACCOUNTS_PER_ORACLE = 4;
9
9
 
10
- export type FormattedOracleType = "pyth" | "raydium_clmm" | "raydium_cpmm" | "switchboard" | "example";
10
+ export type FormattedOracleType = "pyth" | "raydium_clmm" | "raydium_cpmm" | "lst" | "example";
11
11
  export const ORACLE_TYPES_STRINGS: Map<number, FormattedOracleType> = new Map([
12
12
  [0, "pyth"],
13
13
  [1, "raydium_clmm"],
14
14
  [2, "raydium_cpmm"],
15
- [3, "switchboard"],
15
+ [3, "lst"],
16
16
  [255, "example"],
17
17
  ]);
18
18
 
@@ -40,7 +40,7 @@ export enum OracleType {
40
40
  Pyth = 0,
41
41
  RaydiumClmm = 1,
42
42
  RaydiumCpmm = 2,
43
- SwitchBoard = 3,
43
+ Lst = 3,
44
44
  Example = 4,
45
45
  };
46
46
 
@@ -0,0 +1,78 @@
1
+ import BN from 'bn.js';
2
+ import Decimal from 'decimal.js';
3
+ import { AccountInfo, PublicKey } from '@solana/web3.js';
4
+
5
+ import { HUNDRED_PERCENT_BPS, USDC_DECIMALS, WSOL_DECIMALS } from '../../constants';
6
+ import { OracleSettings, OracleType, Quote } from '../../layouts/oracle';
7
+ import { OraclePrice } from './oracle';
8
+
9
+ // stake pool program IDs (mainnet)
10
+ const STAKE_POOL_PROGRAM_ID = new PublicKey("SPoo1Ku8WFXoNDMHPsrGSTSG1Y47rzgn41SLUNakuHy");
11
+ const SANCTUM_STAKE_POOL_PROGRAM_ID = new PublicKey("SP12tWFxD9oJsVWNavTTBZvMbA6gkAmxtVgxdqvyvhY");
12
+
13
+ export class StakePool {
14
+ poolMint: PublicKey;
15
+ lamports: BN; // u64
16
+ supply: BN; // u64
17
+
18
+ constructor(params: {
19
+ poolMint: PublicKey,
20
+ lamports: BN,
21
+ supply: BN,
22
+ }) {
23
+ this.poolMint = params.poolMint;
24
+ this.lamports = params.lamports;
25
+ this.supply = params.supply;
26
+ }
27
+
28
+ static decode(buf: Buffer, offset: number = 0): StakePool {
29
+ let poolMint = new PublicKey(buf.subarray(162, 162 + 32));
30
+ let lamports = new BN(buf.subarray(258, 258 + 8), "le");
31
+ let supply = new BN(buf.subarray(266, 266 + 8), "le");
32
+
33
+ return new StakePool({
34
+ poolMint,
35
+ lamports,
36
+ supply,
37
+ })
38
+ }
39
+ }
40
+
41
+ export class LstOracle {
42
+
43
+ static fetch(
44
+ oracleParams: OracleSettings,
45
+ accountInfos: AccountInfo<Buffer>[],
46
+ wsolPrice: OraclePrice,
47
+ usdcPrice: OraclePrice,
48
+ ): OraclePrice {
49
+ //@ts-ignore
50
+ let state: StakePool = null;
51
+ try {
52
+ const stateAi = accountInfos[0];
53
+ const parsedState = StakePool.decode(stateAi.data, 8);
54
+ state = parsedState;
55
+ } catch (error) {
56
+ return new OraclePrice(new Decimal(0), new Decimal(0), 0);
57
+ }
58
+
59
+ let price = new Decimal(state.lamports.toString())
60
+ .div(new Decimal(state.supply.toString()));
61
+
62
+ let quoteDecimals =
63
+ (oracleParams.quote == Quote.Usdc) ? USDC_DECIMALS : (
64
+ (oracleParams.quote == Quote.Wsol) ? WSOL_DECIMALS : 0);
65
+ price = price.mul(Decimal.pow(10, quoteDecimals - oracleParams.tokenDecimals));
66
+
67
+ let quotePrice =
68
+ (oracleParams.quote === Quote.Usdc) ? usdcPrice :
69
+ ((oracleParams.quote === Quote.Wsol) ? wsolPrice :
70
+ new OraclePrice(new Decimal(1), new Decimal(0), 0));
71
+ price = price.mul(quotePrice.price);
72
+
73
+ let conf = price.mul(new Decimal(oracleParams.confThreshBps)).div(new Decimal(HUNDRED_PERCENT_BPS));
74
+
75
+ return new OraclePrice(price, conf, Date.now(), true);
76
+ }
77
+
78
+ }
@@ -15,6 +15,7 @@ import {
15
15
  RaydiumCLMMOracle
16
16
  } from './raydiumClmmOracle';
17
17
  import { RaydiumCPMMOracle } from './raydiumCpmmOracle';
18
+ import { LstOracle } from './lstOracle';
18
19
 
19
20
  export class OraclePrice {
20
21
  price: Decimal;
@@ -134,6 +135,8 @@ export class PriceAggregator{
134
135
  return RaydiumCLMMOracle.fetch(settings, loadedAccounts, wsolPrice, usdcPrice);
135
136
  case OracleType.RaydiumCpmm:
136
137
  return RaydiumCPMMOracle.fetch(settings, loadedAccounts, wsolPrice, usdcPrice);
138
+ case OracleType.Lst:
139
+ return LstOracle.fetch(settings, loadedAccounts, wsolPrice, usdcPrice);
137
140
  default:
138
141
  throw new Error(`Invalid oracle type: ${settings.oracleType}`);
139
142
  }
package/test.ts CHANGED
@@ -322,7 +322,7 @@ async function testStates() {
322
322
 
323
323
  if (tests.addOrEditToken) {
324
324
  let add_token: AddOrEditTokenInput = {
325
- token_mint: "XsoCS1TfEyfFhfvj8EtZ528L3CaKBDBRqRapnBbDF2W",
325
+ token_mint: "J1toso1uCk3RLmjorhTtrVwY9HJ7X8V9yYac6Y7kGCPn",
326
326
  active: true,
327
327
  min_oracles_thresh: 1,
328
328
  min_conf_bps: 50,
@@ -330,14 +330,14 @@ async function testStates() {
330
330
  conf_multiplier: 1,
331
331
  oracles: [
332
332
  {
333
- oracle_type: "raydium_clmm",
333
+ oracle_type: "lst",
334
334
  account_lut_id: 0,
335
335
  account_lut_index: 0,
336
- account: "6truu3rZuiB9rKQg4VYC3Dt3QwV7DgwGqXrYUcrvnDDE",
336
+ account: "Jito4APyf642JPZPx3hGc6WWJ8zPKtRbRs4P815Awbb",
337
337
  weight_bps: 5000,
338
338
  is_required: false,
339
- conf_thresh_bps: 200,
340
- volatility_thresh_bps: 200,
339
+ conf_thresh_bps: 100,
340
+ volatility_thresh_bps: 100,
341
341
  max_slippage_bps: 100,
342
342
  min_liquidity: 0,
343
343
  staleness_thresh: 120,
@@ -348,10 +348,10 @@ async function testStates() {
348
348
  quote_token: "wsol",
349
349
  },
350
350
  {
351
- oracle_type: "raydium_clmm",
351
+ oracle_type: "pyth",
352
352
  account_lut_id: 0,
353
353
  account_lut_index: 0,
354
- account: "4pCZCVEiYyT4efNdXUdL2tJF8VGMgiMXrZWq6FiNXhRw",
354
+ account: "AxaxyeDT8JnWERSaTKvFXvPKkEdxnamKSqpWbsSjYg1g",
355
355
  weight_bps: 5000,
356
356
  is_required: false,
357
357
  conf_thresh_bps: 200,
@@ -363,7 +363,7 @@ async function testStates() {
363
363
  token_decimals: 9,
364
364
  twap_seconds_ago: 50,
365
365
  twap_secondary_seconds_ago: 100,
366
- quote_token: "wsol",
366
+ quote_token: "usd",
367
367
  },
368
368
  ],
369
369
  };
@@ -377,11 +377,24 @@ async function testStates() {
377
377
  token_weights: [
378
378
  {
379
379
  mint: "So11111111111111111111111111111111111111112",
380
- weight_bps: 100,
380
+ weight_bps: 2000,
381
381
  },
382
- ],
383
- token_mints_hash: [
384
- 0, 0, 0, 0,
382
+ {
383
+ mint: "cbbtcf3aa214zXHbiAZQwf4122FBYbraNdFqgw4iMij",
384
+ weight_bps: 2500,
385
+ },
386
+ {
387
+ mint: "XsoCS1TfEyfFhfvj8EtZ528L3CaKBDBRqRapnBbDF2W",
388
+ weight_bps: 2500,
389
+ },
390
+ {
391
+ mint: "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
392
+ weight_bps: 1000,
393
+ },
394
+ {
395
+ mint: "J1toso1uCk3RLmjorhTtrVwY9HJ7X8V9yYac6Y7kGCPn",
396
+ weight_bps: 2000,
397
+ }
385
398
  ],
386
399
  };
387
400
  let tx = await sdk.updateWeightsTx(task_context, update_weights);