@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.
@@ -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',
@@ -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);
@@ -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
  }
@@ -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
- DEFAULT_RECEIVER_PROGRAM_ID,
42
+ DRIFT_ORACLE_RECEIVER_ID,
44
43
  provider
45
44
  );
46
45
  this.decodeFunc =
@@ -394,6 +394,7 @@ export abstract class BaseTxSender implements TxSender {
394
394
 
395
395
  const friendlyMessage = lastLog?.match(/(failed:) (.+)/)?.[2];
396
396
 
397
+ // @ts-ignore
397
398
  throw new SendTransactionError({
398
399
  action: 'send',
399
400
  signature: txSig,
@@ -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
+ }