@symmetry-hq/temp-v3-sdk 0.0.1

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.
Files changed (148) hide show
  1. package/dist/idl/idl.d.ts +8 -0
  2. package/dist/idl/idl.js +4958 -0
  3. package/dist/idl/types.d.ts +4955 -0
  4. package/dist/idl/types.js +2 -0
  5. package/dist/index.d.ts +24 -0
  6. package/dist/index.js +60 -0
  7. package/dist/layouts/basket.d.ts +42 -0
  8. package/dist/layouts/basket.js +43 -0
  9. package/dist/layouts/config.d.ts +97 -0
  10. package/dist/layouts/config.js +102 -0
  11. package/dist/layouts/fraction.d.ts +6 -0
  12. package/dist/layouts/fraction.js +9 -0
  13. package/dist/layouts/oracle.d.ts +36 -0
  14. package/dist/layouts/oracle.js +37 -0
  15. package/dist/src/constants.d.ts +15 -0
  16. package/dist/src/constants.js +19 -0
  17. package/dist/src/idl/idl.d.ts +8 -0
  18. package/dist/src/idl/idl.js +4958 -0
  19. package/dist/src/idl/types.d.ts +4955 -0
  20. package/dist/src/idl/types.js +2 -0
  21. package/dist/src/index.d.ts +53 -0
  22. package/dist/src/index.js +199 -0
  23. package/dist/src/instructions/accounts.d.ts +27 -0
  24. package/dist/src/instructions/accounts.js +110 -0
  25. package/dist/src/instructions/auction.d.ts +7 -0
  26. package/dist/src/instructions/auction.js +43 -0
  27. package/dist/src/instructions/automation/auction.d.ts +6 -0
  28. package/dist/src/instructions/automation/auction.js +40 -0
  29. package/dist/src/instructions/automation/claimBounty.d.ts +12 -0
  30. package/dist/src/instructions/automation/claimBounty.js +44 -0
  31. package/dist/src/instructions/automation/priceUpdate.d.ts +15 -0
  32. package/dist/src/instructions/automation/priceUpdate.js +47 -0
  33. package/dist/src/instructions/automation/rebalanceSwap.d.ts +10 -0
  34. package/dist/src/instructions/automation/rebalanceSwap.js +42 -0
  35. package/dist/src/instructions/basket.d.ts +120 -0
  36. package/dist/src/instructions/basket.js +622 -0
  37. package/dist/src/instructions/bounty.d.ts +18 -0
  38. package/dist/src/instructions/bounty.js +81 -0
  39. package/dist/src/instructions/fee.d.ts +8 -0
  40. package/dist/src/instructions/fee.js +46 -0
  41. package/dist/src/instructions/globalConfig.d.ts +11 -0
  42. package/dist/src/instructions/globalConfig.js +43 -0
  43. package/dist/src/instructions/luts.d.ts +33 -0
  44. package/dist/src/instructions/luts.js +91 -0
  45. package/dist/src/instructions/management/addBounty.d.ts +7 -0
  46. package/dist/src/instructions/management/addBounty.js +39 -0
  47. package/dist/src/instructions/management/admin.d.ts +9 -0
  48. package/dist/src/instructions/management/admin.js +43 -0
  49. package/dist/src/instructions/management/claimFees.d.ts +7 -0
  50. package/dist/src/instructions/management/claimFees.js +47 -0
  51. package/dist/src/instructions/management/createBasket.d.ts +22 -0
  52. package/dist/src/instructions/management/createBasket.js +101 -0
  53. package/dist/src/instructions/management/edit.d.ts +34 -0
  54. package/dist/src/instructions/management/edit.js +192 -0
  55. package/dist/src/instructions/management/luts.d.ts +29 -0
  56. package/dist/src/instructions/management/luts.js +88 -0
  57. package/dist/src/instructions/pda.d.ts +26 -0
  58. package/dist/src/instructions/pda.js +110 -0
  59. package/dist/src/instructions/price.d.ts +17 -0
  60. package/dist/src/instructions/price.js +47 -0
  61. package/dist/src/instructions/user/deposit.d.ts +32 -0
  62. package/dist/src/instructions/user/deposit.js +168 -0
  63. package/dist/src/instructions/user/withdraw.d.ts +16 -0
  64. package/dist/src/instructions/user/withdraw.js +82 -0
  65. package/dist/src/layouts/basket.d.ts +41 -0
  66. package/dist/src/layouts/basket.js +43 -0
  67. package/dist/src/layouts/config.d.ts +133 -0
  68. package/dist/src/layouts/config.js +137 -0
  69. package/dist/src/layouts/fraction.d.ts +6 -0
  70. package/dist/src/layouts/fraction.js +9 -0
  71. package/dist/src/layouts/intents/bounty.d.ts +18 -0
  72. package/dist/src/layouts/intents/bounty.js +19 -0
  73. package/dist/src/layouts/intents/intent.d.ts +101 -0
  74. package/dist/src/layouts/intents/intent.js +113 -0
  75. package/dist/src/layouts/intents/rebalanceIntent.d.ts +56 -0
  76. package/dist/src/layouts/intents/rebalanceIntent.js +63 -0
  77. package/dist/src/layouts/lookupTable.d.ts +7 -0
  78. package/dist/src/layouts/lookupTable.js +10 -0
  79. package/dist/src/layouts/oracle.d.ts +42 -0
  80. package/dist/src/layouts/oracle.js +43 -0
  81. package/dist/src/states/basket.d.ts +8 -0
  82. package/dist/src/states/basket.js +54 -0
  83. package/dist/src/states/intents/intent.d.ts +14 -0
  84. package/dist/src/states/intents/intent.js +90 -0
  85. package/dist/src/states/intents/rebalanceIntent.d.ts +8 -0
  86. package/dist/src/states/intents/rebalanceIntent.js +54 -0
  87. package/dist/src/states/oracles/clmm_oracle.d.ts +178 -0
  88. package/dist/src/states/oracles/clmm_oracle.js +546 -0
  89. package/dist/src/states/oracles/constants.d.ts +8 -0
  90. package/dist/src/states/oracles/constants.js +12 -0
  91. package/dist/src/states/oracles/oracle.d.ts +60 -0
  92. package/dist/src/states/oracles/oracle.js +237 -0
  93. package/dist/src/states/oracles/pythOracle.d.ts +39 -0
  94. package/dist/src/states/oracles/pythOracle.js +202 -0
  95. package/dist/src/states/oracles/pyth_oracle.d.ts +39 -0
  96. package/dist/src/states/oracles/pyth_oracle.js +202 -0
  97. package/dist/src/states/oracles/raydiumClmmOracle.d.ts +178 -0
  98. package/dist/src/states/oracles/raydiumClmmOracle.js +546 -0
  99. package/dist/src/states/oracles/raydiumCpmmOracle.d.ts +139 -0
  100. package/dist/src/states/oracles/raydiumCpmmOracle.js +420 -0
  101. package/dist/src/states/oracles/raydium_cpmm_oracle.d.ts +139 -0
  102. package/dist/src/states/oracles/raydium_cpmm_oracle.js +420 -0
  103. package/dist/src/states/oracles/switchboardOracle.d.ts +0 -0
  104. package/dist/src/states/oracles/switchboardOracle.js +1 -0
  105. package/dist/src/states/oracles/switchboard_oracle.d.ts +0 -0
  106. package/dist/src/states/oracles/switchboard_oracle.js +1 -0
  107. package/dist/src/txUtils.d.ts +26 -0
  108. package/dist/src/txUtils.js +183 -0
  109. package/dist/states/basket.d.ts +8 -0
  110. package/dist/states/basket.js +57 -0
  111. package/dist/test.d.ts +1 -0
  112. package/dist/test.js +39 -0
  113. package/package.json +30 -0
  114. package/src/constants.ts +24 -0
  115. package/src/index.ts +260 -0
  116. package/src/instructions/automation/auction.ts +55 -0
  117. package/src/instructions/automation/claimBounty.ts +69 -0
  118. package/src/instructions/automation/priceUpdate.ts +73 -0
  119. package/src/instructions/automation/rebalanceSwap.ts +60 -0
  120. package/src/instructions/management/addBounty.ts +56 -0
  121. package/src/instructions/management/admin.ts +65 -0
  122. package/src/instructions/management/claimFees.ts +59 -0
  123. package/src/instructions/management/createBasket.ts +148 -0
  124. package/src/instructions/management/edit.ts +255 -0
  125. package/src/instructions/management/luts.ts +134 -0
  126. package/src/instructions/pda.ts +160 -0
  127. package/src/instructions/user/deposit.ts +237 -0
  128. package/src/instructions/user/withdraw.ts +130 -0
  129. package/src/layouts/basket.ts +82 -0
  130. package/src/layouts/config.ts +301 -0
  131. package/src/layouts/fraction.ts +12 -0
  132. package/src/layouts/intents/bounty.ts +35 -0
  133. package/src/layouts/intents/intent.ts +204 -0
  134. package/src/layouts/intents/rebalanceIntent.ts +111 -0
  135. package/src/layouts/lookupTable.ts +14 -0
  136. package/src/layouts/oracle.ts +96 -0
  137. package/src/states/basket.ts +56 -0
  138. package/src/states/intents/intent.ts +107 -0
  139. package/src/states/intents/rebalanceIntent.ts +57 -0
  140. package/src/states/oracles/constants.ts +13 -0
  141. package/src/states/oracles/oracle.ts +260 -0
  142. package/src/states/oracles/pythOracle.ts +270 -0
  143. package/src/states/oracles/raydiumClmmOracle.ts +812 -0
  144. package/src/states/oracles/raydiumCpmmOracle.ts +614 -0
  145. package/src/states/oracles/switchboardOracle.ts +0 -0
  146. package/src/txUtils.ts +250 -0
  147. package/test.ts +30 -0
  148. package/tsconfig.json +101 -0
