@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.
- package/dist/idl/idl.d.ts +8 -0
- package/dist/idl/idl.js +4958 -0
- package/dist/idl/types.d.ts +4955 -0
- package/dist/idl/types.js +2 -0
- package/dist/index.d.ts +24 -0
- package/dist/index.js +60 -0
- package/dist/layouts/basket.d.ts +42 -0
- package/dist/layouts/basket.js +43 -0
- package/dist/layouts/config.d.ts +97 -0
- package/dist/layouts/config.js +102 -0
- package/dist/layouts/fraction.d.ts +6 -0
- package/dist/layouts/fraction.js +9 -0
- package/dist/layouts/oracle.d.ts +36 -0
- package/dist/layouts/oracle.js +37 -0
- package/dist/src/constants.d.ts +15 -0
- package/dist/src/constants.js +19 -0
- package/dist/src/idl/idl.d.ts +8 -0
- package/dist/src/idl/idl.js +4958 -0
- package/dist/src/idl/types.d.ts +4955 -0
- package/dist/src/idl/types.js +2 -0
- package/dist/src/index.d.ts +53 -0
- package/dist/src/index.js +199 -0
- package/dist/src/instructions/accounts.d.ts +27 -0
- package/dist/src/instructions/accounts.js +110 -0
- package/dist/src/instructions/auction.d.ts +7 -0
- package/dist/src/instructions/auction.js +43 -0
- package/dist/src/instructions/automation/auction.d.ts +6 -0
- package/dist/src/instructions/automation/auction.js +40 -0
- package/dist/src/instructions/automation/claimBounty.d.ts +12 -0
- package/dist/src/instructions/automation/claimBounty.js +44 -0
- package/dist/src/instructions/automation/priceUpdate.d.ts +15 -0
- package/dist/src/instructions/automation/priceUpdate.js +47 -0
- package/dist/src/instructions/automation/rebalanceSwap.d.ts +10 -0
- package/dist/src/instructions/automation/rebalanceSwap.js +42 -0
- package/dist/src/instructions/basket.d.ts +120 -0
- package/dist/src/instructions/basket.js +622 -0
- package/dist/src/instructions/bounty.d.ts +18 -0
- package/dist/src/instructions/bounty.js +81 -0
- package/dist/src/instructions/fee.d.ts +8 -0
- package/dist/src/instructions/fee.js +46 -0
- package/dist/src/instructions/globalConfig.d.ts +11 -0
- package/dist/src/instructions/globalConfig.js +43 -0
- package/dist/src/instructions/luts.d.ts +33 -0
- package/dist/src/instructions/luts.js +91 -0
- package/dist/src/instructions/management/addBounty.d.ts +7 -0
- package/dist/src/instructions/management/addBounty.js +39 -0
- package/dist/src/instructions/management/admin.d.ts +9 -0
- package/dist/src/instructions/management/admin.js +43 -0
- package/dist/src/instructions/management/claimFees.d.ts +7 -0
- package/dist/src/instructions/management/claimFees.js +47 -0
- package/dist/src/instructions/management/createBasket.d.ts +22 -0
- package/dist/src/instructions/management/createBasket.js +101 -0
- package/dist/src/instructions/management/edit.d.ts +34 -0
- package/dist/src/instructions/management/edit.js +192 -0
- package/dist/src/instructions/management/luts.d.ts +29 -0
- package/dist/src/instructions/management/luts.js +88 -0
- package/dist/src/instructions/pda.d.ts +26 -0
- package/dist/src/instructions/pda.js +110 -0
- package/dist/src/instructions/price.d.ts +17 -0
- package/dist/src/instructions/price.js +47 -0
- package/dist/src/instructions/user/deposit.d.ts +32 -0
- package/dist/src/instructions/user/deposit.js +168 -0
- package/dist/src/instructions/user/withdraw.d.ts +16 -0
- package/dist/src/instructions/user/withdraw.js +82 -0
- package/dist/src/layouts/basket.d.ts +41 -0
- package/dist/src/layouts/basket.js +43 -0
- package/dist/src/layouts/config.d.ts +133 -0
- package/dist/src/layouts/config.js +137 -0
- package/dist/src/layouts/fraction.d.ts +6 -0
- package/dist/src/layouts/fraction.js +9 -0
- package/dist/src/layouts/intents/bounty.d.ts +18 -0
- package/dist/src/layouts/intents/bounty.js +19 -0
- package/dist/src/layouts/intents/intent.d.ts +101 -0
- package/dist/src/layouts/intents/intent.js +113 -0
- package/dist/src/layouts/intents/rebalanceIntent.d.ts +56 -0
- package/dist/src/layouts/intents/rebalanceIntent.js +63 -0
- package/dist/src/layouts/lookupTable.d.ts +7 -0
- package/dist/src/layouts/lookupTable.js +10 -0
- package/dist/src/layouts/oracle.d.ts +42 -0
- package/dist/src/layouts/oracle.js +43 -0
- package/dist/src/states/basket.d.ts +8 -0
- package/dist/src/states/basket.js +54 -0
- package/dist/src/states/intents/intent.d.ts +14 -0
- package/dist/src/states/intents/intent.js +90 -0
- package/dist/src/states/intents/rebalanceIntent.d.ts +8 -0
- package/dist/src/states/intents/rebalanceIntent.js +54 -0
- package/dist/src/states/oracles/clmm_oracle.d.ts +178 -0
- package/dist/src/states/oracles/clmm_oracle.js +546 -0
- package/dist/src/states/oracles/constants.d.ts +8 -0
- package/dist/src/states/oracles/constants.js +12 -0
- package/dist/src/states/oracles/oracle.d.ts +60 -0
- package/dist/src/states/oracles/oracle.js +237 -0
- package/dist/src/states/oracles/pythOracle.d.ts +39 -0
- package/dist/src/states/oracles/pythOracle.js +202 -0
- package/dist/src/states/oracles/pyth_oracle.d.ts +39 -0
- package/dist/src/states/oracles/pyth_oracle.js +202 -0
- package/dist/src/states/oracles/raydiumClmmOracle.d.ts +178 -0
- package/dist/src/states/oracles/raydiumClmmOracle.js +546 -0
- package/dist/src/states/oracles/raydiumCpmmOracle.d.ts +139 -0
- package/dist/src/states/oracles/raydiumCpmmOracle.js +420 -0
- package/dist/src/states/oracles/raydium_cpmm_oracle.d.ts +139 -0
- package/dist/src/states/oracles/raydium_cpmm_oracle.js +420 -0
- package/dist/src/states/oracles/switchboardOracle.d.ts +0 -0
- package/dist/src/states/oracles/switchboardOracle.js +1 -0
- package/dist/src/states/oracles/switchboard_oracle.d.ts +0 -0
- package/dist/src/states/oracles/switchboard_oracle.js +1 -0
- package/dist/src/txUtils.d.ts +26 -0
- package/dist/src/txUtils.js +183 -0
- package/dist/states/basket.d.ts +8 -0
- package/dist/states/basket.js +57 -0
- package/dist/test.d.ts +1 -0
- package/dist/test.js +39 -0
- package/package.json +30 -0
- package/src/constants.ts +24 -0
- package/src/index.ts +260 -0
- package/src/instructions/automation/auction.ts +55 -0
- package/src/instructions/automation/claimBounty.ts +69 -0
- package/src/instructions/automation/priceUpdate.ts +73 -0
- package/src/instructions/automation/rebalanceSwap.ts +60 -0
- package/src/instructions/management/addBounty.ts +56 -0
- package/src/instructions/management/admin.ts +65 -0
- package/src/instructions/management/claimFees.ts +59 -0
- package/src/instructions/management/createBasket.ts +148 -0
- package/src/instructions/management/edit.ts +255 -0
- package/src/instructions/management/luts.ts +134 -0
- package/src/instructions/pda.ts +160 -0
- package/src/instructions/user/deposit.ts +237 -0
- package/src/instructions/user/withdraw.ts +130 -0
- package/src/layouts/basket.ts +82 -0
- package/src/layouts/config.ts +301 -0
- package/src/layouts/fraction.ts +12 -0
- package/src/layouts/intents/bounty.ts +35 -0
- package/src/layouts/intents/intent.ts +204 -0
- package/src/layouts/intents/rebalanceIntent.ts +111 -0
- package/src/layouts/lookupTable.ts +14 -0
- package/src/layouts/oracle.ts +96 -0
- package/src/states/basket.ts +56 -0
- package/src/states/intents/intent.ts +107 -0
- package/src/states/intents/rebalanceIntent.ts +57 -0
- package/src/states/oracles/constants.ts +13 -0
- package/src/states/oracles/oracle.ts +260 -0
- package/src/states/oracles/pythOracle.ts +270 -0
- package/src/states/oracles/raydiumClmmOracle.ts +812 -0
- package/src/states/oracles/raydiumCpmmOracle.ts +614 -0
- package/src/states/oracles/switchboardOracle.ts +0 -0
- package/src/txUtils.ts +250 -0
- package/test.ts +30 -0
- package/tsconfig.json +101 -0
|
@@ -0,0 +1,812 @@
|
|
|
1
|
+
import Decimal from 'decimal.js';
|
|
2
|
+
|
|
3
|
+
import { BN } from '@coral-xyz/anchor';
|
|
4
|
+
import { Connection, PublicKey } from '@solana/web3.js';
|
|
5
|
+
|
|
6
|
+
import { U128_MAX } from './constants';
|
|
7
|
+
import { ErrorCode, Oracle, OracleErrors, OraclePrice, OracleResult } from './oracle';
|
|
8
|
+
|
|
9
|
+
const CLMM_PROGRAM_ID = new PublicKey("CAMMCzo5YL8w4VFF8KVHrK22GGUsp5VTaW7grrKgrWqK");
|
|
10
|
+
const MIN_TICK = -443636;
|
|
11
|
+
const MAX_TICK = 443636;
|
|
12
|
+
|
|
13
|
+
class Observation {
|
|
14
|
+
blockTimestamp: BN;
|
|
15
|
+
tickCumulative: BN;
|
|
16
|
+
padding: BN[];
|
|
17
|
+
constructor(params: {blockTimestamp: BN, tickCumulative: BN, padding: BN[]}){
|
|
18
|
+
this.blockTimestamp = params.blockTimestamp;
|
|
19
|
+
this.tickCumulative = params.tickCumulative;
|
|
20
|
+
this.padding = params.padding;
|
|
21
|
+
}
|
|
22
|
+
static decode(data: Buffer, offset = 0): [Observation, number] {
|
|
23
|
+
|
|
24
|
+
const blockTimestamp = new BN(data.readUInt32LE(offset));
|
|
25
|
+
|
|
26
|
+
const tickCumulative = new BN(
|
|
27
|
+
data.subarray(offset + 4, offset + 12),
|
|
28
|
+
"le"
|
|
29
|
+
).fromTwos(64);
|
|
30
|
+
|
|
31
|
+
const padding: BN[] = [];
|
|
32
|
+
let cursor = offset + 12;
|
|
33
|
+
for (let i = 0; i < 4; i++) {
|
|
34
|
+
padding.push(new BN(data.subarray(cursor, cursor + 8), "le"));
|
|
35
|
+
cursor += 8;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
return [
|
|
39
|
+
new Observation({
|
|
40
|
+
blockTimestamp,
|
|
41
|
+
tickCumulative,
|
|
42
|
+
padding }),
|
|
43
|
+
cursor
|
|
44
|
+
];
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
sub(other: Observation): Observation {
|
|
50
|
+
if (!(other instanceof Observation)) {
|
|
51
|
+
throw new TypeError("Subtraction is only supported between Observation instances");
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
return new Observation({
|
|
55
|
+
blockTimestamp: this.blockTimestamp.sub(other.blockTimestamp),
|
|
56
|
+
tickCumulative: this.tickCumulative.sub(other.tickCumulative),
|
|
57
|
+
padding: this.padding
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
add(other: Observation): Observation {
|
|
62
|
+
if (!(other instanceof Observation)) {
|
|
63
|
+
throw new TypeError("Addition is only supported between Observation instances");
|
|
64
|
+
}
|
|
65
|
+
return new Observation({
|
|
66
|
+
blockTimestamp: this.blockTimestamp.add(other.blockTimestamp),
|
|
67
|
+
tickCumulative: this.tickCumulative.add(other.tickCumulative),
|
|
68
|
+
padding: this.padding
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
getWeightedObservation(time: BN): Observation {
|
|
73
|
+
// cumT = (self.tickCumulative * time) / self.blockTimestamp
|
|
74
|
+
const cum = this.tickCumulative.mul(time).div(this.blockTimestamp);
|
|
75
|
+
return new Observation({
|
|
76
|
+
blockTimestamp: time,
|
|
77
|
+
tickCumulative: cum,
|
|
78
|
+
padding: this.padding
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
adjustToTimestamp(targetTimestamp: BN, observationPrev: Observation): Observation {
|
|
83
|
+
// delta = self.sub(prevObservation)
|
|
84
|
+
const delta = this.sub(observationPrev);
|
|
85
|
+
|
|
86
|
+
// weightedDelta = delta.getWeightedObservation(targetTimestamp - self.blockTimestamp)
|
|
87
|
+
const timeForWeighted = targetTimestamp.sub(this.blockTimestamp);
|
|
88
|
+
const weightedDelta = delta.getWeightedObservation(timeForWeighted);
|
|
89
|
+
|
|
90
|
+
// return self.add(weightedDelta)
|
|
91
|
+
return this.add(weightedDelta);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
class ObservationState {
|
|
97
|
+
initialized: boolean;
|
|
98
|
+
recentEpoch: BN;
|
|
99
|
+
observationIndex: number;
|
|
100
|
+
poolId: PublicKey;
|
|
101
|
+
observations: Observation[];
|
|
102
|
+
padding: BN[];
|
|
103
|
+
|
|
104
|
+
constructor(params: {
|
|
105
|
+
initialized: boolean,
|
|
106
|
+
recentEpoch: BN,
|
|
107
|
+
observationIndex: number,
|
|
108
|
+
poolId: PublicKey,
|
|
109
|
+
observations: Observation[],
|
|
110
|
+
padding: BN[]
|
|
111
|
+
}){
|
|
112
|
+
this.initialized = params.initialized;
|
|
113
|
+
this.recentEpoch = params.recentEpoch;
|
|
114
|
+
this.observationIndex = params.observationIndex;
|
|
115
|
+
this.poolId = params.poolId;
|
|
116
|
+
this.observations = params.observations;
|
|
117
|
+
this.padding = params.padding;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
static decode(data: Buffer, offset = 8): [ObservationState, number] {
|
|
121
|
+
let cursor = offset;
|
|
122
|
+
|
|
123
|
+
const initialized = data.readUInt8(cursor) !== 0;
|
|
124
|
+
cursor += 1;
|
|
125
|
+
|
|
126
|
+
const recentEpoch = new BN(data.subarray(cursor, cursor + 8), "le");
|
|
127
|
+
cursor += 8;
|
|
128
|
+
|
|
129
|
+
const observationIndex = data.readUInt16LE(cursor);
|
|
130
|
+
cursor += 2;
|
|
131
|
+
|
|
132
|
+
const poolId = new PublicKey(data.subarray(cursor, cursor + 32));
|
|
133
|
+
cursor += 32;
|
|
134
|
+
|
|
135
|
+
const observations: Observation[] = [];
|
|
136
|
+
for (let i = 0; i < 100; i++) {
|
|
137
|
+
let obs: Observation;
|
|
138
|
+
[obs, cursor] = Observation.decode(data, cursor);
|
|
139
|
+
observations.push(obs);
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
const padding: BN[] = [];
|
|
143
|
+
for (let i = 0; i < 4; i++) {
|
|
144
|
+
padding.push(new BN(data.subarray(cursor, cursor + 8), "le"));
|
|
145
|
+
cursor += 8;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
return [
|
|
149
|
+
new ObservationState({ initialized, recentEpoch, observationIndex, poolId, observations, padding }),
|
|
150
|
+
cursor
|
|
151
|
+
];
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
class RewardInfo {
|
|
157
|
+
rewardState: number;
|
|
158
|
+
openTime: BN;
|
|
159
|
+
endTime: BN;
|
|
160
|
+
lastUpdateTime: BN;
|
|
161
|
+
emissionsPerSecondX64: BN;
|
|
162
|
+
rewardTotalEmissioned: BN;
|
|
163
|
+
rewardClaimed: BN;
|
|
164
|
+
tokenMint: PublicKey;
|
|
165
|
+
tokenVault: PublicKey;
|
|
166
|
+
authority: PublicKey;
|
|
167
|
+
rewardGrowthGlobalX64: BN;
|
|
168
|
+
|
|
169
|
+
constructor(params: {
|
|
170
|
+
rewardState: number,
|
|
171
|
+
openTime: BN,
|
|
172
|
+
endTime: BN,
|
|
173
|
+
lastUpdateTime: BN,
|
|
174
|
+
emissionsPerSecondX64: BN,
|
|
175
|
+
rewardTotalEmissioned: BN,
|
|
176
|
+
rewardClaimed: BN,
|
|
177
|
+
tokenMint: PublicKey,
|
|
178
|
+
tokenVault: PublicKey,
|
|
179
|
+
authority: PublicKey,
|
|
180
|
+
rewardGrowthGlobalX64: BN
|
|
181
|
+
}){
|
|
182
|
+
this.rewardState = params.rewardState;
|
|
183
|
+
this.openTime = params.openTime;
|
|
184
|
+
this.endTime = params.endTime;
|
|
185
|
+
this.lastUpdateTime = params.lastUpdateTime;
|
|
186
|
+
this.emissionsPerSecondX64 = params.emissionsPerSecondX64;
|
|
187
|
+
this.rewardTotalEmissioned = params.rewardTotalEmissioned;
|
|
188
|
+
this.rewardClaimed = params.rewardClaimed;
|
|
189
|
+
this.tokenMint = params.tokenMint;
|
|
190
|
+
this.tokenVault = params.tokenVault;
|
|
191
|
+
this.authority = params.authority;
|
|
192
|
+
this.rewardGrowthGlobalX64 = params.rewardGrowthGlobalX64;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
static decode(data: Buffer, offset: number = 0): [RewardInfo, number] {
|
|
196
|
+
let cursor = offset;
|
|
197
|
+
|
|
198
|
+
const rewardState = data.readUInt8(cursor);
|
|
199
|
+
cursor += 1;
|
|
200
|
+
|
|
201
|
+
const openTime = new BN(data.subarray(cursor, cursor + 8), "le");
|
|
202
|
+
cursor += 8;
|
|
203
|
+
|
|
204
|
+
const endTime = new BN(data.subarray(cursor, cursor + 8), "le");
|
|
205
|
+
cursor += 8;
|
|
206
|
+
|
|
207
|
+
const lastUpdateTime = new BN(data.subarray(cursor, cursor + 8), "le");
|
|
208
|
+
cursor += 8;
|
|
209
|
+
|
|
210
|
+
const emissionsPerSecondX64 = new BN(data.subarray(cursor, cursor + 16), "le");
|
|
211
|
+
cursor += 16;
|
|
212
|
+
|
|
213
|
+
const rewardTotalEmissioned = new BN(data.subarray(cursor, cursor + 8), "le");
|
|
214
|
+
cursor += 8;
|
|
215
|
+
|
|
216
|
+
const rewardClaimed = new BN(data.subarray(cursor, cursor + 8), "le");
|
|
217
|
+
cursor += 8;
|
|
218
|
+
|
|
219
|
+
const tokenMint = new PublicKey(data.subarray(cursor, cursor + 32));
|
|
220
|
+
cursor += 32;
|
|
221
|
+
|
|
222
|
+
const tokenVault = new PublicKey(data.subarray(cursor, cursor + 32));
|
|
223
|
+
cursor += 32;
|
|
224
|
+
|
|
225
|
+
const authority = new PublicKey(data.subarray(cursor, cursor + 32));
|
|
226
|
+
cursor += 32;
|
|
227
|
+
|
|
228
|
+
const rewardGrowthGlobalX64 = new BN(data.subarray(cursor, cursor + 16), "le");
|
|
229
|
+
cursor += 16;
|
|
230
|
+
|
|
231
|
+
return [ new RewardInfo({
|
|
232
|
+
rewardState,
|
|
233
|
+
openTime,
|
|
234
|
+
endTime,
|
|
235
|
+
lastUpdateTime,
|
|
236
|
+
emissionsPerSecondX64,
|
|
237
|
+
rewardTotalEmissioned,
|
|
238
|
+
rewardClaimed,
|
|
239
|
+
tokenMint,
|
|
240
|
+
tokenVault,
|
|
241
|
+
authority,
|
|
242
|
+
rewardGrowthGlobalX64
|
|
243
|
+
}), cursor];
|
|
244
|
+
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
|
|
249
|
+
|
|
250
|
+
class PoolState {
|
|
251
|
+
bump: number[];
|
|
252
|
+
ammConfig: PublicKey;
|
|
253
|
+
owner: PublicKey;
|
|
254
|
+
tokenMint0: PublicKey;
|
|
255
|
+
tokenMint1: PublicKey;
|
|
256
|
+
tokenVault0: PublicKey;
|
|
257
|
+
tokenVault1: PublicKey;
|
|
258
|
+
observationKey: PublicKey;
|
|
259
|
+
mintDecimals0: number;
|
|
260
|
+
mintDecimals1: number;
|
|
261
|
+
tickSpacing: number;
|
|
262
|
+
liquidity: BN;
|
|
263
|
+
sqrtPriceX64: BN;
|
|
264
|
+
tickCurrent: BN;
|
|
265
|
+
padding3: number;
|
|
266
|
+
padding4: number;
|
|
267
|
+
feeGrowthGlobal0X64: BN;
|
|
268
|
+
feeGrowthGlobal1X64: BN;
|
|
269
|
+
protocolFeesToken0: BN;
|
|
270
|
+
protocolFeesToken1: BN;
|
|
271
|
+
swapInAmountToken0: BN;
|
|
272
|
+
swapOutAmountToken1: BN;
|
|
273
|
+
swapInAmountToken1: BN;
|
|
274
|
+
swapOutAmountToken0: BN;
|
|
275
|
+
status: number;
|
|
276
|
+
padding: number[];
|
|
277
|
+
rewardInfos: RewardInfo[];
|
|
278
|
+
tickArrayBitmap: BN[];
|
|
279
|
+
totalFeesToken0: BN;
|
|
280
|
+
totalFeesClaimedToken0: BN;
|
|
281
|
+
totalFeesToken1: BN;
|
|
282
|
+
totalFeesClaimedToken1: BN;
|
|
283
|
+
fundFeesToken0: BN;
|
|
284
|
+
fundFeesToken1: BN;
|
|
285
|
+
openTime: BN;
|
|
286
|
+
recentEpoch: BN;
|
|
287
|
+
padding1: BN[];
|
|
288
|
+
padding2: BN[];
|
|
289
|
+
|
|
290
|
+
constructor(
|
|
291
|
+
params: {
|
|
292
|
+
bump: number[],
|
|
293
|
+
ammConfig: PublicKey,
|
|
294
|
+
owner: PublicKey,
|
|
295
|
+
tokenMint0: PublicKey,
|
|
296
|
+
tokenMint1: PublicKey,
|
|
297
|
+
tokenVault0: PublicKey,
|
|
298
|
+
tokenVault1: PublicKey,
|
|
299
|
+
observationKey: PublicKey,
|
|
300
|
+
mintDecimals0: number,
|
|
301
|
+
mintDecimals1: number,
|
|
302
|
+
tickSpacing: BN,
|
|
303
|
+
liquidity: BN,
|
|
304
|
+
sqrtPriceX64: BN,
|
|
305
|
+
tickCurrent: BN,
|
|
306
|
+
padding3: number,
|
|
307
|
+
padding4: number,
|
|
308
|
+
feeGrowthGlobal0X64: BN,
|
|
309
|
+
feeGrowthGlobal1X64: BN,
|
|
310
|
+
protocolFeesToken0: BN,
|
|
311
|
+
protocolFeesToken1: BN,
|
|
312
|
+
swapInAmountToken0: BN,
|
|
313
|
+
swapOutAmountToken1: BN,
|
|
314
|
+
swapInAmountToken1: BN,
|
|
315
|
+
swapOutAmountToken0: BN,
|
|
316
|
+
status: number,
|
|
317
|
+
padding: number[],
|
|
318
|
+
rewardInfos: RewardInfo[],
|
|
319
|
+
tickArrayBitmap: BN[],
|
|
320
|
+
totalFeesToken0: BN,
|
|
321
|
+
totalFeesClaimedToken0: BN,
|
|
322
|
+
totalFeesToken1: BN,
|
|
323
|
+
totalFeesClaimedToken1: BN,
|
|
324
|
+
fundFeesToken0: BN,
|
|
325
|
+
fundFeesToken1: BN,
|
|
326
|
+
openTime: BN,
|
|
327
|
+
recentEpoch: BN,
|
|
328
|
+
padding1: BN[],
|
|
329
|
+
padding2: BN[]
|
|
330
|
+
}
|
|
331
|
+
){
|
|
332
|
+
this.bump = params.bump;
|
|
333
|
+
this.ammConfig = params.ammConfig;
|
|
334
|
+
this.owner = params.owner;
|
|
335
|
+
this.tokenMint0 = params.tokenMint0;
|
|
336
|
+
this.tokenMint1 = params.tokenMint1;
|
|
337
|
+
this.tokenVault0 = params.tokenVault0;
|
|
338
|
+
this.tokenVault1 = params.tokenVault1;
|
|
339
|
+
this.observationKey = params.observationKey;
|
|
340
|
+
this.mintDecimals0 = params.mintDecimals0;
|
|
341
|
+
this.mintDecimals1 = params.mintDecimals1;
|
|
342
|
+
this.tickSpacing = params.tickSpacing;
|
|
343
|
+
this.liquidity = params.liquidity;
|
|
344
|
+
this.sqrtPriceX64 = params.sqrtPriceX64;
|
|
345
|
+
this.tickCurrent = params.tickCurrent;
|
|
346
|
+
this.padding3 = params.padding3;
|
|
347
|
+
this.padding4 = params.padding4;
|
|
348
|
+
this.feeGrowthGlobal0X64 = params.feeGrowthGlobal0X64;
|
|
349
|
+
this.feeGrowthGlobal1X64 = params.feeGrowthGlobal1X64;
|
|
350
|
+
this.protocolFeesToken0 = params.protocolFeesToken0;
|
|
351
|
+
this.protocolFeesToken1 = params.protocolFeesToken1;
|
|
352
|
+
this.swapInAmountToken0 = params.swapInAmountToken0;
|
|
353
|
+
this.swapOutAmountToken1 = params.swapOutAmountToken1;
|
|
354
|
+
this.swapInAmountToken1 = params.swapInAmountToken1;
|
|
355
|
+
this.swapOutAmountToken0 = params.swapOutAmountToken0;
|
|
356
|
+
this.status = params.status;
|
|
357
|
+
this.padding = params.padding;
|
|
358
|
+
this.rewardInfos = params.rewardInfos;
|
|
359
|
+
this.tickArrayBitmap = params.tickArrayBitmap;
|
|
360
|
+
this.totalFeesToken0 = params.totalFeesToken0;
|
|
361
|
+
this.totalFeesClaimedToken0 = params.totalFeesClaimedToken0;
|
|
362
|
+
this.totalFeesToken1 = params.totalFeesToken1;
|
|
363
|
+
this.totalFeesClaimedToken1 = params.totalFeesClaimedToken1;
|
|
364
|
+
this.fundFeesToken0 = params.fundFeesToken0;
|
|
365
|
+
this.fundFeesToken1 = params.fundFeesToken1;
|
|
366
|
+
this.openTime = params.openTime;
|
|
367
|
+
this.recentEpoch = params.recentEpoch;
|
|
368
|
+
this.padding1 = params.padding1;
|
|
369
|
+
this.padding2 = params.padding2;
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
static decode(data: Buffer, offset: number = 8): [PoolState, number] {
|
|
373
|
+
let cursor = offset;
|
|
374
|
+
|
|
375
|
+
const bump = [data.readUInt8(cursor)];
|
|
376
|
+
cursor += 1;
|
|
377
|
+
|
|
378
|
+
const ammConfig = new PublicKey(data.subarray(cursor, cursor + 32));
|
|
379
|
+
cursor += 32;
|
|
380
|
+
|
|
381
|
+
const owner = new PublicKey(data.subarray(cursor, cursor + 32));
|
|
382
|
+
cursor += 32;
|
|
383
|
+
|
|
384
|
+
const tokenMint0 = new PublicKey(data.subarray(cursor, cursor + 32));
|
|
385
|
+
cursor += 32;
|
|
386
|
+
|
|
387
|
+
const tokenMint1 = new PublicKey(data.subarray(cursor, cursor + 32));
|
|
388
|
+
cursor += 32;
|
|
389
|
+
|
|
390
|
+
const tokenVault0 = new PublicKey(data.subarray(cursor, cursor + 32));
|
|
391
|
+
cursor += 32;
|
|
392
|
+
|
|
393
|
+
const tokenVault1 = new PublicKey(data.subarray(cursor, cursor + 32));
|
|
394
|
+
cursor += 32;
|
|
395
|
+
|
|
396
|
+
const observationKey = new PublicKey(data.subarray(cursor, cursor + 32));
|
|
397
|
+
cursor += 32;
|
|
398
|
+
|
|
399
|
+
const mintDecimals0 = data.readUInt8(cursor);
|
|
400
|
+
cursor += 1;
|
|
401
|
+
|
|
402
|
+
const mintDecimals1 = data.readUInt8(cursor);
|
|
403
|
+
cursor += 1;
|
|
404
|
+
|
|
405
|
+
const tickSpacing = data.readUInt16LE(cursor);
|
|
406
|
+
cursor += 2;
|
|
407
|
+
|
|
408
|
+
const liquidity = new BN(data.subarray(cursor, cursor + 16), "le");
|
|
409
|
+
cursor += 16;
|
|
410
|
+
|
|
411
|
+
const sqrtPriceX64 = new BN(data.subarray(cursor, cursor + 16), "le");
|
|
412
|
+
cursor += 16;
|
|
413
|
+
|
|
414
|
+
const tickCurrent = data.readInt32LE(cursor);
|
|
415
|
+
cursor += 4;
|
|
416
|
+
|
|
417
|
+
const padding3 = data.readUInt16LE(cursor);
|
|
418
|
+
cursor += 2;
|
|
419
|
+
|
|
420
|
+
const padding4 = data.readUInt16LE(cursor);
|
|
421
|
+
cursor += 2;
|
|
422
|
+
|
|
423
|
+
const feeGrowthGlobal0X64 = new BN(data.subarray(cursor, cursor + 16), "le");
|
|
424
|
+
cursor += 16;
|
|
425
|
+
|
|
426
|
+
const feeGrowthGlobal1X64 = new BN(data.subarray(cursor, cursor + 16), "le");
|
|
427
|
+
cursor += 16;
|
|
428
|
+
|
|
429
|
+
const protocolFeesToken0 = new BN(data.subarray(cursor, cursor + 8), "le");
|
|
430
|
+
cursor += 8;
|
|
431
|
+
|
|
432
|
+
const protocolFeesToken1 = new BN(data.subarray(cursor, cursor + 8), "le");
|
|
433
|
+
cursor += 8;
|
|
434
|
+
|
|
435
|
+
const swapInAmountToken0 = new BN(data.subarray(cursor, cursor + 16), "le");
|
|
436
|
+
cursor += 16;
|
|
437
|
+
|
|
438
|
+
const swapOutAmountToken1 = new BN(data.subarray(cursor, cursor + 16), "le");
|
|
439
|
+
cursor += 16;
|
|
440
|
+
|
|
441
|
+
const swapInAmountToken1 = new BN(data.subarray(cursor, cursor + 16), "le");
|
|
442
|
+
cursor += 16;
|
|
443
|
+
|
|
444
|
+
const swapOutAmountToken0 = new BN(data.subarray(cursor, cursor + 16), "le");
|
|
445
|
+
cursor += 16;
|
|
446
|
+
|
|
447
|
+
const status = data.readUInt8(cursor);
|
|
448
|
+
cursor += 1;
|
|
449
|
+
|
|
450
|
+
const padding: number[] = [];
|
|
451
|
+
for (let i = 0; i < 7; i++) {
|
|
452
|
+
padding.push(data.readUInt8(cursor));
|
|
453
|
+
cursor += 1;
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
// RewardInfos
|
|
457
|
+
const rewardInfos: RewardInfo[] = [];
|
|
458
|
+
for (let i = 0; i < 3; i++) {
|
|
459
|
+
const decoded = RewardInfo.decode(data, cursor);
|
|
460
|
+
rewardInfos.push(decoded[0]);
|
|
461
|
+
cursor = decoded[1];
|
|
462
|
+
}
|
|
463
|
+
|
|
464
|
+
// tickArrayBitmap [u64;16]
|
|
465
|
+
const tickArrayBitmap: BN[] = [];
|
|
466
|
+
for (let i = 0; i < 16; i++) {
|
|
467
|
+
tickArrayBitmap.push(new BN(data.subarray(cursor, cursor + 8), "le"));
|
|
468
|
+
cursor += 8;
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
const totalFeesToken0 = new BN(data.subarray(cursor, cursor + 8), "le");
|
|
472
|
+
cursor += 8;
|
|
473
|
+
|
|
474
|
+
const totalFeesClaimedToken0 = new BN(data.subarray(cursor, cursor + 8), "le");
|
|
475
|
+
cursor += 8;
|
|
476
|
+
|
|
477
|
+
const totalFeesToken1 = new BN(data.subarray(cursor, cursor + 8), "le");
|
|
478
|
+
cursor += 8;
|
|
479
|
+
|
|
480
|
+
const totalFeesClaimedToken1 = new BN(data.subarray(cursor, cursor + 8), "le");
|
|
481
|
+
cursor += 8;
|
|
482
|
+
|
|
483
|
+
const fundFeesToken0 = new BN(data.subarray(cursor, cursor + 8), "le");
|
|
484
|
+
cursor += 8;
|
|
485
|
+
|
|
486
|
+
const fundFeesToken1 = new BN(data.subarray(cursor, cursor + 8), "le");
|
|
487
|
+
cursor += 8;
|
|
488
|
+
|
|
489
|
+
const openTime = new BN(data.subarray(cursor, cursor + 8), "le");
|
|
490
|
+
cursor += 8;
|
|
491
|
+
|
|
492
|
+
const recentEpoch = new BN(data.subarray(cursor, cursor + 8), "le");
|
|
493
|
+
cursor += 8;
|
|
494
|
+
|
|
495
|
+
const padding1: BN[] = [];
|
|
496
|
+
for (let i = 0; i < 24; i++) {
|
|
497
|
+
padding1.push(new BN(data.subarray(cursor, cursor + 8), "le"));
|
|
498
|
+
cursor += 8;
|
|
499
|
+
}
|
|
500
|
+
|
|
501
|
+
const padding2: BN[] = [];
|
|
502
|
+
for (let i = 0; i < 32; i++) {
|
|
503
|
+
padding2.push(new BN(data.subarray(cursor, cursor + 8), "le"));
|
|
504
|
+
cursor += 8;
|
|
505
|
+
}
|
|
506
|
+
|
|
507
|
+
return [
|
|
508
|
+
new PoolState({
|
|
509
|
+
bump,
|
|
510
|
+
ammConfig,
|
|
511
|
+
owner,
|
|
512
|
+
tokenMint0,
|
|
513
|
+
tokenMint1,
|
|
514
|
+
tokenVault0,
|
|
515
|
+
tokenVault1,
|
|
516
|
+
observationKey,
|
|
517
|
+
mintDecimals0,
|
|
518
|
+
mintDecimals1,
|
|
519
|
+
tickSpacing,
|
|
520
|
+
liquidity,
|
|
521
|
+
sqrtPriceX64,
|
|
522
|
+
tickCurrent,
|
|
523
|
+
padding3,
|
|
524
|
+
padding4,
|
|
525
|
+
feeGrowthGlobal0X64,
|
|
526
|
+
feeGrowthGlobal1X64,
|
|
527
|
+
protocolFeesToken0,
|
|
528
|
+
protocolFeesToken1,
|
|
529
|
+
swapInAmountToken0,
|
|
530
|
+
swapOutAmountToken1,
|
|
531
|
+
swapInAmountToken1,
|
|
532
|
+
swapOutAmountToken0,
|
|
533
|
+
status,
|
|
534
|
+
padding,
|
|
535
|
+
rewardInfos,
|
|
536
|
+
tickArrayBitmap,
|
|
537
|
+
totalFeesToken0,
|
|
538
|
+
totalFeesClaimedToken0,
|
|
539
|
+
totalFeesToken1,
|
|
540
|
+
totalFeesClaimedToken1,
|
|
541
|
+
fundFeesToken0,
|
|
542
|
+
fundFeesToken1,
|
|
543
|
+
openTime,
|
|
544
|
+
recentEpoch,
|
|
545
|
+
padding1,
|
|
546
|
+
padding2,
|
|
547
|
+
}),
|
|
548
|
+
cursor,
|
|
549
|
+
];
|
|
550
|
+
}
|
|
551
|
+
|
|
552
|
+
|
|
553
|
+
}
|
|
554
|
+
|
|
555
|
+
|
|
556
|
+
export class RaydiumCLMMOracle extends Oracle{
|
|
557
|
+
poolId: PublicKey;
|
|
558
|
+
quoteToken: number;
|
|
559
|
+
poolState: PoolState;
|
|
560
|
+
observationState: ObservationState;
|
|
561
|
+
primarySeconds: number;
|
|
562
|
+
secondarySeconds: number;
|
|
563
|
+
|
|
564
|
+
private constructor(params: {
|
|
565
|
+
poolId: PublicKey,
|
|
566
|
+
quoteToken: number,
|
|
567
|
+
poolState: PoolState,
|
|
568
|
+
observationState: ObservationState,
|
|
569
|
+
weight: number,
|
|
570
|
+
primarySeconds: number,
|
|
571
|
+
secondarySeconds: number,
|
|
572
|
+
confThreshBps?: number,
|
|
573
|
+
stalenessThresh?: number,
|
|
574
|
+
volatilityThresh?: number | Decimal,
|
|
575
|
+
minLiquidity?: number | Decimal,
|
|
576
|
+
stalenessConfRateBps?: number
|
|
577
|
+
}){
|
|
578
|
+
super(
|
|
579
|
+
params.weight,
|
|
580
|
+
params.confThreshBps,
|
|
581
|
+
params.stalenessThresh,
|
|
582
|
+
params.volatilityThresh,
|
|
583
|
+
params.minLiquidity,
|
|
584
|
+
params.stalenessConfRateBps
|
|
585
|
+
);
|
|
586
|
+
|
|
587
|
+
this.poolId = params.poolId;
|
|
588
|
+
this.quoteToken = params.quoteToken;
|
|
589
|
+
this.poolState = params.poolState;
|
|
590
|
+
this.observationState = params.observationState;
|
|
591
|
+
this.primarySeconds = params.primarySeconds;
|
|
592
|
+
this.secondarySeconds = params.secondarySeconds;
|
|
593
|
+
};
|
|
594
|
+
|
|
595
|
+
static async create(params: {
|
|
596
|
+
connection: Connection,
|
|
597
|
+
poolId: PublicKey,
|
|
598
|
+
quoteToken: number,
|
|
599
|
+
weight: number,
|
|
600
|
+
primarySeconds: number,
|
|
601
|
+
secondarySeconds: number,
|
|
602
|
+
confThreshBps?: number,
|
|
603
|
+
stalenessThresh?: number,
|
|
604
|
+
volatilityThresh?: number | Decimal,
|
|
605
|
+
minLiquidity?: number | Decimal,
|
|
606
|
+
stalenessConfRateBps?: number
|
|
607
|
+
}): Promise<RaydiumCLMMOracle> {
|
|
608
|
+
const { connection, poolId } = params;
|
|
609
|
+
|
|
610
|
+
// Fetch poolState
|
|
611
|
+
const poolAccountInfo = await connection.getAccountInfo(new PublicKey(poolId));
|
|
612
|
+
if (!poolAccountInfo) throw new Error("Pool account not found");
|
|
613
|
+
const [poolState, _] = PoolState.decode(poolAccountInfo.data, 8);
|
|
614
|
+
|
|
615
|
+
// Fetch observationState from poolState
|
|
616
|
+
const obsPubkey = poolState.observationKey;
|
|
617
|
+
const obsAccountInfo = await connection.getAccountInfo(new PublicKey(obsPubkey));
|
|
618
|
+
if (!obsAccountInfo) throw new Error("Observation account not found");
|
|
619
|
+
const [observationState, __] = ObservationState.decode(obsAccountInfo.data, 8);
|
|
620
|
+
|
|
621
|
+
|
|
622
|
+
return new RaydiumCLMMOracle({
|
|
623
|
+
poolId: poolId,
|
|
624
|
+
quoteToken: params.quoteToken,
|
|
625
|
+
poolState: poolState,
|
|
626
|
+
observationState: observationState,
|
|
627
|
+
weight: params.weight,
|
|
628
|
+
primarySeconds: params.primarySeconds,
|
|
629
|
+
secondarySeconds: params.secondarySeconds,
|
|
630
|
+
confThreshBps: params.confThreshBps,
|
|
631
|
+
stalenessThresh: params.stalenessThresh,
|
|
632
|
+
volatilityThresh: params.volatilityThresh,
|
|
633
|
+
minLiquidity: params.minLiquidity,
|
|
634
|
+
stalenessConfRateBps: params.stalenessConfRateBps
|
|
635
|
+
});
|
|
636
|
+
}
|
|
637
|
+
|
|
638
|
+
static deriveObservationKey(poolId: PublicKey): [PublicKey, number] {
|
|
639
|
+
const seeds = [
|
|
640
|
+
Buffer.from("observation"),
|
|
641
|
+
poolId.toBuffer(),
|
|
642
|
+
];
|
|
643
|
+
return PublicKey.findProgramAddressSync(seeds, CLMM_PROGRAM_ID);
|
|
644
|
+
};
|
|
645
|
+
|
|
646
|
+
getObservationAtIndex(index: number) {
|
|
647
|
+
return this.observationState.observations[index];
|
|
648
|
+
}
|
|
649
|
+
|
|
650
|
+
getObservationAtTimestamp(timestamp: BN, startIndex: number): Observation {
|
|
651
|
+
let observationCurrent = this.getObservationAtIndex(startIndex);
|
|
652
|
+
let index = startIndex;
|
|
653
|
+
|
|
654
|
+
// const obsIndex = this.observationState.observationIndex;
|
|
655
|
+
|
|
656
|
+
// Loop backwards until we find the observation <= timestamp
|
|
657
|
+
while (observationCurrent.blockTimestamp.gt(timestamp)) {
|
|
658
|
+
index = (index - 1 + 100) % 100;
|
|
659
|
+
observationCurrent = this.getObservationAtIndex(index);
|
|
660
|
+
|
|
661
|
+
if (index === startIndex) {
|
|
662
|
+
throw Error("Observations do not go back far enough in time");
|
|
663
|
+
break; // looped all the way around
|
|
664
|
+
}
|
|
665
|
+
}
|
|
666
|
+
|
|
667
|
+
// Previous index for interpolation
|
|
668
|
+
const prevIndex = (index - 1 + 100) % 100;
|
|
669
|
+
const observationPrev = this.getObservationAtIndex(prevIndex);
|
|
670
|
+
|
|
671
|
+
// Adjust current observation to the target timestamp
|
|
672
|
+
const result = observationCurrent.adjustToTimestamp(timestamp, observationPrev);
|
|
673
|
+
return result;
|
|
674
|
+
}
|
|
675
|
+
|
|
676
|
+
getDeltaObservations(currentTime: BN, primarySeconds: number, secondarySeconds: number): Observation[] {
|
|
677
|
+
|
|
678
|
+
const obsIndex = this.observationState.observationIndex;
|
|
679
|
+
const observationCurrent = this.getObservationAtTimestamp(currentTime, obsIndex);
|
|
680
|
+
|
|
681
|
+
const observationPrimary = this.getObservationAtTimestamp(new BN(currentTime.sub(new BN(primarySeconds))), obsIndex);
|
|
682
|
+
const deltaPrimary = observationCurrent.sub(observationPrimary);
|
|
683
|
+
|
|
684
|
+
const observationSecondary = this.getObservationAtTimestamp(new BN(currentTime.sub(new BN(secondarySeconds))), obsIndex);
|
|
685
|
+
const deltaSecondary = observationCurrent.sub(observationSecondary);
|
|
686
|
+
|
|
687
|
+
return [observationPrimary,observationSecondary];
|
|
688
|
+
}
|
|
689
|
+
|
|
690
|
+
|
|
691
|
+
getSqrtPriceX64FromTick(tick: BN): BN {
|
|
692
|
+
|
|
693
|
+
let numTick = tick.toNumber();
|
|
694
|
+
if (!Number.isInteger(numTick)) {
|
|
695
|
+
throw new Error("tick must be integer");
|
|
696
|
+
}
|
|
697
|
+
if (numTick < MIN_TICK || numTick > MAX_TICK) {
|
|
698
|
+
throw new Error("tick must be in MIN_TICK and MAX_TICK");
|
|
699
|
+
}
|
|
700
|
+
const tickAbs: number = numTick < 0 ? numTick * -1 : numTick;
|
|
701
|
+
|
|
702
|
+
let ratio: BN = (tickAbs & 0x1) != 0 ? new BN("18445821805675395072") : new BN("18446744073709551616");
|
|
703
|
+
if ((tickAbs & 0x2) != 0) ratio = mulRightShift(ratio, new BN("18444899583751176192"));
|
|
704
|
+
if ((tickAbs & 0x4) != 0) ratio = mulRightShift(ratio, new BN("18443055278223355904"));
|
|
705
|
+
if ((tickAbs & 0x8) != 0) ratio = mulRightShift(ratio, new BN("18439367220385607680"));
|
|
706
|
+
if ((tickAbs & 0x10) != 0) ratio = mulRightShift(ratio, new BN("18431993317065453568"));
|
|
707
|
+
if ((tickAbs & 0x20) != 0) ratio = mulRightShift(ratio, new BN("18417254355718170624"));
|
|
708
|
+
if ((tickAbs & 0x40) != 0) ratio = mulRightShift(ratio, new BN("18387811781193609216"));
|
|
709
|
+
if ((tickAbs & 0x80) != 0) ratio = mulRightShift(ratio, new BN("18329067761203558400"));
|
|
710
|
+
if ((tickAbs & 0x100) != 0) ratio = mulRightShift(ratio, new BN("18212142134806163456"));
|
|
711
|
+
if ((tickAbs & 0x200) != 0) ratio = mulRightShift(ratio, new BN("17980523815641700352"));
|
|
712
|
+
if ((tickAbs & 0x400) != 0) ratio = mulRightShift(ratio, new BN("17526086738831433728"));
|
|
713
|
+
if ((tickAbs & 0x800) != 0) ratio = mulRightShift(ratio, new BN("16651378430235570176"));
|
|
714
|
+
if ((tickAbs & 0x1000) != 0) ratio = mulRightShift(ratio, new BN("15030750278694412288"));
|
|
715
|
+
if ((tickAbs & 0x2000) != 0) ratio = mulRightShift(ratio, new BN("12247334978884435968"));
|
|
716
|
+
if ((tickAbs & 0x4000) != 0) ratio = mulRightShift(ratio, new BN("8131365268886854656"));
|
|
717
|
+
if ((tickAbs & 0x8000) != 0) ratio = mulRightShift(ratio, new BN("3584323654725218816"));
|
|
718
|
+
if ((tickAbs & 0x10000) != 0) ratio = mulRightShift(ratio, new BN("696457651848324352"));
|
|
719
|
+
if ((tickAbs & 0x20000) != 0) ratio = mulRightShift(ratio, new BN("26294789957507116"));
|
|
720
|
+
if ((tickAbs & 0x40000) != 0) ratio = mulRightShift(ratio, new BN("37481735321082"));
|
|
721
|
+
|
|
722
|
+
if (numTick > 0) ratio = U128_MAX.div(ratio);
|
|
723
|
+
return ratio;
|
|
724
|
+
}
|
|
725
|
+
|
|
726
|
+
sqrtPriceX64ToPrice(sqrtPriceX64: BN, decimalsA: number, decimalsB: number): Decimal {
|
|
727
|
+
|
|
728
|
+
return this.x64ToDecimal(sqrtPriceX64)
|
|
729
|
+
.pow(2)
|
|
730
|
+
.mul(Decimal.pow(10, decimalsA - decimalsB));
|
|
731
|
+
}
|
|
732
|
+
|
|
733
|
+
x64ToDecimal(num: BN, decimalPlaces?: number): Decimal {
|
|
734
|
+
|
|
735
|
+
return new Decimal(num.toString()).div(Decimal.pow(2, 64)).toDecimalPlaces(decimalPlaces);
|
|
736
|
+
}
|
|
737
|
+
|
|
738
|
+
getTwapPrimary(currentTime: BN): Decimal {
|
|
739
|
+
|
|
740
|
+
let observation = this.getDeltaObservations(currentTime, this.primarySeconds, this.secondarySeconds)[0];
|
|
741
|
+
|
|
742
|
+
let tick = observation.tickCumulative.div(observation.blockTimestamp);
|
|
743
|
+
let twap = this.sqrtPriceX64ToPrice(this.getSqrtPriceX64FromTick(tick),
|
|
744
|
+
this.poolState.mintDecimals0,
|
|
745
|
+
this.poolState.mintDecimals1);
|
|
746
|
+
return twap;
|
|
747
|
+
}
|
|
748
|
+
|
|
749
|
+
getTwapSecondary(currentTime: BN): Decimal {
|
|
750
|
+
|
|
751
|
+
let observation = this.getDeltaObservations(currentTime, this.primarySeconds, this.secondarySeconds)[1];
|
|
752
|
+
let tick = observation.tickCumulative.div(observation.blockTimestamp);
|
|
753
|
+
let twap = this.sqrtPriceX64ToPrice(this.getSqrtPriceX64FromTick(tick),
|
|
754
|
+
this.poolState.mintDecimals0,
|
|
755
|
+
this.poolState.mintDecimals1);
|
|
756
|
+
return twap;
|
|
757
|
+
}
|
|
758
|
+
|
|
759
|
+
getConfidence(currentTime: BN): Decimal {
|
|
760
|
+
|
|
761
|
+
const conf = this.getTwapPrimary(currentTime).sub(this.getTwapSecondary(currentTime)).abs();
|
|
762
|
+
|
|
763
|
+
return conf;
|
|
764
|
+
}
|
|
765
|
+
|
|
766
|
+
|
|
767
|
+
|
|
768
|
+
async fetch(): Promise<OracleResult> {
|
|
769
|
+
const currentTime = new BN(Math.floor(Date.now() / 1000)); // current UNIX timestamp in seconds
|
|
770
|
+
|
|
771
|
+
const confidence = this.getConfidence(currentTime);
|
|
772
|
+
|
|
773
|
+
const liquidity = this.poolState.liquidity; // assuming poolState is already the decoded data
|
|
774
|
+
const price = this.getTwapPrimary(currentTime);
|
|
775
|
+
|
|
776
|
+
let errors = 0;
|
|
777
|
+
|
|
778
|
+
// if (confidence.mul(10_000).greaterThan(this.confThreshBps!)) {
|
|
779
|
+
// errors |= ErrorCode.TOO_UNCERTAIN;
|
|
780
|
+
// }
|
|
781
|
+
|
|
782
|
+
if (liquidity.lt(this.minLiquidity)) {
|
|
783
|
+
errors |= ErrorCode.NOT_ENOUGH_LIQUIDITY;
|
|
784
|
+
};
|
|
785
|
+
let err = new OracleErrors(errors);
|
|
786
|
+
|
|
787
|
+
let oraclePrice = new OraclePrice(price, confidence, currentTime);
|
|
788
|
+
return new OracleResult(
|
|
789
|
+
oraclePrice,
|
|
790
|
+
err
|
|
791
|
+
)
|
|
792
|
+
}
|
|
793
|
+
|
|
794
|
+
|
|
795
|
+
|
|
796
|
+
}
|
|
797
|
+
|
|
798
|
+
function mulRightShift(val: BN, mulBy: BN): BN {
|
|
799
|
+
return signedRightShift(val.mul(mulBy), 64, 256);
|
|
800
|
+
}
|
|
801
|
+
|
|
802
|
+
function signedLeftShift(n0: BN, shiftBy: number, bitWidth: number): BN {
|
|
803
|
+
const twosN0 = n0.toTwos(bitWidth).shln(shiftBy);
|
|
804
|
+
twosN0.imaskn(bitWidth + 1);
|
|
805
|
+
return twosN0.fromTwos(bitWidth);
|
|
806
|
+
}
|
|
807
|
+
|
|
808
|
+
function signedRightShift(n0: BN, shiftBy: number, bitWidth: number): BN {
|
|
809
|
+
const twoN0 = n0.toTwos(bitWidth).shrn(shiftBy);
|
|
810
|
+
twoN0.imaskn(bitWidth - shiftBy + 1);
|
|
811
|
+
return twoN0.fromTwos(bitWidth - shiftBy);
|
|
812
|
+
}
|