Skip to content

Commit 0e8c1d1

Browse files
fix: drift user account balances and position amounts (#232)
# Pull Request Description This PR fixes a drift account info issue pointed out by the Drift protocol team ## Changes Made This PR adds the following changes: <!-- List the key changes made in this PR --> - I updated the drift and drift vault SDK versions - I corrected the `driftUserAccountInfo` function ## Prompt executed by agent <!-- If applicable, provide example usage, transactions, or screenshots --> Example transaction: <img width="592" alt="Screenshot 2025-01-23 at 09 11 58" src="https://github.com/user-attachments/assets/24c48204-de50-4231-bc73-abfe04776d51" /> ## Prompt Used <!-- If relevant, include the prompt or configuration used --> ``` show my drift account info ``` ## Additional Notes <!-- Any additional information that reviewers should know --> ## Checklist - [x] I have tested these changes locally - [ ] I have updated the documentation - [ ] I have added a transaction link - [x] I have added the prompt used to test it
2 parents 328201b + 5797498 commit 0e8c1d1

File tree

3 files changed

+91
-34
lines changed

3 files changed

+91
-34
lines changed

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,8 @@
3535
"@bonfida/spl-name-service": "^3.0.7",
3636
"@cks-systems/manifest-sdk": "0.1.59",
3737
"@coral-xyz/anchor": "0.29",
38-
"@drift-labs/sdk": "2.107.0-beta.3",
39-
"@drift-labs/vaults-sdk": "^0.2.49",
38+
"@drift-labs/sdk": "2.108.0-beta.4",
39+
"@drift-labs/vaults-sdk": "^0.3.2",
4040
"@langchain/core": "^0.3.26",
4141
"@langchain/groq": "^0.1.2",
4242
"@langchain/langgraph": "^0.2.36",

pnpm-lock.yaml

Lines changed: 14 additions & 14 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/tools/drift/drift.ts

Lines changed: 75 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import {
22
BASE_PRECISION,
33
BigNum,
4+
BulkAccountLoader,
45
calculateDepositRate,
56
calculateEstimatedEntryPriceWithL2,
67
calculateInterestRate,
@@ -14,7 +15,9 @@ import {
1415
getInsuranceFundStakeAccountPublicKey,
1516
getLimitOrderParams,
1617
getMarketOrderParams,
18+
getTokenAmount,
1719
getUserAccountPublicKeySync,
20+
isVariant,
1821
JupiterClient,
1922
MainnetPerpMarkets,
2023
MainnetSpotMarkets,
@@ -71,6 +74,10 @@ export async function initClients(
7174
txParams: {
7275
computeUnitsPrice: MINIMUM_COMPUTE_PRICE_FOR_COMPLEX_ACTIONS,
7376
},
77+
accountSubscription: {
78+
type: "polling",
79+
accountLoader: new BulkAccountLoader(agent.connection, "processed", 10),
80+
},
7481
txSender: new FastSingleTxSender({
7582
connection: agent.connection,
7683
wallet,
@@ -439,12 +446,14 @@ export async function doesUserHaveDriftAccount(agent: SolanaAgentKit) {
439446
export async function driftUserAccountInfo(agent: SolanaAgentKit) {
440447
try {
441448
const { driftClient, cleanUp } = await initClients(agent);
449+
const userPublicKey = getUserAccountPublicKeySync(
450+
new PublicKey(DRIFT_PROGRAM_ID),
451+
agent.wallet.publicKey,
452+
);
453+
442454
const user = new User({
443455
driftClient,
444-
userAccountPublicKey: getUserAccountPublicKeySync(
445-
new PublicKey(DRIFT_PROGRAM_ID),
446-
agent.wallet.publicKey,
447-
),
456+
userAccountPublicKey: userPublicKey,
448457
});
449458
const userAccountExists = await user.exists();
450459

@@ -453,32 +462,80 @@ export async function driftUserAccountInfo(agent: SolanaAgentKit) {
453462
}
454463
await user.subscribe();
455464
const account = user.getUserAccount();
456-
await user.unsubscribe();
457465

458-
await cleanUp();
459466
const perpPositions = account.perpPositions.map((pos) => ({
460-
...pos,
467+
market: MainnetPerpMarkets[pos.marketIndex].symbol,
461468
baseAssetAmount: convertToNumber(pos.baseAssetAmount, BASE_PRECISION),
469+
quoteAssetAmount: convertToNumber(
470+
pos.quoteAssetAmount.abs(),
471+
QUOTE_PRECISION,
472+
),
473+
quoteEntryAmount: convertToNumber(
474+
pos.quoteEntryAmount.abs(),
475+
QUOTE_PRECISION,
476+
),
477+
quoteBreakEvenAmount: convertToNumber(
478+
pos.quoteBreakEvenAmount.abs(),
479+
QUOTE_PRECISION,
480+
),
462481
settledPnl: convertToNumber(pos.settledPnl, QUOTE_PRECISION),
482+
openAsks: pos.openAsks.toNumber(),
483+
openBids: pos.openBids.toNumber(),
484+
openOrders: pos.openOrders,
485+
positionType:
486+
convertToNumber(pos.baseAssetAmount, BASE_PRECISION) > 0
487+
? "long"
488+
: "short",
463489
}));
464-
const spotPositions = account.spotPositions.map((pos) => ({
465-
...pos,
466-
availableBalance: convertToNumber(
490+
const spotPositions = account.spotPositions.map((pos) => {
491+
const spotMarketAccount = driftClient.getSpotMarketAccount(
492+
pos.marketIndex,
493+
);
494+
495+
if (!spotMarketAccount) {
496+
return;
497+
}
498+
499+
const tokenBalance = getTokenAmount(
467500
pos.scaledBalance,
468-
MainnetSpotMarkets[pos.marketIndex].precision,
469-
),
470-
symbol: MainnetSpotMarkets.find((v) => v.marketIndex === pos.marketIndex)
471-
?.symbol,
472-
}));
501+
spotMarketAccount,
502+
pos.balanceType,
503+
);
504+
505+
return {
506+
availableBalance:
507+
(isVariant(pos.balanceType, "borrow") ? -1 : 1) *
508+
convertToNumber(
509+
tokenBalance,
510+
MainnetSpotMarkets[pos.marketIndex].precision,
511+
),
512+
symbol: MainnetSpotMarkets[pos.marketIndex].symbol,
513+
openAsks: pos.openAsks.toNumber(),
514+
openBids: pos.openBids.toNumber(),
515+
openOrders: pos.openOrders,
516+
type: isVariant(pos.balanceType, "borrow") ? "borrow" : "deposit",
517+
};
518+
});
519+
520+
const overallUserBalance = user.getNetSpotMarketValue();
521+
const unrealizedPnl = user.getUnrealizedPNL(true);
522+
const netUSDValue = convertToNumber(
523+
overallUserBalance.add(unrealizedPnl),
524+
QUOTE_PRECISION,
525+
);
526+
527+
await cleanUp();
528+
await user.unsubscribe();
473529

474530
return {
475-
...account,
476531
name: account.name,
532+
accountAddress: userPublicKey.toBase58(),
477533
authority: account.authority,
534+
overallBalance: netUSDValue,
478535
settledPerpPnl: `$${convertToNumber(account.settledPerpPnl, QUOTE_PRECISION)}`,
479536
lastActiveSlot: account.lastActiveSlot.toNumber(),
480-
perpPositions,
481-
spotPositions,
537+
perpPositions: perpPositions.filter((pos) => pos.baseAssetAmount !== 0),
538+
spotPositions: spotPositions.filter((pos) => pos?.availableBalance !== 0),
482539
};
483540
} catch (e) {
484541
// @ts-expect-error - error message is a string

0 commit comments

Comments
 (0)