@@ -0,0 +1,237 @@
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
+ var __importDefault = (this && this.__importDefault) || function (mod) {
12
+ return (mod && mod.__esModule) ? mod : { "default": mod };
13
+ };
14
+ Object.defineProperty(exports, "__esModule", { value: true });
15
+ exports.OracleAggregator = exports.Oracle = exports.OracleResult = exports.OraclePrice = exports.OracleErrors = exports.ErrorCode = void 0;
16
+ const decimal_js_1 = __importDefault(require("decimal.js"));
17
+ const anchor_1 = require("@coral-xyz/anchor");
18
+ const constants_1 = require("./constants");
19
+ var ErrorCode;
20
+ (function (ErrorCode) {
21
+ ErrorCode[ErrorCode["NONE"] = 0] = "NONE";
22
+ // Basic Errors –––––––––––––––––––––
23
+ ErrorCode[ErrorCode["INVALID_PRICE"] = 1] = "INVALID_PRICE";
24
+ ErrorCode[ErrorCode["TOO_VOLATILE"] = 2] = "TOO_VOLATILE";
25
+ ErrorCode[ErrorCode["TOO_UNCERTAIN"] = 4] = "TOO_UNCERTAIN";
26
+ ErrorCode[ErrorCode["STALE"] = 8] = "STALE";
27
+ ErrorCode[ErrorCode["NOT_ENOUGH_LIQUIDITY"] = 16] = "NOT_ENOUGH_LIQUIDITY";
28
+ ErrorCode[ErrorCode["NOT_ENABLED"] = 32] = "NOT_ENABLED";
29
+ // Aggregation errors –––––––––––––––
30
+ ErrorCode[ErrorCode["NOT_ENOUGH_ORACLES"] = 64] = "NOT_ENOUGH_ORACLES";
31
+ ErrorCode[ErrorCode["MISSING_REQUIRED_ORACLES"] = 128] = "MISSING_REQUIRED_ORACLES";
32
+ })(ErrorCode || (exports.ErrorCode = ErrorCode = {}));
33
+ class OracleErrors extends Error {
34
+ constructor(code, message) {
35
+ super(message !== null && message !== void 0 ? message : ErrorCode[code]);
36
+ this.name = "OracleErrors";
37
+ this.code = code;
38
+ }
39
+ ;
40
+ }
41
+ exports.OracleErrors = OracleErrors;
42
+ OracleErrors.NONE = new OracleErrors(ErrorCode.NONE);
43
+ OracleErrors.INVALID_PRICE = new OracleErrors(ErrorCode.INVALID_PRICE);
44
+ OracleErrors.TOO_VOLATILE = new OracleErrors(ErrorCode.TOO_VOLATILE);
45
+ OracleErrors.TOO_UNCERTAIN = new OracleErrors(ErrorCode.TOO_UNCERTAIN);
46
+ OracleErrors.STALE = new OracleErrors(ErrorCode.STALE);
47
+ OracleErrors.NOT_ENOUGH_LIQUIDITY = new OracleErrors(ErrorCode.NOT_ENOUGH_LIQUIDITY);
48
+ OracleErrors.NOT_ENABLED = new OracleErrors(ErrorCode.NOT_ENABLED);
49
+ OracleErrors.NOT_ENOUGH_ORACLES = new OracleErrors(ErrorCode.NOT_ENOUGH_ORACLES);
50
+ OracleErrors.MISSING_REQUIRED_ORACLES = new OracleErrors(ErrorCode.NOT_ENABLED);
51
+ class OraclePrice {
52
+ constructor(price, conf, updateTime) {
53
+ this.price = new decimal_js_1.default(price);
54
+ this.conf = new decimal_js_1.default(conf);
55
+ this.updateTime = updateTime;
56
+ this.mid = this.price;
57
+ this.low = this.price.sub(this.conf);
58
+ this.high = this.price.add(this.conf);
59
+ let zero_Decimal = new decimal_js_1.default(0);
60
+ if (this.price.lte(zero_Decimal))
61
+ throw new Error("price should be more than 0");
62
+ if (this.conf.lt(zero_Decimal))
63
+ throw new Error("confidence can't be negative");
64
+ if (this.updateTime.lte(0))
65
+ throw new Error("update time should be more than 0");
66
+ }
67
+ }
68
+ exports.OraclePrice = OraclePrice;
69
+ class OracleResult {
70
+ constructor(price, error) {
71
+ this.error = OracleErrors.NONE;
72
+ this.price = price;
73
+ this.error = error !== null && error !== void 0 ? error : OracleErrors.NONE;
74
+ }
75
+ ok() {
76
+ return this.error === OracleErrors.NONE;
77
+ }
78
+ }
79
+ exports.OracleResult = OracleResult;
80
+ class Oracle {
81
+ constructor(weight, confThreshBps, stalenessThresh, volatilityThresh, minLiquidity, stalenessConfRateBps) {
82
+ this.weight = 1;
83
+ this.confThreshBps = 1500;
84
+ this.stalenessThresh = 60;
85
+ this.volatilityThresh = new decimal_js_1.default(5);
86
+ this.minLiquidity = new decimal_js_1.default(0);
87
+ this.stalenessConfRateBps = 0;
88
+ this.weight = weight;
89
+ this.confThreshBps = confThreshBps !== null && confThreshBps !== void 0 ? confThreshBps : 1500;
90
+ this.stalenessThresh = stalenessThresh !== null && stalenessThresh !== void 0 ? stalenessThresh : 60;
91
+ this.volatilityThresh = new decimal_js_1.default(volatilityThresh !== null && volatilityThresh !== void 0 ? volatilityThresh : 5);
92
+ this.minLiquidity = new decimal_js_1.default(minLiquidity !== null && minLiquidity !== void 0 ? minLiquidity : 0);
93
+ this.stalenessConfRateBps = stalenessConfRateBps !== null && stalenessConfRateBps !== void 0 ? stalenessConfRateBps : 0;
94
+ if (!(0 <= this.weight && new anchor_1.BN(this.weight).lte(constants_1.U32_MAX)))
95
+ throw Error(`Weight must be between 0 and ${constants_1.U32_MAX.toString()}`);
96
+ if (!(0 <= this.confThreshBps && this.confThreshBps < 10000))
97
+ throw Error(`Confidence threshold must be between 0 and 10000`);
98
+ if (!(0 <= this.stalenessConfRateBps && new anchor_1.BN(this.stalenessConfRateBps).lt(constants_1.U32_MAX)))
99
+ throw Error(`Staleness confidence rate must be between 0 and ${constants_1.U32_MAX.toString()}`);
100
+ if (!(new decimal_js_1.default(1).lte(this.volatilityThresh) && this.volatilityThresh.lte(new decimal_js_1.default(constants_1.U32_MAX.toString()))))
101
+ throw Error(`Volatility threshold must be between 1 and ${constants_1.U32_MAX.toString()}`);
102
+ if (!(new decimal_js_1.default(0).lte(this.minLiquidity) && this.minLiquidity.lte(new decimal_js_1.default(constants_1.U64_MAX.toString()))))
103
+ throw Error(`Minimum liquidity must be between 0 and ${constants_1.U64_MAX.toString()}`);
104
+ if (!(0 <= this.stalenessThresh && this.stalenessThresh <= 10000))
105
+ throw Error(`Staleness threshold must be between 0 and 10000`);
106
+ }
107
+ }
108
+ exports.Oracle = Oracle;
109
+ class OracleAggregator {
110
+ constructor(oracles, requiredOracles, minConfBps = 0, confThreshBps = 0, minOraclesThresh = 0) {
111
+ this.minConfBps = 0;
112
+ this.confThreshBps = 0;
113
+ this.minOraclesThresh = 0;
114
+ this.oracles = oracles;
115
+ this.requiredOracles = requiredOracles;
116
+ this.minConfBps = minConfBps;
117
+ this.confThreshBps = confThreshBps;
118
+ this.minOraclesThresh = minOraclesThresh;
119
+ if (!(this.oracles.length > 0))
120
+ throw new Error(`At least one oracle is required`);
121
+ if (!(0 <= this.minConfBps && this.minConfBps < 10000))
122
+ throw new Error(`Minimum confidence must be between 0 and 10000`);
123
+ if (!(0 <= this.confThreshBps && this.confThreshBps < 10000))
124
+ throw new Error(`Confidence threshold must be between 0 and 10000`);
125
+ if (!(0 <= this.minOraclesThresh && new anchor_1.BN(this.minOraclesThresh).lte(constants_1.U32_MAX)))
126
+ throw new Error(`Minimum number of oracles must be between 0 and ${constants_1.U32_MAX}`);
127
+ }
128
+ fetch() {
129
+ return __awaiter(this, void 0, void 0, function* () {
130
+ console.log("Fetching price from oracle aggregator");
131
+ let prices = Array(0);
132
+ let weights = Array(0);
133
+ for (let i = 0; i < this.oracles.length; i++) {
134
+ try {
135
+ let result = yield this.oracles[i].fetch();
136
+ if (result.ok()) {
137
+ prices.push(result.price);
138
+ weights.push(new decimal_js_1.default(this.oracles[i].weight));
139
+ }
140
+ else {
141
+ if (this.requiredOracles.includes(this.oracles[i])) {
142
+ return new OracleResult(null, OracleErrors.MISSING_REQUIRED_ORACLES);
143
+ }
144
+ }
145
+ }
146
+ catch (_a) {
147
+ throw new Error("Unexpected error occured while fetching prices");
148
+ }
149
+ }
150
+ if (prices.length <= this.minOraclesThresh)
151
+ return new OracleResult(null, OracleErrors.NOT_ENOUGH_ORACLES);
152
+ let allPrices = Array(0);
153
+ let allWeights = Array(0);
154
+ let frac3 = new decimal_js_1.default(3);
155
+ prices.map((price, i) => {
156
+ var _a, _b, _c;
157
+ allPrices.push((_a = price === null || price === void 0 ? void 0 : price.mid) !== null && _a !== void 0 ? _a : null, (_b = price === null || price === void 0 ? void 0 : price.low) !== null && _b !== void 0 ? _b : null, (_c = price === null || price === void 0 ? void 0 : price.high) !== null && _c !== void 0 ? _c : null);
158
+ let w = weights[i].div(frac3);
159
+ allWeights.push(w, w, w);
160
+ });
161
+ let medianPrice = weightedMedian(allPrices, allWeights);
162
+ let p25Price = weightedPercentile(allPrices, allWeights, 25);
163
+ let p75Price = weightedPercentile(allPrices, allWeights, 75);
164
+ console.log("Median price: ", medianPrice.toString());
165
+ console.log("P25 price: ", p25Price.toString());
166
+ console.log("P75 price: ", p75Price.toString());
167
+ let first = medianPrice.sub(p25Price);
168
+ let second = p75Price.sub(medianPrice);
169
+ let conf = first.gte(second) ? first : second;
170
+ conf = conf.lte(medianPrice) ? conf : medianPrice;
171
+ if (conf.div(medianPrice).lt(this.minConfBps)) {
172
+ conf = medianPrice.mul(this.minConfBps);
173
+ }
174
+ ;
175
+ if (conf.div(medianPrice).gt(this.confThreshBps)) {
176
+ return new OracleResult(null, OracleErrors.TOO_UNCERTAIN);
177
+ }
178
+ const times = prices.filter((p) => p !== null) // drop nulls
179
+ .map(p => p.updateTime);
180
+ let oldestPriceTime = Math.min(...times);
181
+ return new OracleResult(new OraclePrice(medianPrice, conf, oldestPriceTime));
182
+ });
183
+ }
184
+ }
185
+ exports.OracleAggregator = OracleAggregator;
186
+ function weightedMedian(values, weights) {
187
+ return weightedPercentile(values, weights = weights, 50);
188
+ }
189
+ function weightedPercentile(values, weights, percentile) {
190
+ if (percentile < 0 || percentile > 100) {
191
+ throw new Error("Percentile must be between 0 and 100");
192
+ }
193
+ if (!values || values.length === 0) {
194
+ throw new Error("Prices list is empty");
195
+ }
196
+ if (weights.length !== values.length) {
197
+ throw new Error("Weights and prices must have the same length");
198
+ }
199
+ if (weights.some((w) => w.lt(0))) {
200
+ throw new Error("Weights must be non-negative");
201
+ }
202
+ if (weights.every((w) => w.eq(0))) {
203
+ throw new Error("Weights must be non-zero");
204
+ }
205
+ // Filter out null prices along with their weights
206
+ const arr = [];
207
+ for (let i = 0; i < values.length; i++) {
208
+ const p = values[i];
209
+ if (p !== null) {
210
+ arr.push({ price: p, weight: weights[i] });
211
+ }
212
+ }
213
+ if (arr.length === 0) {
214
+ throw new Error("All prices are null");
215
+ }
216
+ // Sort by price ascending
217
+ arr.sort((a, b) => a.price.sub(b.price).toNumber());
218
+ // Edge cases
219
+ if (percentile === 0)
220
+ return arr[0].price;
221
+ if (percentile === 100)
222
+ return arr[arr.length - 1].price;
223
+ // Compute total weight
224
+ const totalWeight = arr.reduce((sum, x) => sum.add(x.weight), new decimal_js_1.default(0));
225
+ // Threshold = percentile% of total weight
226
+ const thresh = totalWeight.mul(new decimal_js_1.default(percentile));
227
+ // Cumulative sum
228
+ let cum = new decimal_js_1.default(0);
229
+ for (const { price, weight } of arr) {
230
+ cum = cum.add(weight);
231
+ if (cum.gte(thresh)) {
232
+ return price; // nearest-rank percentile
233
+ }
234
+ }
235
+ // fallback (should not happen, but safe)
236
+ return arr[arr.length - 1].price;
237
+ }
@@ -0,0 +1,39 @@
1
+ import { Decimal } from 'decimal.js';
2
+ import { AnchorProvider, BN, Wallet } from '@coral-xyz/anchor';
3
+ import { HermesClient } from '@pythnetwork/hermes-client';
4
+ import { Connection, PublicKey, Signer, TransactionSignature, VersionedTransaction } from '@solana/web3.js';
5
+ import { Oracle, OracleResult } from './oracle';
6
+ interface PythState {
7
+ price: BN;
8
+ conf: BN;
9
+ expo: number;
10
+ publishTime: BN;
11
+ }
12
+ export declare class PythOracle extends Oracle {
13
+ priceFeedAccount: PublicKey;
14
+ state: PythState;
15
+ connection: Connection;
16
+ priceClient: HermesClient;
17
+ priceFeedId: string;
18
+ private constructor();
19
+ static create(connection: Connection | undefined, priceFeedAccount: PublicKey, weight: number, priceClient?: HermesClient, confThreshBps?: number, stalenessThresh?: number, volatilityThresh?: Decimal, minLiquidity?: Decimal, stalenessConfRateBps?: number): Promise<PythOracle>;
20
+ static createWithId(connection: Connection | undefined, priceFeedId: string, wallet: Wallet, weight: number, priceClient?: HermesClient, confThreshBps?: number, stalenessThresh?: number, volatilityThresh?: Decimal, minLiquidity?: Decimal, stalenessConfRateBps?: number): Promise<PythOracle>;
21
+ getConfidence(): Decimal;
22
+ setPriceFeedId(priceFeedId: string): void;
23
+ fetch(): Promise<OracleResult>;
24
+ fetchPriceFromHermes(priceFeedId: string): Promise<PythState>;
25
+ /**
26
+ * Get parsed baskets by manager. Uses 10 paralel rpc calls so might get heavy. Should set feedDd before running this
27
+ * @param {number} shardId - between 0-2^64, default is 0
28
+ * @param {number} [computeUnitPrice] - compute unit price in microlamports, default is 100_000
29
+ */
30
+ updateFeedTx(wallet: Wallet, shardId?: number, computeUnitPrice?: number): Promise<{
31
+ tx: VersionedTransaction;
32
+ signers: Signer[];
33
+ }[]>;
34
+ sendUpdateTx(provider: AnchorProvider, updateFeedTx: {
35
+ tx: VersionedTransaction;
36
+ signers: Signer[];
37
+ }[]): Promise<TransactionSignature[]>;
38
+ }
39
+ export {};
@@ -0,0 +1,202 @@
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.PythOracle = void 0;
13
+ const decimal_js_1 = require("decimal.js");
14
+ const anchor_1 = require("@coral-xyz/anchor");
15
+ const hermes_client_1 = require("@pythnetwork/hermes-client");
16
+ const pyth_solana_receiver_1 = require("@pythnetwork/pyth-solana-receiver");
17
+ const web3_js_1 = require("@solana/web3.js");
18
+ const constants_1 = require("./constants");
19
+ const oracle_1 = require("./oracle");
20
+ ;
21
+ class PythOracle extends oracle_1.Oracle {
22
+ constructor(priceFeedAccount, connection, priceClient, state, weight, confThreshBps, stalenessThresh, volatilityThresh, minLiquidity, stalenessConfRateBps) {
23
+ super(weight, confThreshBps, stalenessThresh, volatilityThresh, minLiquidity, stalenessConfRateBps);
24
+ this.priceFeedId = "";
25
+ this.priceFeedAccount = priceFeedAccount;
26
+ this.connection = connection;
27
+ this.priceClient = priceClient;
28
+ this.state = state;
29
+ }
30
+ ;
31
+ static create() {
32
+ return __awaiter(this, arguments, void 0, function* (connection = new web3_js_1.Connection(constants_1.SOLANA_DEVNET_ENDPOINT), priceFeedAccount, weight, priceClient, confThreshBps, stalenessThresh, volatilityThresh, minLiquidity, stalenessConfRateBps) {
33
+ priceClient = priceClient !== null && priceClient !== void 0 ? priceClient : new hermes_client_1.HermesClient(constants_1.HERMES_PUBLIC_ENDPOINT, {});
34
+ const priceAccountInfo = yield connection.getAccountInfo(priceFeedAccount);
35
+ if (!priceAccountInfo) {
36
+ throw new Error(`Failed to fetch price account info for ${priceFeedAccount.toBase58()}`);
37
+ }
38
+ else {
39
+ let buffer = priceAccountInfo.data;
40
+ let offset = 8;
41
+ let writeAuthority = new web3_js_1.PublicKey(buffer.slice(offset, offset + 32));
42
+ offset += 32;
43
+ let { level, size } = parseVerificationLevel(buffer, offset);
44
+ offset += size;
45
+ let priceMessage = new web3_js_1.PublicKey(buffer.slice(offset, offset + 32));
46
+ offset += 32;
47
+ let price = new anchor_1.BN(buffer.slice(offset, offset + 8), 'le').toString();
48
+ offset += 8;
49
+ let conf = new anchor_1.BN(buffer.slice(offset, offset + 8), 'le').toString();
50
+ offset += 8;
51
+ let exp = new anchor_1.BN(buffer.slice(offset, offset + 4), 'le').fromTwos(32).toString();
52
+ offset += 4;
53
+ let publishTime = new anchor_1.BN(buffer.slice(offset, offset + 8), 'le').fromTwos(64).toString();
54
+ offset += 8;
55
+ let state = {
56
+ price: new anchor_1.BN(price),
57
+ conf: new anchor_1.BN(conf),
58
+ expo: parseInt(exp),
59
+ publishTime: new anchor_1.BN(publishTime)
60
+ };
61
+ return new PythOracle(
62
+ // priceFeedId,
63
+ priceFeedAccount, connection, priceClient, state, weight, confThreshBps, stalenessThresh, volatilityThresh, minLiquidity, stalenessConfRateBps);
64
+ }
65
+ });
66
+ }
67
+ ;
68
+ static createWithId() {
69
+ return __awaiter(this, arguments, void 0, function* (connection = new web3_js_1.Connection(constants_1.SOLANA_DEVNET_ENDPOINT), priceFeedId, wallet, weight, priceClient, confThreshBps, stalenessThresh, volatilityThresh, minLiquidity, stalenessConfRateBps) {
70
+ const pythSolanaReceiver = new pyth_solana_receiver_1.PythSolanaReceiver({
71
+ connection,
72
+ wallet,
73
+ });
74
+ priceClient = priceClient !== null && priceClient !== void 0 ? priceClient : new hermes_client_1.HermesClient(constants_1.HERMES_PUBLIC_ENDPOINT, {});
75
+ const priceAccount = pythSolanaReceiver.getPriceFeedAccountAddress(1, priceFeedId);
76
+ const priceAccountInfo = yield connection.getAccountInfo(priceAccount);
77
+ if (!priceAccountInfo) {
78
+ throw new Error(`Failed to fetch price account info for ${priceAccount.toBase58()}`);
79
+ }
80
+ else {
81
+ let buffer = priceAccountInfo.data;
82
+ let offset = 8;
83
+ let writeAuthority = new web3_js_1.PublicKey(buffer.slice(offset, offset + 32));
84
+ offset += 32;
85
+ let { level, size } = parseVerificationLevel(buffer, offset);
86
+ offset += size;
87
+ let priceMessage = new web3_js_1.PublicKey(buffer.slice(offset, offset + 32));
88
+ offset += 32;
89
+ let price = new anchor_1.BN(buffer.slice(offset, offset + 8), 'le').toString();
90
+ offset += 8;
91
+ let conf = new anchor_1.BN(buffer.slice(offset, offset + 8), 'le').toString();
92
+ offset += 8;
93
+ let exp = new anchor_1.BN(buffer.slice(offset, offset + 4), 'le').fromTwos(32).toString();
94
+ offset += 4;
95
+ let publishTime = new anchor_1.BN(buffer.slice(offset, offset + 8), 'le').fromTwos(64).toString();
96
+ offset += 8;
97
+ let state = {
98
+ price: new anchor_1.BN(price),
99
+ conf: new anchor_1.BN(conf),
100
+ expo: parseInt(exp),
101
+ publishTime: new anchor_1.BN(publishTime)
102
+ };
103
+ let pythOracle = new PythOracle(priceAccount, connection, priceClient, state, weight, confThreshBps, stalenessThresh, volatilityThresh, minLiquidity, stalenessConfRateBps);
104
+ pythOracle.setPriceFeedId(priceFeedId);
105
+ return pythOracle;
106
+ }
107
+ });
108
+ }
109
+ ;
110
+ getConfidence() {
111
+ return new decimal_js_1.Decimal(this.state.conf.toString()).mul(10 ** this.state.expo);
112
+ }
113
+ setPriceFeedId(priceFeedId) {
114
+ this.priceFeedId = priceFeedId;
115
+ }
116
+ fetch() {
117
+ return __awaiter(this, void 0, void 0, function* () {
118
+ const currentTime = new anchor_1.BN(Math.floor(Date.now() / 1000));
119
+ if (currentTime.sub(this.state.publishTime).gt(new anchor_1.BN(this.stalenessThresh))) {
120
+ this.state = yield this.fetchPriceFromHermes(this.priceFeedId);
121
+ }
122
+ let errors = 0;
123
+ console.log(this.confThreshBps);
124
+ console.log(this.state.conf.toString());
125
+ let pr = new decimal_js_1.Decimal(this.state.price.toString()).mul(10 ** this.state.expo);
126
+ let cf = new decimal_js_1.Decimal(this.state.conf.toString()).mul(10 ** this.state.expo);
127
+ console.log(cf.div(pr).mul(10000));
128
+ if (this.getConfidence().div(this.state.price.toString()).mul(10000).gt(this.confThreshBps)) {
129
+ errors |= oracle_1.ErrorCode.TOO_UNCERTAIN;
130
+ }
131
+ let err = new oracle_1.OracleErrors(errors);
132
+ console.log(this.state.publishTime);
133
+ let oraclePrice = new oracle_1.OraclePrice(new decimal_js_1.Decimal(this.state.price.toString()).mul(10 ** this.state.expo), new decimal_js_1.Decimal(this.state.conf.toString()).mul(10 ** this.state.expo), this.state.publishTime);
134
+ return new oracle_1.OracleResult(oraclePrice, err);
135
+ });
136
+ }
137
+ fetchPriceFromHermes(priceFeedId) {
138
+ return __awaiter(this, void 0, void 0, function* () {
139
+ const priceUpdate = yield this.priceClient.getLatestPriceUpdates([priceFeedId], { encoding: "base64" });
140
+ if (priceUpdate && priceUpdate.parsed && priceUpdate.parsed.length > 0) {
141
+ const priceData = priceUpdate.parsed[0].price;
142
+ console.log(priceData.publishTime);
143
+ return {
144
+ price: new anchor_1.BN(priceData.price),
145
+ conf: new anchor_1.BN(priceData.conf),
146
+ expo: priceData.expo,
147
+ publishTime: new anchor_1.BN(priceData.publishTime)
148
+ };
149
+ }
150
+ else {
151
+ throw new Error(`Failed to fetch price update from Hermes for ${priceFeedId}`);
152
+ }
153
+ });
154
+ }
155
+ /**
156
+ * Get parsed baskets by manager. Uses 10 paralel rpc calls so might get heavy. Should set feedDd before running this
157
+ * @param {number} shardId - between 0-2^64, default is 0
158
+ * @param {number} [computeUnitPrice] - compute unit price in microlamports, default is 100_000
159
+ */
160
+ updateFeedTx(wallet_1) {
161
+ return __awaiter(this, arguments, void 0, function* (wallet, shardId = 0, computeUnitPrice = 100000) {
162
+ if (!shardId)
163
+ shardId = 0;
164
+ if (!computeUnitPrice)
165
+ computeUnitPrice = 100000;
166
+ let priceUpdate = yield this.priceClient.getLatestPriceUpdates([this.priceFeedId], { encoding: "base64" });
167
+ const pythSolanaReceiver = new pyth_solana_receiver_1.PythSolanaReceiver({
168
+ connection: this.connection,
169
+ wallet: wallet,
170
+ });
171
+ const transactionBuilder = pythSolanaReceiver.newTransactionBuilder({
172
+ // closeUpdateAccounts: false
173
+ });
174
+ yield transactionBuilder.addUpdatePriceFeed(priceUpdate.binary.data, shardId);
175
+ let build = yield transactionBuilder.buildVersionedTransactions({
176
+ computeUnitPriceMicroLamports: computeUnitPrice,
177
+ });
178
+ return build;
179
+ });
180
+ }
181
+ ;
182
+ sendUpdateTx(provider, updateFeedTx) {
183
+ return __awaiter(this, void 0, void 0, function* () {
184
+ let txs = yield provider.sendAll(updateFeedTx, { skipPreflight: true, commitment: "confirmed" });
185
+ return txs;
186
+ });
187
+ }
188
+ }
189
+ exports.PythOracle = PythOracle;
190
+ function parseVerificationLevel(buf, offset) {
191
+ const discr = buf.readUInt8(offset);
192
+ if (discr === 0) { // Partial
193
+ const numSignatures = buf.readUInt8(offset + 1);
194
+ return { level: `Partial(${numSignatures})`, size: 2 };
195
+ }
196
+ else if (discr === 1) { // Full
197
+ return { level: "Full", size: 1 };
198
+ }
199
+ else {
200
+ throw new Error(`Unknown verification level: ${discr}`);
201
+ }
202
+ }
@@ -0,0 +1,39 @@
1
+ import { Decimal } from 'decimal.js';
2
+ import { AnchorProvider, BN, Wallet } from '@coral-xyz/anchor';
3
+ import { HermesClient } from '@pythnetwork/hermes-client';
4
+ import { Connection, PublicKey, Signer, TransactionSignature, VersionedTransaction } from '@solana/web3.js';
5
+ import { Oracle, OracleResult } from './oracle';
6
+ interface PythState {
7
+ price: BN;
8
+ conf: BN;
9
+ expo: number;
10
+ publishTime: BN;
11
+ }
12
+ export declare class PythOracle extends Oracle {
13
+ price_feed_account: PublicKey;
14
+ state: PythState;
15
+ connection: Connection;
16
+ price_client: HermesClient;
17
+ price_feed_id: string;
18
+ private constructor();
19
+ static create(connection: Connection | undefined, price_feed_account: PublicKey, weight: number, price_client?: HermesClient, conf_thresh_bps?: number, staleness_thresh?: number, volatility_thresh?: Decimal, min_liquidity?: Decimal, staleness_conf_rate_bps?: number): Promise<PythOracle>;
20
+ static createWithId(connection: Connection | undefined, price_feed_id: string, wallet: Wallet, weight: number, price_client?: HermesClient, conf_thresh_bps?: number, staleness_thresh?: number, volatility_thresh?: Decimal, min_liquidity?: Decimal, staleness_conf_rate_bps?: number): Promise<PythOracle>;
21
+ get_confidence(): Decimal;
22
+ set_price_feed_id(price_feed_id: string): void;
23
+ fetch(): Promise<OracleResult>;
24
+ fetchPriceFromHermes(price_feed_id: string): Promise<PythState>;
25
+ /**
26
+ * Get parsed baskets by manager. Uses 10 paralel rpc calls so might get heavy. Should set feed_id before running this
27
+ * @param {number} shardId - between 0-2^64, default is 0
28
+ * @param {number} [computeUnitPrice] - compute unit price in microlamports, default is 100_000
29
+ */
30
+ updateFeedTx(wallet: Wallet, shardId?: number, computeUnitPrice?: number): Promise<{
31
+ tx: VersionedTransaction;
32
+ signers: Signer[];
33
+ }[]>;
34
+ sendUpdateTx(provider: AnchorProvider, updateFeedTx: {
35
+ tx: VersionedTransaction;
36
+ signers: Signer[];
37
+ }[]): Promise<TransactionSignature[]>;
38
+ }
39
+ export {};