@drift-labs/sdk 2.85.0-beta.11 → 2.85.0-beta.12
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/VERSION +1 -1
- package/lib/addresses/pda.d.ts +1 -0
- package/lib/addresses/pda.js +8 -1
- package/lib/adminClient.d.ts +2 -0
- package/lib/adminClient.js +22 -0
- package/lib/config.d.ts +3 -0
- package/lib/config.js +4 -1
- package/lib/constants/perpMarkets.d.ts +1 -0
- package/lib/constants/perpMarkets.js +57 -0
- package/lib/constants/spotMarkets.d.ts +1 -0
- package/lib/constants/spotMarkets.js +20 -0
- package/lib/driftClient.d.ts +24 -1
- package/lib/driftClient.js +116 -0
- package/lib/idl/drift.json +160 -1
- package/lib/math/oracles.d.ts +2 -0
- package/lib/math/oracles.js +14 -1
- package/lib/oracles/pythPullClient.js +1 -1
- package/lib/tx/baseTxSender.js +1 -0
- package/lib/util/pythPullOracleUtils.d.ts +2 -0
- package/lib/util/pythPullOracleUtils.js +15 -0
- package/package.json +2 -1
- package/src/addresses/pda.ts +13 -0
- package/src/adminClient.ts +39 -0
- package/src/config.ts +6 -0
- package/src/constants/perpMarkets.ts +115 -0
- package/src/constants/spotMarkets.ts +41 -0
- package/src/driftClient.ts +263 -1
- package/src/idl/drift.json +160 -1
- package/src/math/oracles.ts +17 -0
- package/src/oracles/pythPullClient.ts +2 -3
- package/src/tx/baseTxSender.ts +1 -0
- package/src/util/pythPullOracleUtils.ts +11 -0
|
@@ -21,6 +21,7 @@ export type SpotMarketConfig = {
|
|
|
21
21
|
serumMarket?: PublicKey;
|
|
22
22
|
phoenixMarket?: PublicKey;
|
|
23
23
|
launchTs?: number;
|
|
24
|
+
pythFeedId?: string;
|
|
24
25
|
};
|
|
25
26
|
|
|
26
27
|
export const WRAPPED_SOL_MINT = new PublicKey(
|
|
@@ -36,6 +37,8 @@ export const DevnetSpotMarkets: SpotMarketConfig[] = [
|
|
|
36
37
|
mint: new PublicKey('8zGuJQqwhZafTah7Uc7Z4tXRnguqkn5KLFAP8oV6PHe2'),
|
|
37
38
|
precision: new BN(10).pow(SIX),
|
|
38
39
|
precisionExp: SIX,
|
|
40
|
+
pythFeedId:
|
|
41
|
+
'0xeaa020c61cc479712813461ce153894a96a6c00b21ed0cfc2798d1f9a9e9c94a',
|
|
39
42
|
},
|
|
40
43
|
{
|
|
41
44
|
symbol: 'SOL',
|
|
@@ -49,6 +52,8 @@ export const DevnetSpotMarkets: SpotMarketConfig[] = [
|
|
|
49
52
|
phoenixMarket: new PublicKey(
|
|
50
53
|
'78ehDnHgbkFxqXZwdFxa8HK7saX58GymeX2wNGdkqYLp'
|
|
51
54
|
),
|
|
55
|
+
pythFeedId:
|
|
56
|
+
'0xef0d8b6fda2ceba41da15d4095d1da392a0d2f8ed0c6c7bc0f4cfac8c280b56d',
|
|
52
57
|
},
|
|
53
58
|
{
|
|
54
59
|
symbol: 'BTC',
|
|
@@ -59,6 +64,8 @@ export const DevnetSpotMarkets: SpotMarketConfig[] = [
|
|
|
59
64
|
precision: new BN(10).pow(SIX),
|
|
60
65
|
precisionExp: SIX,
|
|
61
66
|
serumMarket: new PublicKey('AGsmbVu3MS9u68GEYABWosQQCZwmLcBHu4pWEuBYH7Za'),
|
|
67
|
+
pythFeedId:
|
|
68
|
+
'0xe62df6c8b4a85fe1a67db44dc12de5db330f7ac66b72dc658afedf0f4a415b43',
|
|
62
69
|
},
|
|
63
70
|
];
|
|
64
71
|
|
|
@@ -71,6 +78,8 @@ export const MainnetSpotMarkets: SpotMarketConfig[] = [
|
|
|
71
78
|
mint: new PublicKey('EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v'),
|
|
72
79
|
precision: QUOTE_PRECISION,
|
|
73
80
|
precisionExp: QUOTE_PRECISION_EXP,
|
|
81
|
+
pythFeedId:
|
|
82
|
+
'0xeaa020c61cc479712813461ce153894a96a6c00b21ed0cfc2798d1f9a9e9c94a',
|
|
74
83
|
},
|
|
75
84
|
{
|
|
76
85
|
symbol: 'SOL',
|
|
@@ -84,6 +93,8 @@ export const MainnetSpotMarkets: SpotMarketConfig[] = [
|
|
|
84
93
|
phoenixMarket: new PublicKey(
|
|
85
94
|
'4DoNfFBfF7UokCC2FQzriy7yHK6DY6NVdYpuekQ5pRgg'
|
|
86
95
|
),
|
|
96
|
+
pythFeedId:
|
|
97
|
+
'0xef0d8b6fda2ceba41da15d4095d1da392a0d2f8ed0c6c7bc0f4cfac8c280b56d',
|
|
87
98
|
},
|
|
88
99
|
{
|
|
89
100
|
symbol: 'mSOL',
|
|
@@ -94,6 +105,8 @@ export const MainnetSpotMarkets: SpotMarketConfig[] = [
|
|
|
94
105
|
precision: new BN(10).pow(NINE),
|
|
95
106
|
precisionExp: NINE,
|
|
96
107
|
serumMarket: new PublicKey('9Lyhks5bQQxb9EyyX55NtgKQzpM4WK7JCmeaWuQ5MoXD'),
|
|
108
|
+
pythFeedId:
|
|
109
|
+
'0xc2289a6a43d2ce91c6f55caec370f4acc38a2ed477f58813334c6d03749ff2a4',
|
|
97
110
|
},
|
|
98
111
|
{
|
|
99
112
|
symbol: 'wBTC',
|
|
@@ -104,6 +117,8 @@ export const MainnetSpotMarkets: SpotMarketConfig[] = [
|
|
|
104
117
|
precision: new BN(10).pow(EIGHT),
|
|
105
118
|
precisionExp: EIGHT,
|
|
106
119
|
serumMarket: new PublicKey('3BAKsQd3RuhZKES2DGysMhjBdwjZYKYmxRqnSMtZ4KSN'),
|
|
120
|
+
pythFeedId:
|
|
121
|
+
'0xe62df6c8b4a85fe1a67db44dc12de5db330f7ac66b72dc658afedf0f4a415b43',
|
|
107
122
|
},
|
|
108
123
|
{
|
|
109
124
|
symbol: 'wETH',
|
|
@@ -117,6 +132,8 @@ export const MainnetSpotMarkets: SpotMarketConfig[] = [
|
|
|
117
132
|
phoenixMarket: new PublicKey(
|
|
118
133
|
'Ew3vFDdtdGrknJAVVfraxCA37uNJtimXYPY4QjnfhFHH'
|
|
119
134
|
),
|
|
135
|
+
pythFeedId:
|
|
136
|
+
'0xff61491a931112ddf1bd8147cd1b641375f79f5825126d665480874634fd0ace',
|
|
120
137
|
},
|
|
121
138
|
{
|
|
122
139
|
symbol: 'USDT',
|
|
@@ -127,6 +144,8 @@ export const MainnetSpotMarkets: SpotMarketConfig[] = [
|
|
|
127
144
|
precision: QUOTE_PRECISION,
|
|
128
145
|
precisionExp: QUOTE_PRECISION_EXP,
|
|
129
146
|
serumMarket: new PublicKey('B2na8Awyd7cpC59iEU43FagJAPLigr3AP3s38KM982bu'),
|
|
147
|
+
pythFeedId:
|
|
148
|
+
'0x2b89b9dc8fdf9f34709a5b106b472f0f39bb6ca9ce04b0fd7f2e971688e2e53b',
|
|
130
149
|
},
|
|
131
150
|
{
|
|
132
151
|
symbol: 'jitoSOL',
|
|
@@ -140,6 +159,8 @@ export const MainnetSpotMarkets: SpotMarketConfig[] = [
|
|
|
140
159
|
phoenixMarket: new PublicKey(
|
|
141
160
|
'5LQLfGtqcC5rm2WuGxJf4tjqYmDjsQAbKo2AMLQ8KB7p'
|
|
142
161
|
),
|
|
162
|
+
pythFeedId:
|
|
163
|
+
'0x67be9f519b95cf24338801051f9a808eff0a578ccb388db73b7f6fe1de019ffb',
|
|
143
164
|
},
|
|
144
165
|
{
|
|
145
166
|
symbol: 'PYTH',
|
|
@@ -153,6 +174,8 @@ export const MainnetSpotMarkets: SpotMarketConfig[] = [
|
|
|
153
174
|
phoenixMarket: new PublicKey(
|
|
154
175
|
'2sTMN9A1D1qeZLF95XQgJCUPiKe5DiV52jLfZGqMP46m'
|
|
155
176
|
),
|
|
177
|
+
pythFeedId:
|
|
178
|
+
'0x0bbf28e9a841a1cc788f6a361b17ca072d0ea3098a1e5df1c3922d06719579ff',
|
|
156
179
|
},
|
|
157
180
|
{
|
|
158
181
|
symbol: 'bSOL',
|
|
@@ -163,6 +186,8 @@ export const MainnetSpotMarkets: SpotMarketConfig[] = [
|
|
|
163
186
|
precision: new BN(10).pow(NINE),
|
|
164
187
|
precisionExp: NINE,
|
|
165
188
|
serumMarket: new PublicKey('ARjaHVxGCQfTvvKjLd7U7srvk6orthZSE6uqWchCczZc'),
|
|
189
|
+
pythFeedId:
|
|
190
|
+
'0x89875379e70f8fbadc17aef315adf3a8d5d160b811435537e03c97e8aac97d9c',
|
|
166
191
|
},
|
|
167
192
|
{
|
|
168
193
|
symbol: 'JTO',
|
|
@@ -176,6 +201,8 @@ export const MainnetSpotMarkets: SpotMarketConfig[] = [
|
|
|
176
201
|
phoenixMarket: new PublicKey(
|
|
177
202
|
'BRLLmdtPGuuFn3BU6orYw4KHaohAEptBToi3dwRUnHQZ'
|
|
178
203
|
),
|
|
204
|
+
pythFeedId:
|
|
205
|
+
'0xb43660a5f790c69354b0729a5ef9d50d68f1df92107540210b9cccba1f947cc2',
|
|
179
206
|
},
|
|
180
207
|
{
|
|
181
208
|
symbol: 'WIF',
|
|
@@ -189,6 +216,8 @@ export const MainnetSpotMarkets: SpotMarketConfig[] = [
|
|
|
189
216
|
phoenixMarket: new PublicKey(
|
|
190
217
|
'6ojSigXF7nDPyhFRgmn3V9ywhYseKF9J32ZrranMGVSX'
|
|
191
218
|
),
|
|
219
|
+
pythFeedId:
|
|
220
|
+
'0x4ca4beeca86f0d164160323817a4e42b10010a724c2217c6ee41b54cd4cc61fc',
|
|
192
221
|
},
|
|
193
222
|
{
|
|
194
223
|
symbol: 'JUP',
|
|
@@ -202,6 +231,8 @@ export const MainnetSpotMarkets: SpotMarketConfig[] = [
|
|
|
202
231
|
'2pspvjWWaf3dNgt3jsgSzFCNvMGPb7t8FrEYvLGjvcCe'
|
|
203
232
|
),
|
|
204
233
|
launchTs: 1706731200000,
|
|
234
|
+
pythFeedId:
|
|
235
|
+
'0x0a0408d619e9380abad35060f9192039ed5042fa6f82301d0e48bb52be830996',
|
|
205
236
|
},
|
|
206
237
|
{
|
|
207
238
|
symbol: 'RNDR',
|
|
@@ -213,6 +244,8 @@ export const MainnetSpotMarkets: SpotMarketConfig[] = [
|
|
|
213
244
|
precisionExp: EIGHT,
|
|
214
245
|
serumMarket: new PublicKey('2m7ZLEKtxWF29727DSb5D91erpXPUY1bqhRWRC3wQX7u'),
|
|
215
246
|
launchTs: 1708964021000,
|
|
247
|
+
pythFeedId:
|
|
248
|
+
'0xab7347771135fc733f8f38db462ba085ed3309955f42554a14fa13e855ac0e2f',
|
|
216
249
|
},
|
|
217
250
|
{
|
|
218
251
|
symbol: 'W',
|
|
@@ -226,6 +259,8 @@ export const MainnetSpotMarkets: SpotMarketConfig[] = [
|
|
|
226
259
|
'8dFTCTAbtGuHsdDL8WEPrTU6pXFDrU1QSjBTutw8fwZk'
|
|
227
260
|
),
|
|
228
261
|
launchTs: 1712149014000,
|
|
262
|
+
pythFeedId:
|
|
263
|
+
'0xeff7446475e218517566ea99e72a4abec2e1bd8498b43b7d8331e29dcb059389',
|
|
229
264
|
},
|
|
230
265
|
{
|
|
231
266
|
symbol: 'TNSR',
|
|
@@ -239,6 +274,8 @@ export const MainnetSpotMarkets: SpotMarketConfig[] = [
|
|
|
239
274
|
'AbJCZ9TAJiby5AY3cHcXS2gUdENC6mtsm6m7XpC2ZMvE'
|
|
240
275
|
),
|
|
241
276
|
launchTs: 1712593532000,
|
|
277
|
+
pythFeedId:
|
|
278
|
+
'0x05ecd4597cd48fe13d6cc3596c62af4f9675aee06e2e0b94c06d8bee2b659e05',
|
|
242
279
|
},
|
|
243
280
|
{
|
|
244
281
|
symbol: 'DRIFT',
|
|
@@ -252,6 +289,8 @@ export const MainnetSpotMarkets: SpotMarketConfig[] = [
|
|
|
252
289
|
'8BV6rrWsUabnTDA3dE6A69oUDJAj3hMhtBHTJyXB7czp'
|
|
253
290
|
),
|
|
254
291
|
launchTs: 1715860800000,
|
|
292
|
+
pythFeedId:
|
|
293
|
+
'0x5c1690b27bb02446db17cdda13ccc2c1d609ad6d2ef5bf4983a85ea8b6f19d07',
|
|
255
294
|
},
|
|
256
295
|
{
|
|
257
296
|
symbol: 'INF',
|
|
@@ -262,6 +301,8 @@ export const MainnetSpotMarkets: SpotMarketConfig[] = [
|
|
|
262
301
|
precision: new BN(10).pow(NINE),
|
|
263
302
|
precisionExp: NINE,
|
|
264
303
|
launchTs: 1716595200000,
|
|
304
|
+
pythFeedId:
|
|
305
|
+
'0xf51570985c642c49c2d6e50156390fdba80bb6d5f7fa389d2f012ced4f7d208f',
|
|
265
306
|
},
|
|
266
307
|
{
|
|
267
308
|
symbol: 'dSOL',
|
package/src/driftClient.ts
CHANGED
|
@@ -76,6 +76,7 @@ import {
|
|
|
76
76
|
getInsuranceFundStakeAccountPublicKey,
|
|
77
77
|
getPerpMarketPublicKey,
|
|
78
78
|
getPhoenixFulfillmentConfigPublicKey,
|
|
79
|
+
getPythPullOraclePublicKey,
|
|
79
80
|
getReferrerNamePublicKeySync,
|
|
80
81
|
getSerumFulfillmentConfigPublicKey,
|
|
81
82
|
getSerumSignerPublicKey,
|
|
@@ -127,8 +128,22 @@ import { getMarinadeDepositIx, getMarinadeFinanceProgram } from './marinade';
|
|
|
127
128
|
import { getOrderParams } from './orderParams';
|
|
128
129
|
import { numberToSafeBN } from './math/utils';
|
|
129
130
|
import { TransactionParamProcessor } from './tx/txParamProcessor';
|
|
130
|
-
import { isOracleValid } from './math/oracles';
|
|
131
|
+
import { isOracleValid, trimVaaSignatures } from './math/oracles';
|
|
131
132
|
import { TxHandler } from './tx/txHandler';
|
|
133
|
+
import {
|
|
134
|
+
wormholeCoreBridgeIdl,
|
|
135
|
+
pythSolanaReceiverIdl,
|
|
136
|
+
DEFAULT_RECEIVER_PROGRAM_ID,
|
|
137
|
+
} from '@pythnetwork/pyth-solana-receiver';
|
|
138
|
+
import { parseAccumulatorUpdateData } from '@pythnetwork/price-service-sdk';
|
|
139
|
+
import {
|
|
140
|
+
DEFAULT_WORMHOLE_PROGRAM_ID,
|
|
141
|
+
getGuardianSetPda,
|
|
142
|
+
} from '@pythnetwork/pyth-solana-receiver/lib/address';
|
|
143
|
+
import { DRIFT_ORACLE_RECEIVER_ID } from './config';
|
|
144
|
+
import { WormholeCoreBridgeSolana } from '@pythnetwork/pyth-solana-receiver/lib/idl/wormhole_core_bridge_solana';
|
|
145
|
+
import { PythSolanaReceiver } from '@pythnetwork/pyth-solana-receiver/lib/idl/pyth_solana_receiver';
|
|
146
|
+
import { getFeedIdUint8Array, trimFeedId } from './util/pythPullOracleUtils';
|
|
132
147
|
import { isVersionedTransaction } from './tx/utils';
|
|
133
148
|
|
|
134
149
|
type RemainingAccountParams = {
|
|
@@ -179,6 +194,9 @@ export class DriftClient {
|
|
|
179
194
|
|
|
180
195
|
txHandler: TxHandler;
|
|
181
196
|
|
|
197
|
+
receiverProgram?: Program<PythSolanaReceiver>;
|
|
198
|
+
wormholeProgram?: Program<WormholeCoreBridgeSolana>;
|
|
199
|
+
|
|
182
200
|
public get isSubscribed() {
|
|
183
201
|
return this._isSubscribed && this.accountSubscriber.isSubscribed;
|
|
184
202
|
}
|
|
@@ -6892,6 +6910,250 @@ export class DriftClient {
|
|
|
6892
6910
|
return undefined;
|
|
6893
6911
|
}
|
|
6894
6912
|
|
|
6913
|
+
public getReceiverProgram(): Program<PythSolanaReceiver> {
|
|
6914
|
+
if (this.receiverProgram === undefined) {
|
|
6915
|
+
this.receiverProgram = new Program(
|
|
6916
|
+
pythSolanaReceiverIdl,
|
|
6917
|
+
DEFAULT_RECEIVER_PROGRAM_ID,
|
|
6918
|
+
this.provider
|
|
6919
|
+
);
|
|
6920
|
+
}
|
|
6921
|
+
return this.receiverProgram;
|
|
6922
|
+
}
|
|
6923
|
+
|
|
6924
|
+
public async postPythPullOracleUpdateAtomic(
|
|
6925
|
+
vaaString: string,
|
|
6926
|
+
feedId: string
|
|
6927
|
+
): Promise<TransactionSignature> {
|
|
6928
|
+
const postIxs = await this.getPostPythPullOracleUpdateAtomicIxs(
|
|
6929
|
+
vaaString,
|
|
6930
|
+
feedId
|
|
6931
|
+
);
|
|
6932
|
+
const tx = await this.buildTransaction(postIxs);
|
|
6933
|
+
const { txSig } = await this.sendTransaction(tx, [], this.opts);
|
|
6934
|
+
|
|
6935
|
+
return txSig;
|
|
6936
|
+
}
|
|
6937
|
+
|
|
6938
|
+
public async getPostPythPullOracleUpdateAtomicIxs(
|
|
6939
|
+
vaaString: string,
|
|
6940
|
+
feedId: string,
|
|
6941
|
+
numSignatures = 2
|
|
6942
|
+
): Promise<TransactionInstruction[]> {
|
|
6943
|
+
feedId = trimFeedId(feedId);
|
|
6944
|
+
const accumulatorUpdateData = parseAccumulatorUpdateData(
|
|
6945
|
+
Buffer.from(vaaString, 'base64')
|
|
6946
|
+
);
|
|
6947
|
+
const guardianSetIndex = accumulatorUpdateData.vaa.readUInt32BE(1);
|
|
6948
|
+
const guardianSet = getGuardianSetPda(
|
|
6949
|
+
guardianSetIndex,
|
|
6950
|
+
DEFAULT_WORMHOLE_PROGRAM_ID
|
|
6951
|
+
);
|
|
6952
|
+
const trimmedVaa = trimVaaSignatures(
|
|
6953
|
+
accumulatorUpdateData.vaa,
|
|
6954
|
+
numSignatures
|
|
6955
|
+
);
|
|
6956
|
+
|
|
6957
|
+
const postIxs: TransactionInstruction[] = [];
|
|
6958
|
+
for (const update of accumulatorUpdateData.updates) {
|
|
6959
|
+
postIxs.push(
|
|
6960
|
+
await this.getSinglePostPythPullOracleAtomicIx(
|
|
6961
|
+
{
|
|
6962
|
+
vaa: trimmedVaa,
|
|
6963
|
+
merklePriceUpdate: update,
|
|
6964
|
+
},
|
|
6965
|
+
feedId,
|
|
6966
|
+
guardianSet
|
|
6967
|
+
)
|
|
6968
|
+
);
|
|
6969
|
+
}
|
|
6970
|
+
|
|
6971
|
+
return postIxs;
|
|
6972
|
+
}
|
|
6973
|
+
|
|
6974
|
+
public async getSinglePostPythPullOracleAtomicIx(
|
|
6975
|
+
params: {
|
|
6976
|
+
vaa: Buffer;
|
|
6977
|
+
merklePriceUpdate: {
|
|
6978
|
+
message: Buffer;
|
|
6979
|
+
proof: number[][];
|
|
6980
|
+
};
|
|
6981
|
+
},
|
|
6982
|
+
feedId: string,
|
|
6983
|
+
guardianSet: PublicKey
|
|
6984
|
+
): Promise<TransactionInstruction> {
|
|
6985
|
+
const feedIdBuffer = getFeedIdUint8Array(feedId);
|
|
6986
|
+
const receiverProgram = this.getReceiverProgram();
|
|
6987
|
+
|
|
6988
|
+
const encodedParams = receiverProgram.coder.types.encode(
|
|
6989
|
+
'PostUpdateAtomicParams',
|
|
6990
|
+
params
|
|
6991
|
+
);
|
|
6992
|
+
|
|
6993
|
+
return this.program.instruction.postPythPullOracleUpdateAtomic(
|
|
6994
|
+
feedIdBuffer,
|
|
6995
|
+
encodedParams,
|
|
6996
|
+
{
|
|
6997
|
+
accounts: {
|
|
6998
|
+
keeper: this.wallet.publicKey,
|
|
6999
|
+
pythSolanaReceiver: DRIFT_ORACLE_RECEIVER_ID,
|
|
7000
|
+
guardianSet,
|
|
7001
|
+
priceFeed: getPythPullOraclePublicKey(
|
|
7002
|
+
this.program.programId,
|
|
7003
|
+
feedIdBuffer
|
|
7004
|
+
),
|
|
7005
|
+
},
|
|
7006
|
+
}
|
|
7007
|
+
);
|
|
7008
|
+
}
|
|
7009
|
+
|
|
7010
|
+
public async updatePythPullOracle(
|
|
7011
|
+
vaaString: string,
|
|
7012
|
+
feedId: string
|
|
7013
|
+
): Promise<TransactionSignature> {
|
|
7014
|
+
feedId = trimFeedId(feedId);
|
|
7015
|
+
const accumulatorUpdateData = parseAccumulatorUpdateData(
|
|
7016
|
+
Buffer.from(vaaString, 'base64')
|
|
7017
|
+
);
|
|
7018
|
+
const guardianSetIndex = accumulatorUpdateData.vaa.readUInt32BE(1);
|
|
7019
|
+
const guardianSet = getGuardianSetPda(
|
|
7020
|
+
guardianSetIndex,
|
|
7021
|
+
DEFAULT_WORMHOLE_PROGRAM_ID
|
|
7022
|
+
);
|
|
7023
|
+
|
|
7024
|
+
const [postIxs, encodedVaaAddress] = await this.getBuildEncodedVaaIxs(
|
|
7025
|
+
accumulatorUpdateData.vaa,
|
|
7026
|
+
guardianSet
|
|
7027
|
+
);
|
|
7028
|
+
|
|
7029
|
+
for (const update of accumulatorUpdateData.updates) {
|
|
7030
|
+
postIxs.push(
|
|
7031
|
+
await this.getUpdatePythPullOracleIxs(
|
|
7032
|
+
{
|
|
7033
|
+
merklePriceUpdate: update,
|
|
7034
|
+
},
|
|
7035
|
+
feedId,
|
|
7036
|
+
encodedVaaAddress.publicKey
|
|
7037
|
+
)
|
|
7038
|
+
);
|
|
7039
|
+
}
|
|
7040
|
+
|
|
7041
|
+
const tx = await this.buildTransaction(postIxs);
|
|
7042
|
+
const { txSig } = await this.sendTransaction(
|
|
7043
|
+
tx,
|
|
7044
|
+
[encodedVaaAddress],
|
|
7045
|
+
this.opts
|
|
7046
|
+
);
|
|
7047
|
+
|
|
7048
|
+
return txSig;
|
|
7049
|
+
}
|
|
7050
|
+
|
|
7051
|
+
public async getUpdatePythPullOracleIxs(
|
|
7052
|
+
params: {
|
|
7053
|
+
merklePriceUpdate: {
|
|
7054
|
+
message: Buffer;
|
|
7055
|
+
proof: number[][];
|
|
7056
|
+
};
|
|
7057
|
+
},
|
|
7058
|
+
feedId: string,
|
|
7059
|
+
encodedVaaAddress: PublicKey
|
|
7060
|
+
): Promise<TransactionInstruction> {
|
|
7061
|
+
const feedIdBuffer = getFeedIdUint8Array(feedId);
|
|
7062
|
+
const receiverProgram = this.getReceiverProgram();
|
|
7063
|
+
|
|
7064
|
+
const encodedParams = receiverProgram.coder.types.encode(
|
|
7065
|
+
'PostUpdateParams',
|
|
7066
|
+
params
|
|
7067
|
+
);
|
|
7068
|
+
|
|
7069
|
+
return this.program.instruction.updatePythPullOracle(
|
|
7070
|
+
feedIdBuffer,
|
|
7071
|
+
encodedParams,
|
|
7072
|
+
{
|
|
7073
|
+
accounts: {
|
|
7074
|
+
keeper: this.wallet.publicKey,
|
|
7075
|
+
pythSolanaReceiver: DRIFT_ORACLE_RECEIVER_ID,
|
|
7076
|
+
encodedVaa: encodedVaaAddress,
|
|
7077
|
+
priceFeed: getPythPullOraclePublicKey(
|
|
7078
|
+
this.program.programId,
|
|
7079
|
+
feedIdBuffer
|
|
7080
|
+
),
|
|
7081
|
+
},
|
|
7082
|
+
}
|
|
7083
|
+
);
|
|
7084
|
+
}
|
|
7085
|
+
|
|
7086
|
+
public async getBuildEncodedVaaIxs(
|
|
7087
|
+
vaa: Buffer,
|
|
7088
|
+
guardianSet: PublicKey
|
|
7089
|
+
): Promise<[TransactionInstruction[], Keypair]> {
|
|
7090
|
+
const postIxs: TransactionInstruction[] = [];
|
|
7091
|
+
|
|
7092
|
+
if (this.wormholeProgram === undefined) {
|
|
7093
|
+
this.wormholeProgram = new Program(
|
|
7094
|
+
wormholeCoreBridgeIdl,
|
|
7095
|
+
DEFAULT_WORMHOLE_PROGRAM_ID,
|
|
7096
|
+
this.provider
|
|
7097
|
+
);
|
|
7098
|
+
}
|
|
7099
|
+
|
|
7100
|
+
const encodedVaaKeypair = new Keypair();
|
|
7101
|
+
postIxs.push(
|
|
7102
|
+
await this.wormholeProgram.account.encodedVaa.createInstruction(
|
|
7103
|
+
encodedVaaKeypair,
|
|
7104
|
+
vaa.length + 46
|
|
7105
|
+
)
|
|
7106
|
+
);
|
|
7107
|
+
|
|
7108
|
+
// Why do we need this too?
|
|
7109
|
+
postIxs.push(
|
|
7110
|
+
await this.wormholeProgram.methods
|
|
7111
|
+
.initEncodedVaa()
|
|
7112
|
+
.accounts({
|
|
7113
|
+
encodedVaa: encodedVaaKeypair.publicKey,
|
|
7114
|
+
})
|
|
7115
|
+
.instruction()
|
|
7116
|
+
);
|
|
7117
|
+
|
|
7118
|
+
// Split the write into two ixs
|
|
7119
|
+
postIxs.push(
|
|
7120
|
+
await this.wormholeProgram.methods
|
|
7121
|
+
.writeEncodedVaa({
|
|
7122
|
+
index: 0,
|
|
7123
|
+
data: vaa.subarray(0, 755),
|
|
7124
|
+
})
|
|
7125
|
+
.accounts({
|
|
7126
|
+
draftVaa: encodedVaaKeypair.publicKey,
|
|
7127
|
+
})
|
|
7128
|
+
.instruction()
|
|
7129
|
+
);
|
|
7130
|
+
|
|
7131
|
+
postIxs.push(
|
|
7132
|
+
await this.wormholeProgram.methods
|
|
7133
|
+
.writeEncodedVaa({
|
|
7134
|
+
index: 755,
|
|
7135
|
+
data: vaa.subarray(755),
|
|
7136
|
+
})
|
|
7137
|
+
.accounts({
|
|
7138
|
+
draftVaa: encodedVaaKeypair.publicKey,
|
|
7139
|
+
})
|
|
7140
|
+
.instruction()
|
|
7141
|
+
);
|
|
7142
|
+
|
|
7143
|
+
// Verify
|
|
7144
|
+
postIxs.push(
|
|
7145
|
+
await this.wormholeProgram.methods
|
|
7146
|
+
.verifyEncodedVaaV1()
|
|
7147
|
+
.accounts({
|
|
7148
|
+
guardianSet,
|
|
7149
|
+
draftVaa: encodedVaaKeypair.publicKey,
|
|
7150
|
+
})
|
|
7151
|
+
.instruction()
|
|
7152
|
+
);
|
|
7153
|
+
|
|
7154
|
+
return [postIxs, encodedVaaKeypair];
|
|
7155
|
+
}
|
|
7156
|
+
|
|
6895
7157
|
private handleSignedTransaction(signedTxs: SignedTxData[]) {
|
|
6896
7158
|
if (this.enableMetricsEvents && this.metricsEventEmitter) {
|
|
6897
7159
|
this.metricsEventEmitter.emit('txSigned', signedTxs);
|
package/src/idl/drift.json
CHANGED
|
@@ -2547,6 +2547,86 @@
|
|
|
2547
2547
|
}
|
|
2548
2548
|
]
|
|
2549
2549
|
},
|
|
2550
|
+
{
|
|
2551
|
+
"name": "updatePythPullOracle",
|
|
2552
|
+
"accounts": [
|
|
2553
|
+
{
|
|
2554
|
+
"name": "keeper",
|
|
2555
|
+
"isMut": true,
|
|
2556
|
+
"isSigner": true
|
|
2557
|
+
},
|
|
2558
|
+
{
|
|
2559
|
+
"name": "pythSolanaReceiver",
|
|
2560
|
+
"isMut": false,
|
|
2561
|
+
"isSigner": false
|
|
2562
|
+
},
|
|
2563
|
+
{
|
|
2564
|
+
"name": "encodedVaa",
|
|
2565
|
+
"isMut": false,
|
|
2566
|
+
"isSigner": false
|
|
2567
|
+
},
|
|
2568
|
+
{
|
|
2569
|
+
"name": "priceFeed",
|
|
2570
|
+
"isMut": true,
|
|
2571
|
+
"isSigner": false
|
|
2572
|
+
}
|
|
2573
|
+
],
|
|
2574
|
+
"args": [
|
|
2575
|
+
{
|
|
2576
|
+
"name": "feedId",
|
|
2577
|
+
"type": {
|
|
2578
|
+
"array": [
|
|
2579
|
+
"u8",
|
|
2580
|
+
32
|
|
2581
|
+
]
|
|
2582
|
+
}
|
|
2583
|
+
},
|
|
2584
|
+
{
|
|
2585
|
+
"name": "params",
|
|
2586
|
+
"type": "bytes"
|
|
2587
|
+
}
|
|
2588
|
+
]
|
|
2589
|
+
},
|
|
2590
|
+
{
|
|
2591
|
+
"name": "postPythPullOracleUpdateAtomic",
|
|
2592
|
+
"accounts": [
|
|
2593
|
+
{
|
|
2594
|
+
"name": "keeper",
|
|
2595
|
+
"isMut": true,
|
|
2596
|
+
"isSigner": true
|
|
2597
|
+
},
|
|
2598
|
+
{
|
|
2599
|
+
"name": "pythSolanaReceiver",
|
|
2600
|
+
"isMut": false,
|
|
2601
|
+
"isSigner": false
|
|
2602
|
+
},
|
|
2603
|
+
{
|
|
2604
|
+
"name": "guardianSet",
|
|
2605
|
+
"isMut": false,
|
|
2606
|
+
"isSigner": false
|
|
2607
|
+
},
|
|
2608
|
+
{
|
|
2609
|
+
"name": "priceFeed",
|
|
2610
|
+
"isMut": true,
|
|
2611
|
+
"isSigner": false
|
|
2612
|
+
}
|
|
2613
|
+
],
|
|
2614
|
+
"args": [
|
|
2615
|
+
{
|
|
2616
|
+
"name": "feedId",
|
|
2617
|
+
"type": {
|
|
2618
|
+
"array": [
|
|
2619
|
+
"u8",
|
|
2620
|
+
32
|
|
2621
|
+
]
|
|
2622
|
+
}
|
|
2623
|
+
},
|
|
2624
|
+
{
|
|
2625
|
+
"name": "params",
|
|
2626
|
+
"type": "bytes"
|
|
2627
|
+
}
|
|
2628
|
+
]
|
|
2629
|
+
},
|
|
2550
2630
|
{
|
|
2551
2631
|
"name": "initialize",
|
|
2552
2632
|
"accounts": [
|
|
@@ -5296,6 +5376,47 @@
|
|
|
5296
5376
|
"type": "u16"
|
|
5297
5377
|
}
|
|
5298
5378
|
]
|
|
5379
|
+
},
|
|
5380
|
+
{
|
|
5381
|
+
"name": "initializePythPullOracle",
|
|
5382
|
+
"accounts": [
|
|
5383
|
+
{
|
|
5384
|
+
"name": "admin",
|
|
5385
|
+
"isMut": true,
|
|
5386
|
+
"isSigner": true
|
|
5387
|
+
},
|
|
5388
|
+
{
|
|
5389
|
+
"name": "pythSolanaReceiver",
|
|
5390
|
+
"isMut": false,
|
|
5391
|
+
"isSigner": false
|
|
5392
|
+
},
|
|
5393
|
+
{
|
|
5394
|
+
"name": "priceFeed",
|
|
5395
|
+
"isMut": true,
|
|
5396
|
+
"isSigner": false
|
|
5397
|
+
},
|
|
5398
|
+
{
|
|
5399
|
+
"name": "systemProgram",
|
|
5400
|
+
"isMut": false,
|
|
5401
|
+
"isSigner": false
|
|
5402
|
+
},
|
|
5403
|
+
{
|
|
5404
|
+
"name": "state",
|
|
5405
|
+
"isMut": false,
|
|
5406
|
+
"isSigner": false
|
|
5407
|
+
}
|
|
5408
|
+
],
|
|
5409
|
+
"args": [
|
|
5410
|
+
{
|
|
5411
|
+
"name": "feedId",
|
|
5412
|
+
"type": {
|
|
5413
|
+
"array": [
|
|
5414
|
+
"u8",
|
|
5415
|
+
32
|
|
5416
|
+
]
|
|
5417
|
+
}
|
|
5418
|
+
}
|
|
5419
|
+
]
|
|
5299
5420
|
}
|
|
5300
5421
|
],
|
|
5301
5422
|
"accounts": [
|
|
@@ -12029,6 +12150,44 @@
|
|
|
12029
12150
|
"code": 6268,
|
|
12030
12151
|
"name": "MaxBorrows",
|
|
12031
12152
|
"msg": "Can not borow more than max borrows"
|
|
12153
|
+
},
|
|
12154
|
+
{
|
|
12155
|
+
"code": 6269,
|
|
12156
|
+
"name": "OracleUpdatesNotMonotonic",
|
|
12157
|
+
"msg": "Updates must be monotonically increasing"
|
|
12158
|
+
},
|
|
12159
|
+
{
|
|
12160
|
+
"code": 6270,
|
|
12161
|
+
"name": "OraclePriceFeedMessageMismatch",
|
|
12162
|
+
"msg": "Trying to update price feed with the wrong feed id"
|
|
12163
|
+
},
|
|
12164
|
+
{
|
|
12165
|
+
"code": 6271,
|
|
12166
|
+
"name": "OracleUnsupportedMessageType",
|
|
12167
|
+
"msg": "The message in the update must be a PriceFeedMessage"
|
|
12168
|
+
},
|
|
12169
|
+
{
|
|
12170
|
+
"code": 6272,
|
|
12171
|
+
"name": "OracleDeserializeMessageFailed",
|
|
12172
|
+
"msg": "Could not deserialize the message in the update"
|
|
12173
|
+
},
|
|
12174
|
+
{
|
|
12175
|
+
"code": 6273,
|
|
12176
|
+
"name": "OracleWrongGuardianSetOwner",
|
|
12177
|
+
"msg": "Wrong guardian set owner in update price atomic"
|
|
12178
|
+
},
|
|
12179
|
+
{
|
|
12180
|
+
"code": 6274,
|
|
12181
|
+
"name": "OracleWrongWriteAuthority",
|
|
12182
|
+
"msg": "Oracle post update atomic price feed account must be drift program"
|
|
12183
|
+
},
|
|
12184
|
+
{
|
|
12185
|
+
"code": 6275,
|
|
12186
|
+
"name": "OracleWrongVaaOwner",
|
|
12187
|
+
"msg": "Oracle vaa owner must be wormhole program"
|
|
12032
12188
|
}
|
|
12033
|
-
]
|
|
12189
|
+
],
|
|
12190
|
+
"metadata": {
|
|
12191
|
+
"address": "dRiftyHA39MWEi3m9aunc5MzRF1JYuBsbn6VPcn33UH"
|
|
12192
|
+
}
|
|
12034
12193
|
}
|
package/src/math/oracles.ts
CHANGED
|
@@ -209,3 +209,20 @@ export function getNewOracleConfPct(
|
|
|
209
209
|
|
|
210
210
|
return confIntervalPctResult;
|
|
211
211
|
}
|
|
212
|
+
|
|
213
|
+
export function trimVaaSignatures(vaa: Buffer, n = 3): Buffer {
|
|
214
|
+
const currentNumSignatures = vaa[5];
|
|
215
|
+
if (n > currentNumSignatures) {
|
|
216
|
+
throw new Error(
|
|
217
|
+
"Resulting VAA can't have more signatures than the original VAA"
|
|
218
|
+
);
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
const trimmedVaa = Buffer.concat([
|
|
222
|
+
vaa.subarray(0, 6 + n * 66),
|
|
223
|
+
vaa.subarray(6 + currentNumSignatures * 66),
|
|
224
|
+
]);
|
|
225
|
+
|
|
226
|
+
trimmedVaa[5] = n;
|
|
227
|
+
return trimmedVaa;
|
|
228
|
+
}
|
|
@@ -9,11 +9,10 @@ import {
|
|
|
9
9
|
} from '../constants/numericConstants';
|
|
10
10
|
import {
|
|
11
11
|
PythSolanaReceiverProgram,
|
|
12
|
-
DEFAULT_RECEIVER_PROGRAM_ID,
|
|
13
12
|
pythSolanaReceiverIdl,
|
|
14
13
|
} from '@pythnetwork/pyth-solana-receiver';
|
|
15
14
|
import { PriceUpdateAccount } from '@pythnetwork/pyth-solana-receiver/lib/PythSolanaReceiver';
|
|
16
|
-
import { Wallet } from '..';
|
|
15
|
+
import { DRIFT_ORACLE_RECEIVER_ID, Wallet } from '..';
|
|
17
16
|
|
|
18
17
|
export class PythPullClient implements OracleClient {
|
|
19
18
|
private connection: Connection;
|
|
@@ -40,7 +39,7 @@ export class PythPullClient implements OracleClient {
|
|
|
40
39
|
);
|
|
41
40
|
this.receiver = new Program<PythSolanaReceiverProgram>(
|
|
42
41
|
pythSolanaReceiverIdl as PythSolanaReceiverProgram,
|
|
43
|
-
|
|
42
|
+
DRIFT_ORACLE_RECEIVER_ID,
|
|
44
43
|
provider
|
|
45
44
|
);
|
|
46
45
|
this.decodeFunc =
|
package/src/tx/baseTxSender.ts
CHANGED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export function trimFeedId(feedId: string): string {
|
|
2
|
+
if (feedId.startsWith('0x')) {
|
|
3
|
+
return feedId.slice(2);
|
|
4
|
+
}
|
|
5
|
+
return feedId;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export function getFeedIdUint8Array(feedId: string): Uint8Array {
|
|
9
|
+
const trimmedFeedId = trimFeedId(feedId);
|
|
10
|
+
return Uint8Array.from(Buffer.from(trimmedFeedId, 'hex'));
|
|
11
|
+
}
|