diff --git a/anchor/src/client/drift.ts b/anchor/src/client/drift.ts index 2cf4899..d1b0b0d 100644 --- a/anchor/src/client/drift.ts +++ b/anchor/src/client/drift.ts @@ -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) {} @@ -10,51 +20,247 @@ export class DriftClient { * Client methods */ - public async exampleMethod( + public async initialize(fund: PublicKey): Promise { + const tx = await this.initializeTx(fund, {}); + return await this.base.sendAndConfirm(tx); + } + + public async updateUserCustomMarginRatio( fund: PublicKey, - amount: BN + subAccountId: number, + marginRatio: number ): Promise { - 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 { + 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 { + const tx = await this.updateUserDelegateTx( + fund, + subAccountId, + delegate, + {} + ); + return await this.base.sendAndConfirm(tx); + } + + public async deposit( + fund: PublicKey, + subAccountId: number, + amount: BN + ): Promise { + 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 */ { + ): Promise { + 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 { 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 { + 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 { - return await this.exampleMethodTxBuilder( - fund, - manager, - amount - ).transaction(); + apiOptions: ApiTxOptions + ): Promise { + 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 { + 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 { + 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 { + 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 { + 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 { + 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, + }); } } diff --git a/anchor/target/idl/glam.json b/anchor/target/idl/glam.json index 8711c59..479ffd6 100644 --- a/anchor/target/idl/glam.json +++ b/anchor/target/idl/glam.json @@ -1,5 +1,5 @@ { - "address": "GLAMpLuXu78TA4ao3DPZvT1zQ7woxoQ8ahdYbhnqY9mP", + "address": "Gco1pcjxCMYjKJjSNJ7mKV7qezeUTE7arXJgy7PAPNRc", "metadata": { "name": "glam", "version": "0.2.9", @@ -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": [ diff --git a/anchor/target/types/glam.ts b/anchor/target/types/glam.ts index 3f34aa5..4e58a03 100644 --- a/anchor/target/types/glam.ts +++ b/anchor/target/types/glam.ts @@ -3716,8 +3716,48 @@ export type Glam = { "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": [ diff --git a/anchor/tests/glam_drift.spec.ts b/anchor/tests/glam_drift.spec.ts index 88ae289..6991dd5 100644 --- a/anchor/tests/glam_drift.spec.ts +++ b/anchor/tests/glam_drift.spec.ts @@ -1,17 +1,5 @@ import * as anchor from "@coral-xyz/anchor"; -import { PublicKey } from "@solana/web3.js"; -import { - getAssociatedTokenAddressSync, - createAssociatedTokenAccount, -} from "@solana/spl-token"; -import { DRIFT_PROGRAM_ID, DriftClient } from "@drift-labs/sdk"; -import { Glam, GlamClient, GlamProgram } from "../src"; - -import { - getDriftStateAccountPublicKey, - getUserAccountPublicKey, - getUserStatsAccountPublicKey, -} from "@drift-labs/sdk"; +import { GlamClient, GlamProgram } from "../src"; import { createFundForTest } from "./setup"; describe("glam_drift", () => { @@ -42,30 +30,8 @@ describe("glam_drift", () => { }); it("Drift initialize", async () => { - const userAccountPublicKey = await getUserAccountPublicKey( - new PublicKey(DRIFT_PROGRAM_ID), - treasuryPDA, - 0 - ); - const userStatsAccountPublicKey = await getUserStatsAccountPublicKey( - new PublicKey(DRIFT_PROGRAM_ID), - treasuryPDA - ); - const statePublicKey = await getDriftStateAccountPublicKey( - new PublicKey(DRIFT_PROGRAM_ID) - ); - console.log("statePublicKey", statePublicKey.toBase58()); try { - const txId = await program.methods - .driftInitialize() - .accounts({ - fund: fundPDA, - user: userAccountPublicKey, - userStats: userStatsAccountPublicKey, - state: statePublicKey, - manager, - }) - .rpc({ commitment }); + const txId = await glamClient.drift.initialize(fundPDA); console.log("driftInitialize", txId); } catch (e) { console.error(e); @@ -74,23 +40,13 @@ describe("glam_drift", () => { }); it("Drift: update trader", async () => { - const userAccountPublicKey = await getUserAccountPublicKey( - new PublicKey(DRIFT_PROGRAM_ID), - treasuryPDA, - 0 - ); const trader = manager; - try { - const txId = await program.methods - .driftUpdateUserDelegate(0, trader) - .accounts({ - fund: fundPDA, - user: userAccountPublicKey, - manager, - }) - .rpc({ commitment }); - + const txId = await glamClient.drift.updateUserDelegate( + fundPDA, + 0, + trader + ); console.log("driftUpdateUserDelegate", txId); } catch (e) { console.error(e);