Skip to content

Instantly share code, notes, and snippets.

@wphan
Created July 15, 2024 14:47
Show Gist options
  • Save wphan/23f0b266032af1e463c1b88d20473e9a to your computer and use it in GitHub Desktop.
Save wphan/23f0b266032af1e463c1b88d20473e9a to your computer and use it in GitHub Desktop.
drift: settle pnl for user
/**
* add `"@drift-labs/sdk": "2.86.0-beta.6"` to package.json
*
* must set env vars before running:
* * RPC_ENDPOINT: valid solana rpc
* * ANCHOR_WALLET: private key file or raw string
*
* Usage:
* ts-node settleUserPnl.ts
*
*/
import {
BASE_PRECISION,
convertToNumber,
decodeName,
DRIFT_PROGRAM_ID,
DriftClient,
loadKeypair,
PublicKey,
QUOTE_PRECISION,
User,
Wallet,
WhileValidTxSender,
} from "@drift-labs/sdk";
import { Connection } from "@solana/web3.js";
import inquirer from "inquirer";
async function handleSettlePnlForUser(driftClient: DriftClient) {
const userAccountPubkeyName = "UserAccount to settle";
const userAccountCmd = await inquirer.prompt({
type: "input",
prefix: "drift>",
name: userAccountPubkeyName,
});
const userAcc = userAccountCmd[userAccountPubkeyName];
const userAccPubkey = new PublicKey(userAcc);
const user = new User({
driftClient,
userAccountPublicKey: userAccPubkey,
accountSubscription: {
type: "websocket",
},
});
await user.subscribe();
const perpMarketChoices: Array<{
msg: string;
market: number;
}> = [];
for (const pos of user.getActivePerpPositions()) {
const perpMarket = driftClient.getPerpMarketAccount(pos.marketIndex);
perpMarketChoices.push({
msg: `[${pos.marketIndex} ${decodeName(
perpMarket.name
)}]: base: ${convertToNumber(
pos.baseAssetAmount,
BASE_PRECISION
)}, quote: ${convertToNumber(pos.quoteAssetAmount, QUOTE_PRECISION)}`,
market: pos.marketIndex,
});
}
const getPerpCmdName = "Perp market index";
const doGetPerpCmd = await inquirer.prompt({
type: "list",
prefix: "Drift>",
name: getPerpCmdName,
message: `Pick which perp market to settle for user`,
choices: perpMarketChoices.map((c) => c.msg),
});
const perpMarketSelected = doGetPerpCmd[getPerpCmdName];
const perpMarketIndex = perpMarketChoices.find(
(c) => c.msg === perpMarketSelected
).market;
console.log(`Settling user ${userAccPubkey} in market ${perpMarketIndex}`);
const tx = await driftClient.settlePNL(
userAccPubkey,
user.getUserAccount(),
perpMarketIndex,
{ computeUnitsPrice: 50000 }
);
console.log(
`Settled user ${userAccPubkey} in market ${perpMarketIndex}: ${tx}`
);
}
const main = async () => {
if (!process.env.RPC_ENDPOINT) {
throw new Error("RPC_ENDPOINT env var must be set to a valid solana RPC")
}
const connection = new Connection(process.env.RPC_ENDPOINT);
if (!process.env.ANCHOR_WALLET) {
throw new Error("ANCHOR_WALLET must be set to a private key");
}
const keypair = loadKeypair(process.env.ANCHOR_WALLET!);
const wallet = new Wallet(keypair);
const driftClient = new DriftClient({
connection,
wallet: wallet,
programID: new PublicKey(DRIFT_PROGRAM_ID),
env: "mainnet-beta",
accountSubscription: {
type: "websocket",
},
userStats: true,
activeSubAccountId: parseInt(process.env.SUBACCOUNT_ID ?? "0"),
opts: {
maxRetries: 0,
skipPreflight: true,
},
txSender: new WhileValidTxSender({
connection,
wallet,
opts: {
skipPreflight: true,
maxRetries: 0,
},
retrySleep: 2000,
}),
});
const subStart = Date.now();
console.log(`DriftClient subscribing...`);
await driftClient.subscribe();
console.log(`DriftClient subscribed in ${Date.now() - subStart}ms`);
await handleSettlePnlForUser(driftClient);
};
main().catch((e) => {
console.error(e);
process.exit(1);
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment