Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

risk: drift on chain policy #234

Merged
merged 1 commit into from
Oct 7, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 36 additions & 2 deletions anchor/src/client/drift.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,15 @@ import {
initialize as _initialize,
PositionDirection,
BulkAccountLoader,
decodeUser,
} from "@drift-labs/sdk";

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

const DRIFT_VAULT = new PublicKey(
"JCNCMFXo5M5qwUPg2Utu1u6YWp3MbygxqBsBeXXJfrw"
);
const DRIFT_MARGIN_PRECISION = 10_000;

const remainingAccountsForOrders = [
{
Expand Down Expand Up @@ -204,6 +206,39 @@ export class DriftClient {
return market;
}

async fetchPolicyConfig(fund: any) {
let driftUserAccount;
if (fund) {
const [driftUserAddress] = this.getUser(fund.id);
const connection = this.base.provider.connection;
const info = await connection.getAccountInfo(
driftUserAddress,
connection.commitment
);
if (info) {
driftUserAccount = decodeUser(info.data);
}
}
let delegate = driftUserAccount?.delegate;
if (
delegate &&
delegate.toBase58() === "11111111111111111111111111111111"
) {
delegate = undefined;
}
return {
driftAccessControl: delegate ? 0 : 1,
driftDelegatedAccount: delegate || null,
driftMarketIndexesPerp: fund?.driftMarketIndexesPerp || [],
driftOrderTypes: fund?.driftOrderTypes || [],
driftMaxLeverage: driftUserAccount?.maxMarginRatio
? DRIFT_MARGIN_PRECISION / driftUserAccount?.maxMarginRatio
: null,
driftEnableSpot: driftUserAccount?.isMarginTradingEnabled || false,
driftMarketIndexesSpot: fund?.driftMarketIndexesSpot || [],
};
}

/*
* API methods
*/
Expand Down Expand Up @@ -244,9 +279,8 @@ export class DriftClient {
const manager = apiOptions.signer || this.base.getManager();
const [user] = this.getUser(fund, subAccountId);

const MARGIN_PRECISION = 10_000;
// https://github.com/drift-labs/protocol-v2/blob/babed162b08b1fe34e49a81c5aa3e4ec0a88ecdf/programs/drift/src/math/constants.rs#L183-L184
const marginRatio = MARGIN_PRECISION / maxLeverage;
const marginRatio = DRIFT_MARGIN_PRECISION / maxLeverage;

const tx = await this.base.program.methods
.driftUpdateUserCustomMarginRatio(subAccountId, marginRatio)
Expand Down
62 changes: 59 additions & 3 deletions playground/src/app/risk/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,16 +11,42 @@ import { IntegrationsList } from "./components/integrations-list";
import { integrations } from "./data";
import PageContentWrapper from "@/components/PageContentWrapper";
import { useGlam } from "@glam/anchor/react";
import DynamicForm from "@/components/DynamicForm";
import schema from "../../data/glamRiskSchema.json";
import { useForm } from "react-hook-form";

export default function Risk() {
export default async function Risk() {
//@ts-ignore
const { allFunds, activeFund } = useGlam();
const { allFunds, activeFund, glamClient } = useGlam();

const fundId = activeFund?.addressStr;
const fund: any = fundId
? (allFunds || []).find((f: any) => f.idStr === fundId)
: undefined;

const driftForm = useForm<any>({
defaultValues: {
driftAccessControl: 0,
driftDelegatedAccount: null,
driftMarketIndexesPerp: [],
driftOrderTypes: [],
driftMaxLeverage: null,
driftEnableSpot: false,
driftMarketIndexesSpot: [],
},
});

useEffect(() => {
const fetchDriftData = async () => {
const driftPolicy = await glamClient.drift.fetchPolicyConfig(fund);
for (const [key, value] of Object.entries(driftPolicy)) {
driftForm.setValue(key, value);
}
};

fetchDriftData();
}, [fund]);

//TODO: load on chain data and remove this whole useEffect
const [rerender, setRerender] = useState(0);
useEffect(() => {
Expand All @@ -47,6 +73,23 @@ export default function Risk() {
setRerender(rerender + 1);
}, [fundId]);

// form behavior, change visible fields based on access control
const watchDriftAccessControl = driftForm.watch("driftAccessControl");
useEffect(() => {
if (watchDriftAccessControl === 0) {
schema.drift.fields.driftDelegatedAccount["x-hidden"] = false;
schema.drift.fields.driftMarketIndexesPerp["x-hidden"] = true;
schema.drift.fields.driftOrderTypes["x-hidden"] = true;
schema.drift.fields.driftMarketIndexesSpot["x-hidden"] = true;
} else {
schema.drift.fields.driftDelegatedAccount["x-hidden"] = true;
schema.drift.fields.driftMarketIndexesPerp["x-hidden"] = false;
schema.drift.fields.driftOrderTypes["x-hidden"] = false;
schema.drift.fields.driftMarketIndexesSpot["x-hidden"] = false;
}
setRerender(rerender + 1);
}, [watchDriftAccessControl]);

return (
<PageContentWrapper>
<div className="flex">
Expand All @@ -68,7 +111,20 @@ export default function Risk() {
</TabsContent>
</Tabs>
</div>
<div className="w-full ml-16"></div>
<div className="w-full ml-16 pt-[26px]">
<DynamicForm
schema={schema}
isNested={true}
groups={["drift"]}
formData={driftForm}
onSubmit={(data: any) => {
console.log("submit", data);
}}
onWatch={(data: any) => {
console.log("watch", data);
}}
/>
</div>
</div>
</PageContentWrapper>
);
Expand Down
87 changes: 13 additions & 74 deletions playground/src/app/trade/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -73,69 +73,14 @@ import {
OrderType,
PositionDirection,
} from "@drift-labs/sdk";
import {
DRIFT_ORDER_TYPES,
DRIFT_PERP_MARKETS,
DRIFT_SPOT_MARKETS,
} from "@/constants";

const spotMarkets = [{ label: "SOL/USDC", value: "SOL-USDC" }] as const;

const ORDER_TYPES: [string, ...string[]] = [
"Market",
"Limit",
"Trigger Market",
"Trigger Limit",
"Oracle",
];

const PERP_MARKETS: [string, ...string[]] = [
"SOL-PERP",
"BTC-PERP",
"ETH-PERP",
"APT-PERP",
"1MBONK-PERP",
"MATIC-PERP",
"ARB-PERP",
"DOGE-PERP",
"BNB-PERP",
"SUI-PERP",
"1MPEPE-PERP",
"OP-PERP",
"RENDER-PERP",
"XRP-PERP",
"HNT-PERP",
"INJ-PERP",
"LINK-PERP",
"RLB-PERP",
"PYTH-PERP",
"TIA-PERP",
"JTO-PERP",
"SEI-PERP",
"AVAX-PERP",
"WIF-PERP",
"JUP-PERP",
"DYM-PERP",
"TAO-PERP",
"W-PERP",
"KMNO-PERP",
"TNSR-PERP",
"DRIFT-PERP",
"CLOUD-PERP",
"IO-PERP",
"ZEX-PERP",
"POPCAT-PERP",
"1KWEN-PERP",
"TRUMP-WIN-2024-BET",
"KAMALA-POPULAR-VOTE-2024-BET",
"FED-CUT-50-SEPT-2024-BET",
"REPUBLICAN-POPULAR-AND-WIN-BET",
"BREAKPOINT-IGGYERIC-BET",
"DEMOCRATS-WIN-MICHIGAN-BET",
"TON-PERP",
"LANDO-F1-SGP-WIN-BET",
"MOTHER-PERP",
"MOODENG-PERP",
"WARWICK-FIGHT-WIN-BET",
];

const perpsMarkets = PERP_MARKETS.map((x) => ({ label: x, value: x }));
const orderTypes = ORDER_TYPES.map((x) => ({ label: x, value: x }));
const spotMarkets = DRIFT_SPOT_MARKETS.map((x) => ({ label: x, value: x }));
const perpsMarkets = DRIFT_PERP_MARKETS.map((x) => ({ label: x, value: x }));

const swapSchema = z.object({
venue: z.enum(["Jupiter"]),
Expand All @@ -157,14 +102,8 @@ const swapSchema = z.object({

const spotSchema = z.object({
venue: z.enum(["Jupiter", "Drift"]),
spotMarket: z.enum(["SOL-USDC"]),
spotType: z.enum([
"Market",
"Limit",
"Trigger Market",
"Trigger Limit",
"Oracle",
]),
spotMarket: z.enum(DRIFT_SPOT_MARKETS),
spotType: z.enum(DRIFT_ORDER_TYPES),
side: z.enum(["Buy", "Sell"]),
limitPrice: z.number().nonnegative(),
size: z.number().nonnegative(),
Expand All @@ -177,8 +116,8 @@ const spotSchema = z.object({

const perpsSchema = z.object({
venue: z.enum(["Drift"]),
perpsMarket: z.enum(PERP_MARKETS),
perpsType: z.enum(ORDER_TYPES),
perpsMarket: z.enum(DRIFT_PERP_MARKETS),
perpsType: z.enum(DRIFT_ORDER_TYPES),
side: z.enum(["Buy", "Sell"]),
limitPrice: z.number().nonnegative(),
size: z.number().nonnegative(),
Expand Down Expand Up @@ -441,7 +380,7 @@ export default function Trade() {
values.side === "Buy"
? PositionDirection.LONG
: PositionDirection.SHORT,
marketIndex: PERP_MARKETS.indexOf(values.perpsMarket),
marketIndex: DRIFT_PERP_MARKETS.indexOf(values.perpsMarket),
baseAssetAmount: new anchor.BN(values.size * LAMPORTS_PER_SOL),
price: new anchor.BN(values.limitPrice), // set a very low limit price
});
Expand Down Expand Up @@ -1428,7 +1367,7 @@ export default function Trade() {

<div className="flex">
<ExplorerLink
path={`/account/${driftUserAccount}`}
path={`https://app.drift.trade/?userAccount=${driftUserAccount}`}
label={driftUserAccount}
/>
</div>
Expand Down
Loading