@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,614 @@
|
|
|
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 { ErrorCode, Oracle, OracleErrors, OraclePrice, OracleResult } from './oracle';
|
|
7
|
+
|
|
8
|
+
const CPMM_PROGRAM_ID = new PublicKey("CPMMoo8L3F4NbTegBCKVNunggL7H1ZpdTHKxQB5qKP1C");
|
|
9
|
+
const DEV_CPMM_PROGRAM_ID = new PublicKey("DRaycpLY18LhpbydsBWbVJtxpNv9oXPgjRSfpF2bWpYb");
|
|
10
|
+
|
|
11
|
+
enum Side {
|
|
12
|
+
Base,
|
|
13
|
+
Quote,
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
enum Quote {
|
|
17
|
+
Usdc,
|
|
18
|
+
Wsol,
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
class Observation {
|
|
22
|
+
timestamp: BN; // u64
|
|
23
|
+
cumT0Price: BN; // u128
|
|
24
|
+
cumT1Price: BN; // u128
|
|
25
|
+
constructor(params: {timestamp: BN, cumT0Price: BN, cumT1Price: BN}){
|
|
26
|
+
this.timestamp = params.timestamp;
|
|
27
|
+
this.cumT0Price = params.cumT0Price;
|
|
28
|
+
this.cumT1Price = params.cumT1Price;
|
|
29
|
+
}
|
|
30
|
+
static decode(data: Buffer, offset = 0): [Observation, number] {
|
|
31
|
+
|
|
32
|
+
const timestamp = new BN(
|
|
33
|
+
data.subarray(offset, offset+8),
|
|
34
|
+
"le"
|
|
35
|
+
);
|
|
36
|
+
|
|
37
|
+
const cumT0Price = new BN(
|
|
38
|
+
data.subarray(offset + 8, offset + 24),
|
|
39
|
+
'le'
|
|
40
|
+
);
|
|
41
|
+
|
|
42
|
+
const cumT1Price = new BN(
|
|
43
|
+
data.subarray(offset + 24, offset + 40),
|
|
44
|
+
'le'
|
|
45
|
+
);
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
return [
|
|
50
|
+
new Observation({
|
|
51
|
+
timestamp,
|
|
52
|
+
cumT0Price,
|
|
53
|
+
cumT1Price }),
|
|
54
|
+
offset + 40
|
|
55
|
+
];
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
sub(other: Observation): Observation {
|
|
61
|
+
if (!(other instanceof Observation)) {
|
|
62
|
+
throw new TypeError("Subtraction is only supported between Observation instances");
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
return new Observation({
|
|
66
|
+
timestamp: this.timestamp.sub(other.timestamp),
|
|
67
|
+
cumT0Price: this.cumT0Price.sub(other.cumT0Price),
|
|
68
|
+
cumT1Price: this.cumT1Price.sub(other.cumT1Price),
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
add(other: Observation): Observation {
|
|
73
|
+
if (!(other instanceof Observation)) {
|
|
74
|
+
throw new TypeError("Addition is only supported between Observation instances");
|
|
75
|
+
}
|
|
76
|
+
return new Observation({
|
|
77
|
+
timestamp: this.timestamp.add(other.timestamp),
|
|
78
|
+
cumT0Price: this.cumT0Price.add(other.cumT0Price),
|
|
79
|
+
cumT1Price: this.cumT1Price.add(other.cumT1Price),
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
getWeightedObservation(time: BN): Observation {
|
|
84
|
+
const cumT0Price = this.cumT0Price.mul(time).div(this.timestamp);
|
|
85
|
+
const cumT1Price = this.cumT1Price.mul(time).div(this.timestamp);
|
|
86
|
+
return new Observation({
|
|
87
|
+
timestamp: time,
|
|
88
|
+
cumT0Price,
|
|
89
|
+
cumT1Price
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
adjustToTimestamp(targetTimestamp: BN, observationPrev: Observation): Observation {
|
|
94
|
+
// delta = self.sub(prevPbservation)
|
|
95
|
+
const delta = this.sub(observationPrev);
|
|
96
|
+
|
|
97
|
+
// weightedDelta = delta.getWeightedObservation(targetTimestamp - self.blockTimestamp)
|
|
98
|
+
const timeForWeighted = targetTimestamp.sub(this.timestamp);
|
|
99
|
+
const weightedDelta = delta.getWeightedObservation(timeForWeighted);
|
|
100
|
+
|
|
101
|
+
// return self.add(weightedDelta)
|
|
102
|
+
return this.add(weightedDelta);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
public getTwap(side: Side): BN {
|
|
106
|
+
let cumPrice = new BN(0);
|
|
107
|
+
if(side === Side.Base)
|
|
108
|
+
cumPrice = this.cumT0Price;
|
|
109
|
+
else cumPrice = this.cumT1Price;
|
|
110
|
+
console.log("cumPrice", cumPrice.toString())
|
|
111
|
+
return cumPrice.div(this.timestamp);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
class ObservationState {
|
|
117
|
+
initialized : boolean;
|
|
118
|
+
observationIndex: number; //u16
|
|
119
|
+
poolId: PublicKey;
|
|
120
|
+
observations: Observation[];
|
|
121
|
+
lastUpdateTimestamp: BN; // u64
|
|
122
|
+
padding: BN[]; // [u64; 3]
|
|
123
|
+
|
|
124
|
+
constructor(params: {
|
|
125
|
+
initialized: boolean,
|
|
126
|
+
observationIndex: number,
|
|
127
|
+
poolId: PublicKey,
|
|
128
|
+
observations: Observation[],
|
|
129
|
+
lastUpdateTimestamp: BN,
|
|
130
|
+
padding: BN[]
|
|
131
|
+
}){
|
|
132
|
+
this.initialized = params.initialized;
|
|
133
|
+
this.observationIndex = params.observationIndex;
|
|
134
|
+
this.poolId = params.poolId;
|
|
135
|
+
this.observations = params.observations;
|
|
136
|
+
this.lastUpdateTimestamp = params.lastUpdateTimestamp;
|
|
137
|
+
this.padding = params.padding;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
static decode(data: Buffer, offset = 8): [ObservationState, number] {
|
|
141
|
+
let cursor = offset;
|
|
142
|
+
|
|
143
|
+
const initialized = data.readUInt8(cursor) !== 0;
|
|
144
|
+
cursor += 1;
|
|
145
|
+
|
|
146
|
+
const observationIndex = data.readUInt16LE(cursor);
|
|
147
|
+
cursor += 2;
|
|
148
|
+
|
|
149
|
+
const poolId = new PublicKey(data.subarray(cursor, cursor + 32));
|
|
150
|
+
cursor += 32;
|
|
151
|
+
|
|
152
|
+
const observations: Observation[] = [];
|
|
153
|
+
for (let i = 0; i < 100; i++) {
|
|
154
|
+
let obs: Observation;
|
|
155
|
+
[obs, cursor] = Observation.decode(data, cursor);
|
|
156
|
+
observations.push(obs);
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
const lastUpdateTimestamp = new BN(data.subarray(cursor, cursor + 8), "le");
|
|
160
|
+
cursor += 8;
|
|
161
|
+
|
|
162
|
+
const padding: BN[] = [];
|
|
163
|
+
for (let i = 0; i < 4; i++) {
|
|
164
|
+
padding.push(new BN(data.subarray(cursor, cursor + 8), "le"));
|
|
165
|
+
cursor += 8;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
return [
|
|
169
|
+
new ObservationState({
|
|
170
|
+
initialized,
|
|
171
|
+
observationIndex,
|
|
172
|
+
poolId,
|
|
173
|
+
observations,
|
|
174
|
+
lastUpdateTimestamp,
|
|
175
|
+
padding
|
|
176
|
+
}),
|
|
177
|
+
cursor
|
|
178
|
+
]
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
class PoolState {
|
|
183
|
+
ammConfig: PublicKey;
|
|
184
|
+
poolCreator: PublicKey;
|
|
185
|
+
token0Vault: PublicKey;
|
|
186
|
+
token1Vault: PublicKey;
|
|
187
|
+
lpMint: PublicKey;
|
|
188
|
+
token0Mint: PublicKey;
|
|
189
|
+
token1Mint: PublicKey;
|
|
190
|
+
token0Program: PublicKey;
|
|
191
|
+
token1Program: PublicKey;
|
|
192
|
+
observationKey: PublicKey;
|
|
193
|
+
authBump: number; // u8
|
|
194
|
+
status: number; // u8
|
|
195
|
+
lpMintDecimals: number; // u8
|
|
196
|
+
mint0Decimals: number; // u8
|
|
197
|
+
mint1Decimals: number; // u8
|
|
198
|
+
lpSupply: BN; // u64
|
|
199
|
+
protocolFeesToken0: BN; // u64
|
|
200
|
+
protocolFeesToken1: BN; // u64
|
|
201
|
+
fundFeesToken0: BN; // u64
|
|
202
|
+
fundFeesToken1: BN; // u64
|
|
203
|
+
openTime: BN; // u64
|
|
204
|
+
recentEpoch: BN; // u64
|
|
205
|
+
creatorFeeOn: number; //u8
|
|
206
|
+
enableCreatorFee: boolean;
|
|
207
|
+
padding1: number[]; // [u8; 6]
|
|
208
|
+
creatorFeesToken0: BN; // u64
|
|
209
|
+
creatorFeesToken1: BN; // u64
|
|
210
|
+
padding: BN[]; // [u64; 28]
|
|
211
|
+
|
|
212
|
+
constructor(
|
|
213
|
+
params: {
|
|
214
|
+
ammConfig: PublicKey;
|
|
215
|
+
poolCreator: PublicKey;
|
|
216
|
+
token0Vault: PublicKey;
|
|
217
|
+
token1Vault: PublicKey;
|
|
218
|
+
lpMint: PublicKey;
|
|
219
|
+
token0Mint: PublicKey;
|
|
220
|
+
token1Mint: PublicKey;
|
|
221
|
+
token0Program: PublicKey;
|
|
222
|
+
token1Program: PublicKey;
|
|
223
|
+
observationKey: PublicKey;
|
|
224
|
+
authBump: number; // u8
|
|
225
|
+
status: number; // u8
|
|
226
|
+
lpMintDecimals: number; // u8
|
|
227
|
+
mint0Decimals: number; // u8
|
|
228
|
+
mint1Decimals: number; // u8
|
|
229
|
+
lpSupply: BN; // u64
|
|
230
|
+
protocolFeesToken0: BN; // u64
|
|
231
|
+
protocolFeesToken1: BN; // u64
|
|
232
|
+
fundFeesToken0: BN; // u64
|
|
233
|
+
fundFeesToken1: BN; // u64
|
|
234
|
+
openTime: BN; // u64
|
|
235
|
+
recentEpoch: BN; // u64
|
|
236
|
+
creatorFeeOn: number; //u8
|
|
237
|
+
enableCreatorFee: boolean;
|
|
238
|
+
padding1: number[]; // [u8; 6]
|
|
239
|
+
creatorFeesToken0: BN; // u64
|
|
240
|
+
creatorFeesToken1: BN; // u64
|
|
241
|
+
padding: BN[]; // [u64; 28]
|
|
242
|
+
}){
|
|
243
|
+
this.ammConfig = params.ammConfig;
|
|
244
|
+
this.poolCreator = params.poolCreator;
|
|
245
|
+
this.token0Vault = params.token0Vault;
|
|
246
|
+
this.token1Vault = params.token1Vault;
|
|
247
|
+
this.lpMint = params.lpMint;
|
|
248
|
+
this.token0Mint = params.token0Mint;
|
|
249
|
+
this.token1Mint = params.token1Mint;
|
|
250
|
+
this.token0Program = params.token0Program;
|
|
251
|
+
this.token1Program = params.token1Program;
|
|
252
|
+
this.observationKey = params.observationKey;
|
|
253
|
+
this.authBump = params.authBump; // u8
|
|
254
|
+
this.status = params.status; // u8
|
|
255
|
+
this.lpMintDecimals = params.lpMintDecimals; // u8
|
|
256
|
+
this.mint0Decimals = params.mint0Decimals; // u8
|
|
257
|
+
this.mint1Decimals = params.mint1Decimals; // u8
|
|
258
|
+
this.lpSupply = params.lpSupply; // u64
|
|
259
|
+
this.protocolFeesToken0 = params.protocolFeesToken0; // u64
|
|
260
|
+
this.protocolFeesToken1 = params.protocolFeesToken1; // u64
|
|
261
|
+
this.fundFeesToken0 = params.fundFeesToken0; // u64
|
|
262
|
+
this.fundFeesToken1 = params.fundFeesToken1; // u64
|
|
263
|
+
this.openTime = params.openTime; // u64
|
|
264
|
+
this.recentEpoch = params.recentEpoch; // u64
|
|
265
|
+
this.creatorFeeOn = params.creatorFeeOn; //u8
|
|
266
|
+
this.enableCreatorFee = params.enableCreatorFee;
|
|
267
|
+
this.padding1 = params.padding1; // [u8; 6]
|
|
268
|
+
this.creatorFeesToken0 = params.creatorFeesToken0; // u64
|
|
269
|
+
this.creatorFeesToken1 = params.creatorFeesToken1; // u64
|
|
270
|
+
this.padding = params.padding // [u64; 28]
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
static decode(data: Buffer, offset: number = 8): [PoolState, number] {
|
|
274
|
+
let cursor = offset;
|
|
275
|
+
|
|
276
|
+
const ammConfig = new PublicKey(data.subarray(cursor, cursor + 32));
|
|
277
|
+
cursor += 32;
|
|
278
|
+
|
|
279
|
+
const poolCreator = new PublicKey(data.subarray(cursor, cursor + 32));
|
|
280
|
+
cursor += 32;
|
|
281
|
+
|
|
282
|
+
const token0Vault = new PublicKey(data.subarray(cursor, cursor + 32));
|
|
283
|
+
cursor += 32;
|
|
284
|
+
|
|
285
|
+
const token1Vault = new PublicKey(data.subarray(cursor, cursor + 32));
|
|
286
|
+
cursor += 32;
|
|
287
|
+
|
|
288
|
+
const lpMint = new PublicKey(data.subarray(cursor, cursor + 32));
|
|
289
|
+
cursor += 32;
|
|
290
|
+
|
|
291
|
+
const token0Mint = new PublicKey(data.subarray(cursor, cursor + 32));
|
|
292
|
+
cursor += 32;
|
|
293
|
+
|
|
294
|
+
const token1Mint = new PublicKey(data.subarray(cursor, cursor + 32));
|
|
295
|
+
cursor += 32;
|
|
296
|
+
|
|
297
|
+
const token0Program = new PublicKey(data.subarray(cursor, cursor + 32));
|
|
298
|
+
cursor += 32;
|
|
299
|
+
|
|
300
|
+
const token1Program = new PublicKey(data.subarray(cursor, cursor + 32));
|
|
301
|
+
cursor += 32;
|
|
302
|
+
|
|
303
|
+
const observationKey = new PublicKey(data.subarray(cursor, cursor + 32));
|
|
304
|
+
cursor += 32;
|
|
305
|
+
|
|
306
|
+
const authBump = data.readUInt8(cursor);
|
|
307
|
+
cursor += 1;
|
|
308
|
+
|
|
309
|
+
const status = data.readUInt8(cursor);
|
|
310
|
+
cursor += 1;
|
|
311
|
+
|
|
312
|
+
const lpMintDecimals = data.readUInt8(cursor);
|
|
313
|
+
cursor += 1;
|
|
314
|
+
|
|
315
|
+
const mint0Decimals = data.readUInt8(cursor);
|
|
316
|
+
cursor += 1;
|
|
317
|
+
|
|
318
|
+
const mint1Decimals = data.readUInt8(cursor);
|
|
319
|
+
cursor += 1;
|
|
320
|
+
|
|
321
|
+
const lpSupply = new BN(data.subarray(cursor, cursor + 8), "le");
|
|
322
|
+
cursor += 8;
|
|
323
|
+
|
|
324
|
+
const protocolFeesToken0 = new BN(data.subarray(cursor, cursor + 8), "le");
|
|
325
|
+
cursor += 8;
|
|
326
|
+
|
|
327
|
+
const protocolFeesToken1 = new BN(data.subarray(cursor, cursor + 8), "le");
|
|
328
|
+
cursor += 8;
|
|
329
|
+
|
|
330
|
+
const fundFeesToken0 = new BN(data.subarray(cursor, cursor + 8), "le");
|
|
331
|
+
cursor += 8;
|
|
332
|
+
|
|
333
|
+
const fundFeesToken1 = new BN(data.subarray(cursor, cursor + 8), "le");
|
|
334
|
+
cursor += 8;
|
|
335
|
+
|
|
336
|
+
const openTime = new BN(data.subarray(cursor, cursor + 8), "le");
|
|
337
|
+
cursor += 8;
|
|
338
|
+
|
|
339
|
+
const recentEpoch = new BN(data.subarray(cursor, cursor + 8), "le");
|
|
340
|
+
cursor += 8;
|
|
341
|
+
|
|
342
|
+
const creatorFeeOn = data.readUInt8(cursor);
|
|
343
|
+
cursor += 1;
|
|
344
|
+
|
|
345
|
+
const enableCreatorFee = !!data.readUInt8(cursor);
|
|
346
|
+
cursor += 1;
|
|
347
|
+
|
|
348
|
+
const padding1: number[] = [];
|
|
349
|
+
for (let i = 0; i < 6; i++) {
|
|
350
|
+
padding1.push(data.readUInt8(cursor));
|
|
351
|
+
cursor += 1;
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
const creatorFeesToken0 = new BN(data.subarray(cursor, cursor + 8), "le");
|
|
355
|
+
cursor += 8;
|
|
356
|
+
|
|
357
|
+
const creatorFeesToken1 = new BN(data.subarray(cursor, cursor + 8), "le");
|
|
358
|
+
cursor += 8;
|
|
359
|
+
|
|
360
|
+
const padding: BN[] = [];
|
|
361
|
+
for (let i = 0; i < 28; i++) {
|
|
362
|
+
padding.push(new BN(data.subarray(cursor, cursor + 8), "le"));
|
|
363
|
+
cursor += 8;
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
return [
|
|
367
|
+
new PoolState({
|
|
368
|
+
ammConfig,
|
|
369
|
+
poolCreator,
|
|
370
|
+
token0Vault,
|
|
371
|
+
token1Vault,
|
|
372
|
+
lpMint,
|
|
373
|
+
token0Mint,
|
|
374
|
+
token1Mint,
|
|
375
|
+
token0Program,
|
|
376
|
+
token1Program,
|
|
377
|
+
observationKey,
|
|
378
|
+
authBump,
|
|
379
|
+
status,
|
|
380
|
+
lpMintDecimals,
|
|
381
|
+
mint0Decimals,
|
|
382
|
+
mint1Decimals,
|
|
383
|
+
lpSupply,
|
|
384
|
+
protocolFeesToken0,
|
|
385
|
+
protocolFeesToken1,
|
|
386
|
+
fundFeesToken0,
|
|
387
|
+
fundFeesToken1,
|
|
388
|
+
openTime,
|
|
389
|
+
recentEpoch,
|
|
390
|
+
creatorFeeOn,
|
|
391
|
+
enableCreatorFee,
|
|
392
|
+
padding1,
|
|
393
|
+
creatorFeesToken0,
|
|
394
|
+
creatorFeesToken1,
|
|
395
|
+
padding,
|
|
396
|
+
}),
|
|
397
|
+
cursor,
|
|
398
|
+
];
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
export class RaydiumCPMMOracle extends Oracle{
|
|
403
|
+
poolId: PublicKey;
|
|
404
|
+
quoteToken: Quote;
|
|
405
|
+
poolState: PoolState;
|
|
406
|
+
side: Side;
|
|
407
|
+
observationState: ObservationState;
|
|
408
|
+
|
|
409
|
+
private constructor(params: {
|
|
410
|
+
poolId: PublicKey;
|
|
411
|
+
quoteToken: Quote;
|
|
412
|
+
poolState: PoolState;
|
|
413
|
+
side: Side;
|
|
414
|
+
observationState: ObservationState,
|
|
415
|
+
weight: number,
|
|
416
|
+
confThreshBps?: number,
|
|
417
|
+
stalenessThresh?: number,
|
|
418
|
+
volatilityThresh?: number | Decimal,
|
|
419
|
+
minLiquidity?: number | Decimal,
|
|
420
|
+
stalenessConfRateBps?: number
|
|
421
|
+
}){
|
|
422
|
+
super(
|
|
423
|
+
params.weight,
|
|
424
|
+
params.confThreshBps,
|
|
425
|
+
params.stalenessThresh,
|
|
426
|
+
params.volatilityThresh,
|
|
427
|
+
params.minLiquidity,
|
|
428
|
+
params.stalenessConfRateBps
|
|
429
|
+
);
|
|
430
|
+
|
|
431
|
+
this.poolId = params.poolId;
|
|
432
|
+
this.quoteToken = params.quoteToken;
|
|
433
|
+
this.poolState = params.poolState;
|
|
434
|
+
this.side = params.side;
|
|
435
|
+
this.observationState = params.observationState;
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
static async create(params: {
|
|
439
|
+
connection: Connection,
|
|
440
|
+
poolId: PublicKey,
|
|
441
|
+
quoteToken: Quote,
|
|
442
|
+
side: Side,
|
|
443
|
+
weight: number,
|
|
444
|
+
confThreshBps?: number,
|
|
445
|
+
stalenessThresh?: number,
|
|
446
|
+
volatilityThresh?: number | Decimal,
|
|
447
|
+
minLiquidity?: number | Decimal,
|
|
448
|
+
stalenessConfRateBps?: number
|
|
449
|
+
}): Promise<RaydiumCPMMOracle> {
|
|
450
|
+
const { connection, poolId } = params;
|
|
451
|
+
|
|
452
|
+
// Fetch pooState
|
|
453
|
+
const poolAccountInfo = await connection.getAccountInfo(new PublicKey(poolId));
|
|
454
|
+
if (!poolAccountInfo) throw new Error("Pool account not found");
|
|
455
|
+
const [poolState, _] = PoolState.decode(poolAccountInfo.data, 8);
|
|
456
|
+
|
|
457
|
+
// Fetch observationState from poolState
|
|
458
|
+
const obsPubkey = poolState.observationKey;
|
|
459
|
+
const obsAccountInfo = await connection.getAccountInfo(new PublicKey(obsPubkey));
|
|
460
|
+
if (!obsAccountInfo) throw new Error("Observation account not found");
|
|
461
|
+
const [observationState, __] = ObservationState.decode(obsAccountInfo.data, 8);
|
|
462
|
+
|
|
463
|
+
|
|
464
|
+
return new RaydiumCPMMOracle({
|
|
465
|
+
poolId: poolId,
|
|
466
|
+
quoteToken: params.quoteToken,
|
|
467
|
+
poolState: poolState,
|
|
468
|
+
side: params.side,
|
|
469
|
+
observationState: observationState,
|
|
470
|
+
weight: params.weight,
|
|
471
|
+
confThreshBps: params.confThreshBps,
|
|
472
|
+
stalenessThresh: params.stalenessThresh,
|
|
473
|
+
volatilityThresh: params.volatilityThresh,
|
|
474
|
+
minLiquidity: params.minLiquidity,
|
|
475
|
+
stalenessConfRateBps: params.stalenessConfRateBps
|
|
476
|
+
});
|
|
477
|
+
}
|
|
478
|
+
|
|
479
|
+
public setSide(side: Side) {
|
|
480
|
+
this.side = side;
|
|
481
|
+
}
|
|
482
|
+
|
|
483
|
+
static deriveObservationKey(poolId: PublicKey): [PublicKey, number] {
|
|
484
|
+
const seeds = [
|
|
485
|
+
Buffer.from("observation"),
|
|
486
|
+
poolId.toBuffer(),
|
|
487
|
+
];
|
|
488
|
+
return PublicKey.findProgramAddressSync(seeds, CPMM_PROGRAM_ID);
|
|
489
|
+
};
|
|
490
|
+
|
|
491
|
+
getObservationAtIndex(index: number) {
|
|
492
|
+
return this.observationState.observations[index];
|
|
493
|
+
}
|
|
494
|
+
|
|
495
|
+
getObservationAtTimestamp(timestamp: BN, startIndex: number): Observation {
|
|
496
|
+
let observationCurrent = this.getObservationAtIndex(startIndex);
|
|
497
|
+
let index = startIndex;
|
|
498
|
+
// Loop backwards until we find the observation <= timestamp
|
|
499
|
+
while (observationCurrent.timestamp.gt(timestamp)) {
|
|
500
|
+
index = (index - 1 + 100) % 100;
|
|
501
|
+
observationCurrent = this.getObservationAtIndex(index);
|
|
502
|
+
|
|
503
|
+
if (index === startIndex) {
|
|
504
|
+
throw Error("Observations do not go back far enough in time");
|
|
505
|
+
break; // looped all the way around
|
|
506
|
+
}
|
|
507
|
+
}
|
|
508
|
+
|
|
509
|
+
// Previous index for interpolation
|
|
510
|
+
const prevIndex = (index - 1 + 100) % 100;
|
|
511
|
+
const observationPrev = this.getObservationAtIndex(prevIndex);
|
|
512
|
+
|
|
513
|
+
// Adjust current observation to the target timestamp
|
|
514
|
+
const result = observationCurrent.adjustToTimestamp(timestamp, observationPrev);
|
|
515
|
+
return result;
|
|
516
|
+
}
|
|
517
|
+
|
|
518
|
+
getDeltaObservations(currentTime: BN): Observation[] {
|
|
519
|
+
|
|
520
|
+
const obsIndex = this.observationState.observationIndex;
|
|
521
|
+
const observationCurrent = this.getObservationAtTimestamp(currentTime, obsIndex);
|
|
522
|
+
const observation30s = this.getObservationAtTimestamp(new BN(currentTime.sub(new BN(30))), obsIndex);
|
|
523
|
+
const delta30s = observationCurrent.sub(observation30s);
|
|
524
|
+
|
|
525
|
+
const observation2min = this.getObservationAtTimestamp(new BN(currentTime.sub(new BN(120))), obsIndex);
|
|
526
|
+
const delta2min = observationCurrent.sub(observation2min);
|
|
527
|
+
|
|
528
|
+
const observation5min = this.getObservationAtTimestamp(new BN(currentTime.sub(new BN(300))), obsIndex);
|
|
529
|
+
const delta5min = observationCurrent.sub(observation5min);
|
|
530
|
+
|
|
531
|
+
const observation20min = this.getObservationAtTimestamp(new BN(currentTime.sub(new BN(1200))), obsIndex);
|
|
532
|
+
const delta20min = observationCurrent.sub(observation20min);
|
|
533
|
+
|
|
534
|
+
return [delta30s,delta2min, delta5min, delta20min];
|
|
535
|
+
};
|
|
536
|
+
|
|
537
|
+
getDecimals(): number {
|
|
538
|
+
let dec;
|
|
539
|
+
if(this.side === Side.Base)
|
|
540
|
+
dec = this.poolState.mint0Decimals - this.poolState.mint1Decimals;
|
|
541
|
+
else dec = this.poolState.mint1Decimals - this.poolState.mint0Decimals;
|
|
542
|
+
return dec;
|
|
543
|
+
}
|
|
544
|
+
|
|
545
|
+
getTwap30sec(currentTime: BN): Decimal {
|
|
546
|
+
let observation = this.getDeltaObservations(currentTime)[0];
|
|
547
|
+
let twapScaled = new Decimal(observation.getTwap(this.side).toString()).div(2**32);
|
|
548
|
+
let twap = new Decimal(twapScaled.toString()).div(10**this.getDecimals());
|
|
549
|
+
return twap;
|
|
550
|
+
}
|
|
551
|
+
|
|
552
|
+
getTwap2min(currentTime: BN): Decimal {
|
|
553
|
+
let observation = this.getDeltaObservations(currentTime)[1];
|
|
554
|
+
let twapScaled = new Decimal(observation.getTwap(this.side).toString()).div(2**32);
|
|
555
|
+
let twap = new Decimal(twapScaled.toString()).div(10**this.getDecimals())
|
|
556
|
+
return twap;
|
|
557
|
+
}
|
|
558
|
+
|
|
559
|
+
getTwap5min(currentTime: BN): Decimal {
|
|
560
|
+
let observation = this.getDeltaObservations(currentTime)[2];
|
|
561
|
+
let twapScaled = new Decimal(observation.getTwap(this.side).toString()).div(2**32);
|
|
562
|
+
let twap = new Decimal(twapScaled.toString()).div(10**this.getDecimals())
|
|
563
|
+
return twap;
|
|
564
|
+
}
|
|
565
|
+
|
|
566
|
+
getTwap20min(currentTime: BN): Decimal {
|
|
567
|
+
let observation = this.getDeltaObservations(currentTime)[3];
|
|
568
|
+
let twapScaled = new Decimal(observation.getTwap(this.side).toString()).div(2**32);
|
|
569
|
+
let twap = new Decimal(twapScaled.toString()).div(10**this.getDecimals())
|
|
570
|
+
return twap;
|
|
571
|
+
}
|
|
572
|
+
|
|
573
|
+
getConfidence(currentTime: BN): Decimal {
|
|
574
|
+
|
|
575
|
+
const twapNow = this.getTwap30sec(currentTime);
|
|
576
|
+
|
|
577
|
+
const diff2Min = twapNow.sub(this.getTwap2min(currentTime)).abs();
|
|
578
|
+
const diff5Min = twapNow.sub(this.getTwap5min(currentTime)).abs();
|
|
579
|
+
const diff20Min = twapNow.sub(this.getTwap20min(currentTime)).abs();
|
|
580
|
+
|
|
581
|
+
let max = diff2Min;
|
|
582
|
+
if (diff5Min.gt(max)) max = diff5Min;
|
|
583
|
+
if (diff20Min.gt(max)) max = diff20Min;
|
|
584
|
+
|
|
585
|
+
return max;
|
|
586
|
+
}
|
|
587
|
+
|
|
588
|
+
async fetch(): Promise<OracleResult> {
|
|
589
|
+
const currentTime = new BN(Math.floor(Date.now() / 1000)); // current UNIX timestamp in seconds
|
|
590
|
+
|
|
591
|
+
const confidence = this.getConfidence(currentTime);
|
|
592
|
+
|
|
593
|
+
// const liquidity = this.poolState.liquidity; // assuming poolState is already the decoded data
|
|
594
|
+
const price = this.getTwap30sec(currentTime);
|
|
595
|
+
|
|
596
|
+
let errors = 0;
|
|
597
|
+
|
|
598
|
+
// if (confidence.mul(10_000).greaterThan(this.confThreshBps!)) {
|
|
599
|
+
// errors |= ErrorCode.TOO_UNCERTAIN;
|
|
600
|
+
// }
|
|
601
|
+
|
|
602
|
+
// if (liquidity.lt(this.minLiquidity)) {
|
|
603
|
+
// errors |= ErrorCode.NOT_ENOUGH_LIQUIDITY;
|
|
604
|
+
// };
|
|
605
|
+
let err = new OracleErrors(errors);
|
|
606
|
+
|
|
607
|
+
let oraclePrice = new OraclePrice(price, confidence, currentTime);
|
|
608
|
+
return new OracleResult(
|
|
609
|
+
oraclePrice,
|
|
610
|
+
err
|
|
611
|
+
)
|
|
612
|
+
}
|
|
613
|
+
|
|
614
|
+
}
|
|
File without changes
|