@drift-labs/sdk 2.82.0-beta.6 → 2.82.0-beta.8
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/README.md +65 -47
- package/VERSION +1 -1
- package/lib/tx/baseTxSender.js +3 -2
- package/lib/tx/types.d.ts +5 -0
- package/lib/tx/types.js +12 -1
- package/package.json +1 -1
- package/src/tx/baseTxSender.ts +8 -4
- package/src/tx/types.ts +12 -0
package/README.md
CHANGED
|
@@ -19,6 +19,13 @@ npm i @drift-labs/sdk
|
|
|
19
19
|
|
|
20
20
|
## Getting Started
|
|
21
21
|
|
|
22
|
+
Documentation:
|
|
23
|
+
|
|
24
|
+
- [API docs](https://drift-labs.github.io/v2-teacher/)
|
|
25
|
+
- [overview docs](https://docs.drift.trade/)
|
|
26
|
+
|
|
27
|
+
The below is a light overview of using solana and drift's typescript sdk, but not as comprehensive as the [API docs](https://drift-labs.github.io/v2-teacher/).
|
|
28
|
+
|
|
22
29
|
### Setting up a wallet for your program
|
|
23
30
|
|
|
24
31
|
```bash
|
|
@@ -77,8 +84,10 @@ convertToNumber(new BN(10500), new BN(1000)); // = 10.5
|
|
|
77
84
|
### Setting up an account and making a trade
|
|
78
85
|
|
|
79
86
|
```typescript
|
|
80
|
-
import
|
|
81
|
-
import {
|
|
87
|
+
import * as anchor from '@coral-xyz/anchor';
|
|
88
|
+
import { AnchorProvider } from '@coral-xyz/anchor';
|
|
89
|
+
import { getAssociatedTokenAddress, TOKEN_PROGRAM_ID } from '@solana/spl-token';
|
|
90
|
+
|
|
82
91
|
import { Connection, Keypair, PublicKey } from '@solana/web3.js';
|
|
83
92
|
import {
|
|
84
93
|
calculateReservePrice,
|
|
@@ -95,16 +104,17 @@ import {
|
|
|
95
104
|
BASE_PRECISION,
|
|
96
105
|
getMarketOrderParams,
|
|
97
106
|
BulkAccountLoader,
|
|
98
|
-
|
|
107
|
+
BN,
|
|
108
|
+
calculateBidAskPrice,
|
|
109
|
+
getMarketsAndOraclesForSubscription,
|
|
110
|
+
calculateEstimatedPerpEntryPrice,
|
|
99
111
|
} from '../sdk';
|
|
100
112
|
|
|
101
113
|
export const getTokenAddress = (
|
|
102
114
|
mintAddress: string,
|
|
103
115
|
userPubKey: string
|
|
104
116
|
): Promise<PublicKey> => {
|
|
105
|
-
return
|
|
106
|
-
new PublicKey(`ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL`),
|
|
107
|
-
TOKEN_PROGRAM_ID,
|
|
117
|
+
return getAssociatedTokenAddress(
|
|
108
118
|
new PublicKey(mintAddress),
|
|
109
119
|
new PublicKey(userPubKey)
|
|
110
120
|
);
|
|
@@ -112,49 +122,56 @@ export const getTokenAddress = (
|
|
|
112
122
|
|
|
113
123
|
const main = async () => {
|
|
114
124
|
const env = 'devnet';
|
|
125
|
+
// const env = 'mainnet-beta';
|
|
126
|
+
|
|
115
127
|
// Initialize Drift SDK
|
|
116
128
|
const sdkConfig = initialize({ env });
|
|
117
129
|
|
|
118
130
|
// Set up the Wallet and Provider
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
);
|
|
123
|
-
const wallet = new Wallet(keypair);
|
|
131
|
+
if (!process.env.ANCHOR_WALLET) {
|
|
132
|
+
throw new Error('ANCHOR_WALLET env var must be set.');
|
|
133
|
+
}
|
|
124
134
|
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
135
|
+
if (!process.env.ANCHOR_PROVIDER_URL) {
|
|
136
|
+
throw new Error('ANCHOR_PROVIDER_URL env var must be set.');
|
|
137
|
+
}
|
|
128
138
|
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
139
|
+
const provider = anchor.AnchorProvider.local(
|
|
140
|
+
process.env.ANCHOR_PROVIDER_URL,
|
|
141
|
+
{
|
|
142
|
+
preflightCommitment: 'confirmed',
|
|
143
|
+
skipPreflight: false,
|
|
144
|
+
commitment: 'confirmed',
|
|
145
|
+
}
|
|
134
146
|
);
|
|
135
|
-
|
|
136
147
|
// Check SOL Balance
|
|
137
|
-
const lamportsBalance = await connection.getBalance(
|
|
138
|
-
|
|
148
|
+
const lamportsBalance = await provider.connection.getBalance(
|
|
149
|
+
provider.wallet.publicKey
|
|
150
|
+
);
|
|
151
|
+
console.log(
|
|
152
|
+
provider.wallet.publicKey.toString(),
|
|
153
|
+
env,
|
|
154
|
+
'SOL balance:',
|
|
155
|
+
lamportsBalance / 10 ** 9
|
|
156
|
+
);
|
|
139
157
|
|
|
140
158
|
// Misc. other things to set up
|
|
141
159
|
const usdcTokenAddress = await getTokenAddress(
|
|
142
160
|
sdkConfig.USDC_MINT_ADDRESS,
|
|
143
|
-
wallet.publicKey.toString()
|
|
161
|
+
provider.wallet.publicKey.toString()
|
|
144
162
|
);
|
|
145
163
|
|
|
146
164
|
// Set up the Drift Client
|
|
147
165
|
const driftPublicKey = new PublicKey(sdkConfig.DRIFT_PROGRAM_ID);
|
|
148
166
|
const bulkAccountLoader = new BulkAccountLoader(
|
|
149
|
-
connection,
|
|
167
|
+
provider.connection,
|
|
150
168
|
'confirmed',
|
|
151
169
|
1000
|
|
152
170
|
);
|
|
153
171
|
const driftClient = new DriftClient({
|
|
154
|
-
connection,
|
|
172
|
+
connection: provider.connection,
|
|
155
173
|
wallet: provider.wallet,
|
|
156
174
|
programID: driftPublicKey,
|
|
157
|
-
...getMarketsAndOraclesForSubscription(env),
|
|
158
175
|
accountSubscription: {
|
|
159
176
|
type: 'polling',
|
|
160
177
|
accountLoader: bulkAccountLoader,
|
|
@@ -162,6 +179,8 @@ const main = async () => {
|
|
|
162
179
|
});
|
|
163
180
|
await driftClient.subscribe();
|
|
164
181
|
|
|
182
|
+
console.log('subscribed to driftClient');
|
|
183
|
+
|
|
165
184
|
// Set up user client
|
|
166
185
|
const user = new User({
|
|
167
186
|
driftClient: driftClient,
|
|
@@ -176,13 +195,20 @@ const main = async () => {
|
|
|
176
195
|
const userAccountExists = await user.exists();
|
|
177
196
|
|
|
178
197
|
if (!userAccountExists) {
|
|
179
|
-
|
|
198
|
+
console.log(
|
|
199
|
+
'initializing to',
|
|
200
|
+
env,
|
|
201
|
+
' drift account for',
|
|
202
|
+
provider.wallet.publicKey.toString()
|
|
203
|
+
);
|
|
204
|
+
|
|
205
|
+
//// Create a Drift V2 account by Depositing some USDC ($10,000 in this case)
|
|
180
206
|
const depositAmount = new BN(10000).mul(QUOTE_PRECISION);
|
|
181
207
|
await driftClient.initializeUserAccountAndDepositCollateral(
|
|
182
208
|
depositAmount,
|
|
183
209
|
await getTokenAddress(
|
|
184
210
|
usdcTokenAddress.toString(),
|
|
185
|
-
wallet.publicKey.toString()
|
|
211
|
+
provider.wallet.publicKey.toString()
|
|
186
212
|
)
|
|
187
213
|
);
|
|
188
214
|
}
|
|
@@ -194,6 +220,9 @@ const main = async () => {
|
|
|
194
220
|
(market) => market.baseAssetSymbol === 'SOL'
|
|
195
221
|
);
|
|
196
222
|
|
|
223
|
+
const marketIndex = solMarketInfo.marketIndex;
|
|
224
|
+
|
|
225
|
+
// Get vAMM bid and ask price
|
|
197
226
|
const [bid, ask] = calculateBidAskPrice(
|
|
198
227
|
driftClient.getPerpMarketAccount(marketIndex).amm,
|
|
199
228
|
driftClient.getOracleDataForPerpMarket(marketIndex)
|
|
@@ -203,35 +232,26 @@ const main = async () => {
|
|
|
203
232
|
const formattedAskPrice = convertToNumber(ask, PRICE_PRECISION);
|
|
204
233
|
|
|
205
234
|
console.log(
|
|
206
|
-
|
|
235
|
+
env,
|
|
236
|
+
`vAMM bid: $${formattedBidPrice} and ask: $${formattedAskPrice}`
|
|
207
237
|
);
|
|
208
238
|
|
|
209
|
-
// Estimate the slippage for a $5000 LONG trade
|
|
210
239
|
const solMarketAccount = driftClient.getPerpMarketAccount(
|
|
211
240
|
solMarketInfo.marketIndex
|
|
212
241
|
);
|
|
242
|
+
console.log(env, `Placing a 1 SOL-PERP LONG order`);
|
|
213
243
|
|
|
214
|
-
const
|
|
215
|
-
calculateTradeSlippage(
|
|
216
|
-
PositionDirection.LONG,
|
|
217
|
-
new BN(1).mul(BASE_PRECISION),
|
|
218
|
-
solMarketAccount,
|
|
219
|
-
'base',
|
|
220
|
-
driftClient.getOracleDataForPerpMarket(solMarketInfo.marketIndex)
|
|
221
|
-
)[0],
|
|
222
|
-
PRICE_PRECISION
|
|
223
|
-
);
|
|
224
|
-
|
|
225
|
-
console.log(`Slippage for a 1 SOL-PERP would be $${slippage}`);
|
|
226
|
-
|
|
227
|
-
await driftClient.placePerpOrder(
|
|
244
|
+
const txSig = await driftClient.placePerpOrder(
|
|
228
245
|
getMarketOrderParams({
|
|
229
246
|
baseAssetAmount: new BN(1).mul(BASE_PRECISION),
|
|
230
247
|
direction: PositionDirection.LONG,
|
|
231
248
|
marketIndex: solMarketAccount.marketIndex,
|
|
232
249
|
})
|
|
233
250
|
);
|
|
234
|
-
console.log(
|
|
251
|
+
console.log(
|
|
252
|
+
env,
|
|
253
|
+
`Placed a 1 SOL-PERP LONG order. Tranaction signature: ${txSig}`
|
|
254
|
+
);
|
|
235
255
|
};
|
|
236
256
|
|
|
237
257
|
main();
|
|
@@ -244,5 +264,3 @@ Drift Protocol v2 is licensed under [Apache 2.0](./LICENSE).
|
|
|
244
264
|
Unless you explicitly state otherwise, any contribution intentionally submitted
|
|
245
265
|
for inclusion in Drift SDK by you, as defined in the Apache-2.0 license, shall be
|
|
246
266
|
licensed as above, without any additional terms or conditions.
|
|
247
|
-
|
|
248
|
-
|
package/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
2.82.0-beta.
|
|
1
|
+
2.82.0-beta.8
|
package/lib/tx/baseTxSender.js
CHANGED
|
@@ -10,6 +10,7 @@ const anchor_1 = require("@coral-xyz/anchor");
|
|
|
10
10
|
const assert_1 = __importDefault(require("assert"));
|
|
11
11
|
const bs58_1 = __importDefault(require("bs58"));
|
|
12
12
|
const DEFAULT_TIMEOUT = 35000;
|
|
13
|
+
const NOT_CONFIRMED_ERROR_CODE = -1001;
|
|
13
14
|
class BaseTxSender {
|
|
14
15
|
constructor({ connection, wallet, opts = anchor_1.AnchorProvider.defaultOptions(), timeout = DEFAULT_TIMEOUT, additionalConnections = new Array(), confirmationStrategy = types_1.ConfirmationStrategy.Combo, additionalTxSenderCallbacks, }) {
|
|
15
16
|
this.timeoutCount = 0;
|
|
@@ -181,7 +182,7 @@ class BaseTxSender {
|
|
|
181
182
|
}
|
|
182
183
|
this.timeoutCount += 1;
|
|
183
184
|
const duration = (Date.now() - start) / 1000;
|
|
184
|
-
throw new
|
|
185
|
+
throw new types_1.TxSendError(`Transaction was not confirmed in ${duration.toFixed(2)} seconds. It is unknown if it succeeded or failed. Check signature ${signature} using the Solana Explorer or CLI tools.`, NOT_CONFIRMED_ERROR_CODE);
|
|
185
186
|
}
|
|
186
187
|
return response;
|
|
187
188
|
}
|
|
@@ -203,7 +204,7 @@ class BaseTxSender {
|
|
|
203
204
|
// Transaction not confirmed within 30 seconds
|
|
204
205
|
this.timeoutCount += 1;
|
|
205
206
|
const duration = (Date.now() - start) / 1000;
|
|
206
|
-
throw new
|
|
207
|
+
throw new types_1.TxSendError(`Transaction was not confirmed in ${duration.toFixed(2)} seconds. It is unknown if it succeeded or failed. Check signature ${signature} using the Solana Explorer or CLI tools.`, NOT_CONFIRMED_ERROR_CODE);
|
|
207
208
|
}
|
|
208
209
|
async confirmTransaction(signature, commitment) {
|
|
209
210
|
if (this.confirmationStrategy === types_1.ConfirmationStrategy.WebSocket ||
|
package/lib/tx/types.d.ts
CHANGED
|
@@ -22,3 +22,8 @@ export interface TxSender {
|
|
|
22
22
|
simulateTransaction(tx: VersionedTransaction): Promise<boolean>;
|
|
23
23
|
getTimeoutCount(): number;
|
|
24
24
|
}
|
|
25
|
+
export declare class TxSendError extends Error {
|
|
26
|
+
message: string;
|
|
27
|
+
code: number;
|
|
28
|
+
constructor(message: string, code: number);
|
|
29
|
+
}
|
package/lib/tx/types.js
CHANGED
|
@@ -1,9 +1,20 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.ConfirmationStrategy = void 0;
|
|
3
|
+
exports.TxSendError = exports.ConfirmationStrategy = void 0;
|
|
4
4
|
var ConfirmationStrategy;
|
|
5
5
|
(function (ConfirmationStrategy) {
|
|
6
6
|
ConfirmationStrategy["WebSocket"] = "websocket";
|
|
7
7
|
ConfirmationStrategy["Polling"] = "polling";
|
|
8
8
|
ConfirmationStrategy["Combo"] = "combo";
|
|
9
9
|
})(ConfirmationStrategy = exports.ConfirmationStrategy || (exports.ConfirmationStrategy = {}));
|
|
10
|
+
class TxSendError extends Error {
|
|
11
|
+
constructor(message, code) {
|
|
12
|
+
super(message);
|
|
13
|
+
this.message = message;
|
|
14
|
+
this.code = code;
|
|
15
|
+
if (Error.captureStackTrace) {
|
|
16
|
+
Error.captureStackTrace(this, TxSendError);
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
exports.TxSendError = TxSendError;
|
package/package.json
CHANGED
package/src/tx/baseTxSender.ts
CHANGED
|
@@ -2,6 +2,7 @@ import {
|
|
|
2
2
|
ConfirmationStrategy,
|
|
3
3
|
ExtraConfirmationOptions,
|
|
4
4
|
TxSender,
|
|
5
|
+
TxSendError,
|
|
5
6
|
TxSigAndSlot,
|
|
6
7
|
} from './types';
|
|
7
8
|
import {
|
|
@@ -25,6 +26,7 @@ import bs58 from 'bs58';
|
|
|
25
26
|
import { IWallet } from '../types';
|
|
26
27
|
|
|
27
28
|
const DEFAULT_TIMEOUT = 35000;
|
|
29
|
+
const NOT_CONFIRMED_ERROR_CODE = -1001;
|
|
28
30
|
|
|
29
31
|
export abstract class BaseTxSender implements TxSender {
|
|
30
32
|
connection: Connection;
|
|
@@ -282,10 +284,11 @@ export abstract class BaseTxSender implements TxSender {
|
|
|
282
284
|
}
|
|
283
285
|
this.timeoutCount += 1;
|
|
284
286
|
const duration = (Date.now() - start) / 1000;
|
|
285
|
-
throw new
|
|
287
|
+
throw new TxSendError(
|
|
286
288
|
`Transaction was not confirmed in ${duration.toFixed(
|
|
287
289
|
2
|
|
288
|
-
)} seconds. It is unknown if it succeeded or failed. Check signature ${signature} using the Solana Explorer or CLI tools
|
|
290
|
+
)} seconds. It is unknown if it succeeded or failed. Check signature ${signature} using the Solana Explorer or CLI tools.`,
|
|
291
|
+
NOT_CONFIRMED_ERROR_CODE
|
|
289
292
|
);
|
|
290
293
|
}
|
|
291
294
|
|
|
@@ -317,10 +320,11 @@ export abstract class BaseTxSender implements TxSender {
|
|
|
317
320
|
// Transaction not confirmed within 30 seconds
|
|
318
321
|
this.timeoutCount += 1;
|
|
319
322
|
const duration = (Date.now() - start) / 1000;
|
|
320
|
-
throw new
|
|
323
|
+
throw new TxSendError(
|
|
321
324
|
`Transaction was not confirmed in ${duration.toFixed(
|
|
322
325
|
2
|
|
323
|
-
)} seconds. It is unknown if it succeeded or failed. Check signature ${signature} using the Solana Explorer or CLI tools
|
|
326
|
+
)} seconds. It is unknown if it succeeded or failed. Check signature ${signature} using the Solana Explorer or CLI tools.`,
|
|
327
|
+
NOT_CONFIRMED_ERROR_CODE
|
|
324
328
|
);
|
|
325
329
|
}
|
|
326
330
|
|
package/src/tx/types.ts
CHANGED
|
@@ -60,3 +60,15 @@ export interface TxSender {
|
|
|
60
60
|
|
|
61
61
|
getTimeoutCount(): number;
|
|
62
62
|
}
|
|
63
|
+
|
|
64
|
+
export class TxSendError extends Error {
|
|
65
|
+
constructor(
|
|
66
|
+
public message: string,
|
|
67
|
+
public code: number
|
|
68
|
+
) {
|
|
69
|
+
super(message);
|
|
70
|
+
if (Error.captureStackTrace) {
|
|
71
|
+
Error.captureStackTrace(this, TxSendError);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|