Skip to content

Commit

Permalink
drift: sdk client
Browse files Browse the repository at this point in the history
  • Loading branch information
0x0ece committed Sep 13, 2024
1 parent daf2f67 commit 0cf5e00
Show file tree
Hide file tree
Showing 4 changed files with 329 additions and 87 deletions.
268 changes: 237 additions & 31 deletions anchor/src/client/drift.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,17 @@
import { BN } from "@coral-xyz/anchor";
import { PublicKey, Transaction, TransactionSignature } from "@solana/web3.js";
import {
PublicKey,
VersionedTransaction,
TransactionSignature,
} from "@solana/web3.js";
import {
DRIFT_PROGRAM_ID,
getDriftStateAccountPublicKey,
getUserAccountPublicKey,
getUserStatsAccountPublicKey,
} from "@drift-labs/sdk";

import { BaseClient } from "./base";
import { BaseClient, ApiTxOptions } from "./base";

export class DriftClient {
public constructor(readonly base: BaseClient) {}
Expand All @@ -10,51 +20,247 @@ export class DriftClient {
* Client methods
*/

public async exampleMethod(
public async initialize(fund: PublicKey): Promise<TransactionSignature> {
const tx = await this.initializeTx(fund, {});
return await this.base.sendAndConfirm(tx);
}

public async updateUserCustomMarginRatio(
fund: PublicKey,
amount: BN
subAccountId: number,
marginRatio: number
): Promise<TransactionSignature> {
return await this.exampleMethodTxBuilder(
const tx = await this.updateUserCustomMarginRatioTx(
fund,
this.base.getManager(),
amount
).rpc();
subAccountId,
marginRatio,
{}
);
return await this.base.sendAndConfirm(tx);
}

/*
* Tx Builders
*/
public async updateUserMarginTradingEnabled(
fund: PublicKey,
subAccountId: number,
marginTradingEnabled: boolean
): Promise<TransactionSignature> {
const tx = await this.updateUserMarginTradingEnabledTx(
fund,
subAccountId,
marginTradingEnabled,
{}
);
return await this.base.sendAndConfirm(tx);
}

public exampleMethodTxBuilder(
public async updateUserDelegate(
fund: PublicKey,
manager: PublicKey,
subAccountId: number,
delegate: PublicKey
): Promise<TransactionSignature> {
const tx = await this.updateUserDelegateTx(
fund,
subAccountId,
delegate,
{}
);
return await this.base.sendAndConfirm(tx);
}

public async deposit(
fund: PublicKey,
subAccountId: number,
amount: BN
): Promise<TransactionSignature> {
const tx = await this.depositTx(fund, subAccountId, amount, {});
return await this.base.sendAndConfirm(tx);
}

public async withdraw(
fund: PublicKey,
subAccountId: number,
amount: BN
): any /* MethodsBuilder<Glam, ?> */ {
): Promise<TransactionSignature> {
const tx = await this.withdrawTx(fund, subAccountId, amount, {});
return await this.base.sendAndConfirm(tx);
}

/*
* Utils
*/

DRIFT_PROGRAM = new PublicKey(DRIFT_PROGRAM_ID);

public async getUser(fund: PublicKey): Promise<PublicKey[]> {
const treasury = this.base.getTreasuryPDA(fund);
return [
await await getUserAccountPublicKey(this.DRIFT_PROGRAM, treasury, 0),
await getUserStatsAccountPublicKey(this.DRIFT_PROGRAM, treasury),
];
}

return this.base.program.methods
.initializeFund(this.base.getFundModel({})) //TODO: replace with method
.accounts({
//@ts-ignore IDL ts type is unhappy
fund,
treasury,
manager,
});
public async getUserStats(fund: PublicKey): Promise<PublicKey> {
const treasury = this.base.getTreasuryPDA(fund);
return await await getUserAccountPublicKey(this.DRIFT_PROGRAM, treasury, 0);
}

/*
* API methods
*/

public async exampleMethodTx(
public async initializeTx(
fund: PublicKey,
manager: PublicKey,
amount: BN
): Promise<Transaction> {
return await this.exampleMethodTxBuilder(
fund,
manager,
amount
).transaction();
apiOptions: ApiTxOptions
): Promise<VersionedTransaction> {
const manager = apiOptions.signer || this.base.getManager();

const [user, userStats] = await this.getUser(fund);
const state = await getDriftStateAccountPublicKey(this.DRIFT_PROGRAM);

const tx = await this.base.program.methods
.driftInitialize()
.accounts({
fund,
user,
userStats,
state,
manager,
})
.transaction();

return await this.base.intoVersionedTransaction({
tx,
...apiOptions,
});
}

public async updateUserCustomMarginRatioTx(
fund: PublicKey,
subAccountId: number,
marginRatio: number,
apiOptions: ApiTxOptions
): Promise<VersionedTransaction> {
const manager = apiOptions.signer || this.base.getManager();
const [user] = await this.getUser(fund);

const tx = await this.base.program.methods
.driftUpdateUserCustomMarginRatio(subAccountId, marginRatio)
.accounts({
fund,
user,
manager,
})
.transaction();

return await this.base.intoVersionedTransaction({
tx,
...apiOptions,
});
}

public async updateUserMarginTradingEnabledTx(
fund: PublicKey,
subAccountId: number,
marginTradingEnabled: boolean,
apiOptions: ApiTxOptions
): Promise<VersionedTransaction> {
const manager = apiOptions.signer || this.base.getManager();
const [user] = await this.getUser(fund);

const tx = await this.base.program.methods
.driftUpdateUserMarginTradingEnabled(subAccountId, marginTradingEnabled)
.accounts({
fund,
user,
manager,
})
.transaction();

return await this.base.intoVersionedTransaction({
tx,
...apiOptions,
});
}

public async updateUserDelegateTx(
fund: PublicKey,
subAccountId: number,
delegate: PublicKey,
apiOptions: ApiTxOptions
): Promise<VersionedTransaction> {
const manager = apiOptions.signer || this.base.getManager();
const [user] = await this.getUser(fund);

const tx = await this.base.program.methods
.driftUpdateUserDelegate(subAccountId, delegate)
.accounts({
fund,
user,
manager,
})
.transaction();

return await this.base.intoVersionedTransaction({
tx,
...apiOptions,
});
}

public async depositTx(
fund: PublicKey,
subAccountId: number,
amount: BN,
apiOptions: ApiTxOptions
): Promise<VersionedTransaction> {
const manager = apiOptions.signer || this.base.getManager();
const treasury = this.base.getTreasuryPDA(fund);

const [user, userStats] = await this.getUser(fund);
const state = await getDriftStateAccountPublicKey(this.DRIFT_PROGRAM);

const tx = await this.base.program.methods
.driftDeposit(subAccountId, amount)
.accounts({
fund,
user,
userStats,
state,
manager,
})
.transaction();

return await this.base.intoVersionedTransaction({
tx,
...apiOptions,
});
}

public async withdrawTx(
fund: PublicKey,
subAccountId: number,
amount: BN,
apiOptions: ApiTxOptions
): Promise<VersionedTransaction> {
const manager = apiOptions.signer || this.base.getManager();
const treasury = this.base.getTreasuryPDA(fund);

const [user, userStats] = await this.getUser(fund);
const state = await getDriftStateAccountPublicKey(this.DRIFT_PROGRAM);

const tx = await this.base.program.methods
.driftWithdraw(subAccountId, amount)
.accounts({
fund,
user,
userStats,
state,
manager,
})
.transaction();

return await this.base.intoVersionedTransaction({
tx,
...apiOptions,
});
}
}
46 changes: 43 additions & 3 deletions anchor/target/idl/glam.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"address": "GLAMpLuXu78TA4ao3DPZvT1zQ7woxoQ8ahdYbhnqY9mP",
"address": "Gco1pcjxCMYjKJjSNJ7mKV7qezeUTE7arXJgy7PAPNRc",
"metadata": {
"name": "glam",
"version": "0.2.9",
Expand Down Expand Up @@ -3710,8 +3710,48 @@
"errors": [
{
"code": 6000,
"name": "NotAuthorized",
"msg": "Signer is not authorized"
"name": "CloseNotEmptyError",
"msg": "Error closing account: not empty"
},
{
"code": 6001,
"name": "NotAuthorizedError",
"msg": "Error: not authorized"
},
{
"code": 6002,
"name": "InvalidFundName",
"msg": "Invalid fund name: max 30 chars"
},
{
"code": 6003,
"name": "InvalidFundSymbol",
"msg": "Too many assets: max 50"
},
{
"code": 6004,
"name": "InvalidFundUri",
"msg": "Too many assets: max 20"
},
{
"code": 6005,
"name": "InvalidAssetsLen",
"msg": "Too many assets: max 100"
},
{
"code": 6006,
"name": "InvalidAssetsWeights",
"msg": "Number of weights should match number of assets"
},
{
"code": 6007,
"name": "InvalidAssetForSwap",
"msg": "Asset cannot be swapped"
},
{
"code": 6008,
"name": "InvalidSwap",
"msg": "Swap failed"
}
],
"types": [
Expand Down
Loading

0 comments on commit 0cf5e00

Please sign in to comment.