@drift-labs/sdk 2.85.0-beta.9 → 2.86.0-beta.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/VERSION +1 -1
- package/bun.lockb +0 -0
- 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 +26 -1
- package/lib/driftClient.js +157 -31
- package/lib/driftClientConfig.d.ts +2 -1
- package/lib/idl/drift.json +161 -2
- 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/tx/blockhashFetcher/baseBlockhashFetcher.d.ts +8 -0
- package/lib/tx/blockhashFetcher/baseBlockhashFetcher.js +13 -0
- package/lib/tx/blockhashFetcher/cachedBlockhashFetcher.d.ts +28 -0
- package/lib/tx/blockhashFetcher/cachedBlockhashFetcher.js +73 -0
- package/lib/tx/blockhashFetcher/types.d.ts +4 -0
- package/lib/tx/blockhashFetcher/types.js +2 -0
- package/lib/tx/txHandler.d.ts +10 -0
- package/lib/tx/txHandler.js +16 -7
- package/lib/tx/utils.d.ts +2 -0
- package/lib/tx/utils.js +10 -0
- package/lib/util/pythPullOracleUtils.d.ts +2 -0
- package/lib/util/pythPullOracleUtils.js +15 -0
- package/package.json +6 -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 +347 -41
- package/src/driftClientConfig.ts +2 -1
- package/src/idl/drift.json +161 -2
- package/src/math/oracles.ts +17 -0
- package/src/oracles/pythPullClient.ts +2 -3
- package/src/tx/baseTxSender.ts +1 -0
- package/src/tx/blockhashFetcher/baseBlockhashFetcher.ts +19 -0
- package/src/tx/blockhashFetcher/cachedBlockhashFetcher.ts +90 -0
- package/src/tx/blockhashFetcher/types.ts +5 -0
- package/src/tx/txHandler.ts +38 -4
- package/src/tx/utils.ts +11 -0
- package/src/util/pythPullOracleUtils.ts +11 -0
- package/tests/tx/cachedBlockhashFetcher.test.ts +96 -0
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,23 @@ 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';
|
|
147
|
+
import { isVersionedTransaction } from './tx/utils';
|
|
132
148
|
|
|
133
149
|
type RemainingAccountParams = {
|
|
134
150
|
userAccounts: UserAccount[];
|
|
@@ -178,6 +194,9 @@ export class DriftClient {
|
|
|
178
194
|
|
|
179
195
|
txHandler: TxHandler;
|
|
180
196
|
|
|
197
|
+
receiverProgram?: Program<PythSolanaReceiver>;
|
|
198
|
+
wormholeProgram?: Program<WormholeCoreBridgeSolana>;
|
|
199
|
+
|
|
181
200
|
public get isSubscribed() {
|
|
182
201
|
return this._isSubscribed && this.accountSubscriber.isSubscribed;
|
|
183
202
|
}
|
|
@@ -227,6 +246,7 @@ export class DriftClient {
|
|
|
227
246
|
onSignedCb: this.handleSignedTransaction.bind(this),
|
|
228
247
|
preSignedCb: this.handlePreSignedTransaction.bind(this),
|
|
229
248
|
},
|
|
249
|
+
config: config.txHandlerConfig,
|
|
230
250
|
});
|
|
231
251
|
|
|
232
252
|
if (config.includeDelegates && config.subAccountIds) {
|
|
@@ -1800,25 +1820,14 @@ export class DriftClient {
|
|
|
1800
1820
|
});
|
|
1801
1821
|
}
|
|
1802
1822
|
|
|
1803
|
-
|
|
1804
|
-
* Deposit funds into the given spot market
|
|
1805
|
-
*
|
|
1806
|
-
* @param amount to deposit
|
|
1807
|
-
* @param marketIndex spot market index to deposit into
|
|
1808
|
-
* @param associatedTokenAccount can be the wallet public key if using native sol
|
|
1809
|
-
* @param subAccountId subaccountId to deposit
|
|
1810
|
-
* @param reduceOnly if true, deposit must not increase account risk
|
|
1811
|
-
*/
|
|
1812
|
-
public async deposit(
|
|
1823
|
+
public async createDepositTxn(
|
|
1813
1824
|
amount: BN,
|
|
1814
1825
|
marketIndex: number,
|
|
1815
1826
|
associatedTokenAccount: PublicKey,
|
|
1816
1827
|
subAccountId?: number,
|
|
1817
1828
|
reduceOnly = false,
|
|
1818
1829
|
txParams?: TxParams
|
|
1819
|
-
): Promise<
|
|
1820
|
-
const additionalSigners: Array<Signer> = [];
|
|
1821
|
-
|
|
1830
|
+
): Promise<ReturnType<typeof this.buildTransaction>> {
|
|
1822
1831
|
const spotMarketAccount = this.getSpotMarketAccount(marketIndex);
|
|
1823
1832
|
|
|
1824
1833
|
const isSolMarket = spotMarketAccount.mint.equals(WRAPPED_SOL_MINT);
|
|
@@ -1868,11 +1877,36 @@ export class DriftClient {
|
|
|
1868
1877
|
|
|
1869
1878
|
const tx = await this.buildTransaction(instructions, txParams);
|
|
1870
1879
|
|
|
1871
|
-
|
|
1872
|
-
|
|
1873
|
-
|
|
1874
|
-
|
|
1880
|
+
return tx;
|
|
1881
|
+
}
|
|
1882
|
+
|
|
1883
|
+
/**
|
|
1884
|
+
* Deposit funds into the given spot market
|
|
1885
|
+
*
|
|
1886
|
+
* @param amount to deposit
|
|
1887
|
+
* @param marketIndex spot market index to deposit into
|
|
1888
|
+
* @param associatedTokenAccount can be the wallet public key if using native sol
|
|
1889
|
+
* @param subAccountId subaccountId to deposit
|
|
1890
|
+
* @param reduceOnly if true, deposit must not increase account risk
|
|
1891
|
+
*/
|
|
1892
|
+
public async deposit(
|
|
1893
|
+
amount: BN,
|
|
1894
|
+
marketIndex: number,
|
|
1895
|
+
associatedTokenAccount: PublicKey,
|
|
1896
|
+
subAccountId?: number,
|
|
1897
|
+
reduceOnly = false,
|
|
1898
|
+
txParams?: TxParams
|
|
1899
|
+
): Promise<TransactionSignature> {
|
|
1900
|
+
const tx = await this.createDepositTxn(
|
|
1901
|
+
amount,
|
|
1902
|
+
marketIndex,
|
|
1903
|
+
associatedTokenAccount,
|
|
1904
|
+
subAccountId,
|
|
1905
|
+
reduceOnly,
|
|
1906
|
+
txParams
|
|
1875
1907
|
);
|
|
1908
|
+
|
|
1909
|
+
const { txSig, slot } = await this.sendTransaction(tx, [], this.opts);
|
|
1876
1910
|
this.spotMarketLastSlotCache.set(marketIndex, slot);
|
|
1877
1911
|
return txSig;
|
|
1878
1912
|
}
|
|
@@ -2005,20 +2039,7 @@ export class DriftClient {
|
|
|
2005
2039
|
);
|
|
2006
2040
|
}
|
|
2007
2041
|
|
|
2008
|
-
|
|
2009
|
-
* Creates the User account for a user, and deposits some initial collateral
|
|
2010
|
-
* @param amount
|
|
2011
|
-
* @param userTokenAccount
|
|
2012
|
-
* @param marketIndex
|
|
2013
|
-
* @param subAccountId
|
|
2014
|
-
* @param name
|
|
2015
|
-
* @param fromSubAccountId
|
|
2016
|
-
* @param referrerInfo
|
|
2017
|
-
* @param donateAmount
|
|
2018
|
-
* @param txParams
|
|
2019
|
-
* @returns
|
|
2020
|
-
*/
|
|
2021
|
-
public async initializeUserAccountAndDepositCollateral(
|
|
2042
|
+
public async createInitializeUserAccountAndDepositCollateral(
|
|
2022
2043
|
amount: BN,
|
|
2023
2044
|
userTokenAccount: PublicKey,
|
|
2024
2045
|
marketIndex = 0,
|
|
@@ -2029,7 +2050,7 @@ export class DriftClient {
|
|
|
2029
2050
|
donateAmount?: BN,
|
|
2030
2051
|
txParams?: TxParams,
|
|
2031
2052
|
customMaxMarginRatio?: number
|
|
2032
|
-
): Promise<[
|
|
2053
|
+
): Promise<[Transaction | VersionedTransaction, PublicKey]> {
|
|
2033
2054
|
const ixs = [];
|
|
2034
2055
|
|
|
2035
2056
|
const [userAccountPublicKey, initializeUserAccountIx] =
|
|
@@ -2039,8 +2060,6 @@ export class DriftClient {
|
|
|
2039
2060
|
referrerInfo
|
|
2040
2061
|
);
|
|
2041
2062
|
|
|
2042
|
-
const additionalSigners: Array<Signer> = [];
|
|
2043
|
-
|
|
2044
2063
|
const spotMarket = this.getSpotMarketAccount(marketIndex);
|
|
2045
2064
|
|
|
2046
2065
|
const isSolMarket = spotMarket.mint.equals(WRAPPED_SOL_MINT);
|
|
@@ -2134,6 +2153,49 @@ export class DriftClient {
|
|
|
2134
2153
|
|
|
2135
2154
|
const tx = await this.buildTransaction(ixs, txParams);
|
|
2136
2155
|
|
|
2156
|
+
return [tx, userAccountPublicKey];
|
|
2157
|
+
}
|
|
2158
|
+
|
|
2159
|
+
/**
|
|
2160
|
+
* Creates the User account for a user, and deposits some initial collateral
|
|
2161
|
+
* @param amount
|
|
2162
|
+
* @param userTokenAccount
|
|
2163
|
+
* @param marketIndex
|
|
2164
|
+
* @param subAccountId
|
|
2165
|
+
* @param name
|
|
2166
|
+
* @param fromSubAccountId
|
|
2167
|
+
* @param referrerInfo
|
|
2168
|
+
* @param donateAmount
|
|
2169
|
+
* @param txParams
|
|
2170
|
+
* @returns
|
|
2171
|
+
*/
|
|
2172
|
+
public async initializeUserAccountAndDepositCollateral(
|
|
2173
|
+
amount: BN,
|
|
2174
|
+
userTokenAccount: PublicKey,
|
|
2175
|
+
marketIndex = 0,
|
|
2176
|
+
subAccountId = 0,
|
|
2177
|
+
name?: string,
|
|
2178
|
+
fromSubAccountId?: number,
|
|
2179
|
+
referrerInfo?: ReferrerInfo,
|
|
2180
|
+
donateAmount?: BN,
|
|
2181
|
+
txParams?: TxParams,
|
|
2182
|
+
customMaxMarginRatio?: number
|
|
2183
|
+
): Promise<[TransactionSignature, PublicKey]> {
|
|
2184
|
+
const [tx, userAccountPublicKey] =
|
|
2185
|
+
await this.createInitializeUserAccountAndDepositCollateral(
|
|
2186
|
+
amount,
|
|
2187
|
+
userTokenAccount,
|
|
2188
|
+
marketIndex,
|
|
2189
|
+
subAccountId,
|
|
2190
|
+
name,
|
|
2191
|
+
fromSubAccountId,
|
|
2192
|
+
referrerInfo,
|
|
2193
|
+
donateAmount,
|
|
2194
|
+
txParams,
|
|
2195
|
+
customMaxMarginRatio
|
|
2196
|
+
);
|
|
2197
|
+
const additionalSigners: Array<Signer> = [];
|
|
2198
|
+
|
|
2137
2199
|
const { txSig, slot } = await this.sendTransaction(
|
|
2138
2200
|
tx,
|
|
2139
2201
|
additionalSigners,
|
|
@@ -4118,6 +4180,10 @@ export class DriftClient {
|
|
|
4118
4180
|
const outMarket = this.getSpotMarketAccount(outMarketIndex);
|
|
4119
4181
|
const inMarket = this.getSpotMarketAccount(inMarketIndex);
|
|
4120
4182
|
|
|
4183
|
+
const isExactOut = swapMode === 'ExactOut' || quote.swapMode === 'ExactOut';
|
|
4184
|
+
const amountIn = new BN(quote.inAmount);
|
|
4185
|
+
const exactOutBufferedAmountIn = amountIn.muln(1001).divn(1000); // Add 10bp buffer
|
|
4186
|
+
|
|
4121
4187
|
if (!quote) {
|
|
4122
4188
|
const fetchedQuote = await jupiterClient.getQuote({
|
|
4123
4189
|
inputMint: inMarket.mint,
|
|
@@ -4198,7 +4264,7 @@ export class DriftClient {
|
|
|
4198
4264
|
const { beginSwapIx, endSwapIx } = await this.getSwapIx({
|
|
4199
4265
|
outMarketIndex,
|
|
4200
4266
|
inMarketIndex,
|
|
4201
|
-
amountIn:
|
|
4267
|
+
amountIn: isExactOut ? exactOutBufferedAmountIn : amountIn,
|
|
4202
4268
|
inTokenAccount: inAssociatedTokenAccount,
|
|
4203
4269
|
outTokenAccount: outAssociatedTokenAccount,
|
|
4204
4270
|
reduceOnly,
|
|
@@ -6844,6 +6910,250 @@ export class DriftClient {
|
|
|
6844
6910
|
return undefined;
|
|
6845
6911
|
}
|
|
6846
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
|
+
|
|
6847
7157
|
private handleSignedTransaction(signedTxs: SignedTxData[]) {
|
|
6848
7158
|
if (this.enableMetricsEvents && this.metricsEventEmitter) {
|
|
6849
7159
|
this.metricsEventEmitter.emit('txSigned', signedTxs);
|
|
@@ -6859,11 +7169,7 @@ export class DriftClient {
|
|
|
6859
7169
|
private isVersionedTransaction(
|
|
6860
7170
|
tx: Transaction | VersionedTransaction
|
|
6861
7171
|
): boolean {
|
|
6862
|
-
|
|
6863
|
-
const isVersionedTx =
|
|
6864
|
-
tx instanceof VersionedTransaction || version !== undefined;
|
|
6865
|
-
|
|
6866
|
-
return isVersionedTx;
|
|
7172
|
+
return isVersionedTransaction(tx);
|
|
6867
7173
|
}
|
|
6868
7174
|
|
|
6869
7175
|
sendTransaction(
|
package/src/driftClientConfig.ts
CHANGED
|
@@ -10,7 +10,7 @@ import { OracleInfo } from './oracles/types';
|
|
|
10
10
|
import { BulkAccountLoader } from './accounts/bulkAccountLoader';
|
|
11
11
|
import { DriftEnv } from './config';
|
|
12
12
|
import { TxSender } from './tx/types';
|
|
13
|
-
import { TxHandler } from './tx/txHandler';
|
|
13
|
+
import { TxHandler, TxHandlerConfig } from './tx/txHandler';
|
|
14
14
|
|
|
15
15
|
export type DriftClientConfig = {
|
|
16
16
|
connection: Connection;
|
|
@@ -35,6 +35,7 @@ export type DriftClientConfig = {
|
|
|
35
35
|
txVersion?: TransactionVersion; // which tx version to use
|
|
36
36
|
txParams?: TxParams; // default tx params to use
|
|
37
37
|
enableMetricsEvents?: boolean;
|
|
38
|
+
txHandlerConfig?: TxHandlerConfig;
|
|
38
39
|
};
|
|
39
40
|
|
|
40
41
|
export type DriftClientSubscriptionConfig =
|
package/src/idl/drift.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "2.
|
|
2
|
+
"version": "2.85.0",
|
|
3
3
|
"name": "drift",
|
|
4
4
|
"instructions": [
|
|
5
5
|
{
|
|
@@ -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
|
+
}
|