diff --git a/anchor/programs/glam/src/instructions/drift.rs b/anchor/programs/glam/src/instructions/drift.rs index a8fdc4de..ac98281e 100644 --- a/anchor/programs/glam/src/instructions/drift.rs +++ b/anchor/programs/glam/src/instructions/drift.rs @@ -420,12 +420,36 @@ pub fn drift_place_orders_handler<'c: 'info, 'info>( ctx: Context<'_, '_, 'c, 'info, DriftPlaceOrders<'info>>, order_params: Vec, ) -> Result<()> { + let fund = &ctx.accounts.fund; for order in &order_params { let permission = match order.market_type { MarketType::Spot => Permission::DriftSpotMarket, MarketType::Perp => Permission::DriftPerpMarket, }; acl::check_access(&ctx.accounts.fund, &ctx.accounts.manager.key, permission)?; + + match order.market_type { + MarketType::Spot => { + if let Some(drift_market_indexes_spot) = fund.drift_market_indexes_spot() { + if drift_market_indexes_spot.len() > 0 { + require!( + drift_market_indexes_spot.contains(&(order.market_index as u32)), + AccessError::NotAuthorized + ); + } + } + } + MarketType::Perp => { + if let Some(drift_market_indexes_perp) = fund.drift_market_indexes_perp() { + if drift_market_indexes_perp.len() > 0 { + require!( + drift_market_indexes_perp.contains(&(order.market_index as u32)), + AccessError::NotAuthorized + ); + } + } + } + } } let fund_key = ctx.accounts.fund.key(); diff --git a/anchor/programs/glam/src/instructions/manager.rs b/anchor/programs/glam/src/instructions/manager.rs index 2041bd1d..6ad82fd6 100644 --- a/anchor/programs/glam/src/instructions/manager.rs +++ b/anchor/programs/glam/src/instructions/manager.rs @@ -535,6 +535,48 @@ pub fn update_fund_handler<'c: 'info, 'info>( } } + if !fund_model.drift_market_indexes_perp.is_empty() { + let mut found = false; + for EngineField { name, value } in &mut fund.params[0] { + if let (EngineFieldName::DriftMarketIndexesPerp, EngineFieldValue::VecU32 { val }) = + (name, value) + { + val.clear(); + val.extend(fund_model.drift_market_indexes_perp.clone()); + found = true; + } + } + if !found { + fund.params[0].push(EngineField { + name: EngineFieldName::DriftMarketIndexesPerp, + value: EngineFieldValue::VecU32 { + val: fund_model.drift_market_indexes_perp, + }, + }); + } + } + + if !fund_model.drift_market_indexes_spot.is_empty() { + let mut found = false; + for EngineField { name, value } in &mut fund.params[0] { + if let (EngineFieldName::DriftMarketIndexesSpot, EngineFieldValue::VecU32 { val }) = + (name, value) + { + val.clear(); + val.extend(fund_model.drift_market_indexes_spot.clone()); + found = true; + } + } + if !found { + fund.params[0].push(EngineField { + name: EngineFieldName::DriftMarketIndexesSpot, + value: EngineFieldValue::VecU32 { + val: fund_model.drift_market_indexes_spot, + }, + }); + } + } + Ok(()) } diff --git a/anchor/programs/glam/src/state/accounts.rs b/anchor/programs/glam/src/state/accounts.rs index 077c0ea3..61396bee 100644 --- a/anchor/programs/glam/src/state/accounts.rs +++ b/anchor/programs/glam/src/state/accounts.rs @@ -17,6 +17,8 @@ pub enum EngineFieldName { IntegrationAcls, ExternalTreasuryAccounts, // external accounts with treasury assets LockUp, // share class + DriftMarketIndexesPerp, + DriftMarketIndexesSpot, } #[derive(AnchorDeserialize, AnchorSerialize, Clone, Debug)] @@ -203,6 +205,36 @@ impl FundAccount { return None; } + pub fn drift_market_indexes_perp(&self) -> Option<&Vec> { + for EngineField { name, value } in &self.params[0] { + match name { + EngineFieldName::DriftMarketIndexesPerp => { + return match value { + EngineFieldValue::VecU32 { val: v } => Some(v), + _ => None, + }; + } + _ => { /* ignore */ } + } + } + return None; + } + + pub fn drift_market_indexes_spot(&self) -> Option<&Vec> { + for EngineField { name, value } in &self.params[0] { + match name { + EngineFieldName::DriftMarketIndexesSpot => { + return match value { + EngineFieldValue::VecU32 { val: v } => Some(v), + _ => None, + }; + } + _ => { /* ignore */ } + } + } + return None; + } + pub fn add_to_engine_field(&mut self, engine_field_name: EngineFieldName, pubkey: Pubkey) { // Try to find the MarinadeTickets field, if it exists. let mut engine_field = self.params[0] diff --git a/anchor/programs/glam/src/state/acl.rs b/anchor/programs/glam/src/state/acl.rs index e0776cc2..ac5e6ac6 100644 --- a/anchor/programs/glam/src/state/acl.rs +++ b/anchor/programs/glam/src/state/acl.rs @@ -46,7 +46,7 @@ pub struct DelegateAcl { pub enum IntegrationName { Drift, SplStakePool, - SanctunmStakePool, + SanctumStakePool, NativeStaking, Marinade, Jupiter, diff --git a/anchor/programs/glam/src/state/model/model.rs b/anchor/programs/glam/src/state/model/model.rs index 05380fd4..2b659c87 100644 --- a/anchor/programs/glam/src/state/model/model.rs +++ b/anchor/programs/glam/src/state/model/model.rs @@ -29,6 +29,8 @@ pub struct FundModel { // ACLs pub delegate_acls: Vec, pub integration_acls: Vec, + pub drift_market_indexes_perp: Vec, + pub drift_market_indexes_spot: Vec, // Openfunds pub is_raw_openfunds: bool, diff --git a/anchor/src/client/drift.ts b/anchor/src/client/drift.ts index 4e15029c..45669e47 100644 --- a/anchor/src/client/drift.ts +++ b/anchor/src/client/drift.ts @@ -85,12 +85,12 @@ export class DriftClient { public async updateUserCustomMarginRatio( fund: PublicKey, - marginRatio: number, + maxLeverage: number, // 1=1x, 2=2x ... 50=50x leverage subAccountId: number = 0 ): Promise { const tx = await this.updateUserCustomMarginRatioTx( fund, - marginRatio, + maxLeverage, subAccountId ); return await this.base.sendAndConfirm(tx); @@ -237,13 +237,17 @@ export class DriftClient { public async updateUserCustomMarginRatioTx( fund: PublicKey, - marginRatio: number, + maxLeverage: number, // 1=1x, 2=2x ... 50=50x leverage subAccountId: number = 0, apiOptions: ApiTxOptions = {} ): Promise { 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 tx = await this.base.program.methods .driftUpdateUserCustomMarginRatio(subAccountId, marginRatio) .accounts({ diff --git a/anchor/src/models.ts b/anchor/src/models.ts index d8222bac..c366dba4 100644 --- a/anchor/src/models.ts +++ b/anchor/src/models.ts @@ -25,6 +25,8 @@ export const FundModel = class { assetsWeights: obj.assetsWeights || [], delegateAcls: obj.delegateAcls || [], integrationAcls: obj.integrationAcls || [], + driftMarketIndexesPerp: obj.driftMarketIndexesPerp || [], + driftMarketIndexesSpot: obj.driftMarketIndexesSpot || [], shareClasses: obj.shareClasses ? obj.shareClasses.map( (shareClass: any) => diff --git a/anchor/target/idl/glam.json b/anchor/target/idl/glam.json index 53908187..8415d624 100644 --- a/anchor/target/idl/glam.json +++ b/anchor/target/idl/glam.json @@ -3866,13 +3866,48 @@ "errors": [ { "code": 6000, - "name": "NotAuthorized", - "msg": "Signer is not authorized" + "name": "CloseNotEmptyError", + "msg": "Error closing account: not empty" }, { "code": 6001, - "name": "IntegrationDisabled", - "msg": "Integration is disabled" + "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": [ @@ -4138,6 +4173,12 @@ }, { "name": "LockUp" + }, + { + "name": "DriftMarketIndexesPerp" + }, + { + "name": "DriftMarketIndexesSpot" } ] } @@ -4730,6 +4771,18 @@ } } }, + { + "name": "drift_market_indexes_perp", + "type": { + "vec": "u32" + } + }, + { + "name": "drift_market_indexes_spot", + "type": { + "vec": "u32" + } + }, { "name": "is_raw_openfunds", "type": "bool" @@ -4903,7 +4956,7 @@ "name": "SplStakePool" }, { - "name": "SanctunmStakePool" + "name": "SanctumStakePool" }, { "name": "NativeStaking" diff --git a/anchor/target/types/glam.ts b/anchor/target/types/glam.ts index e3547247..6f191e02 100644 --- a/anchor/target/types/glam.ts +++ b/anchor/target/types/glam.ts @@ -3872,13 +3872,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": "integrationDisabled", - "msg": "Integration is disabled" + "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": [ @@ -4144,6 +4179,12 @@ export type Glam = { }, { "name": "lockUp" + }, + { + "name": "driftMarketIndexesPerp" + }, + { + "name": "driftMarketIndexesSpot" } ] } @@ -4736,6 +4777,18 @@ export type Glam = { } } }, + { + "name": "driftMarketIndexesPerp", + "type": { + "vec": "u32" + } + }, + { + "name": "driftMarketIndexesSpot", + "type": { + "vec": "u32" + } + }, { "name": "isRawOpenfunds", "type": "bool" @@ -4909,7 +4962,7 @@ export type Glam = { "name": "splStakePool" }, { - "name": "sanctunmStakePool" + "name": "sanctumStakePool" }, { "name": "nativeStaking" diff --git a/anchor/tests/glam_drift.spec.ts b/anchor/tests/glam_drift.spec.ts index 0ce77ff9..0bd1ad74 100644 --- a/anchor/tests/glam_drift.spec.ts +++ b/anchor/tests/glam_drift.spec.ts @@ -155,4 +155,35 @@ describe("glam_drift", () => { throw e; } }); + + it("Drift: constrain market", async () => { + try { + const txId = await glamClient.updateFund(fundPDA, { + driftMarketIndexesPerp: [2, 3], + }); + console.log("driftPlaceOrders", txId); + } catch (e) { + console.error(e); + throw e; + } + }); + + it("Drift: place perp order again - should fail", async () => { + const orderParams = getOrderParams({ + orderType: OrderType.LIMIT, + marketType: MarketType.PERP, + direction: PositionDirection.LONG, + marketIndex: 0, + baseAssetAmount: new anchor.BN(10_0000_000), + price: new anchor.BN(100_000_000), // set a very low limit price + }); + + try { + const txId = await glamClient.drift.placeOrder(fundPDA, orderParams); + expect(txId).toBeUndefined(); + } catch (err) { + const errMsg = err.message + err.logs; + expect(errMsg).toContain("Signer is not authorized"); + } + }); }); diff --git a/playground/src/app/access/components/columns.tsx b/playground/src/app/access/components/columns.tsx index b26f8067..03c3807c 100644 --- a/playground/src/app/access/components/columns.tsx +++ b/playground/src/app/access/components/columns.tsx @@ -9,11 +9,14 @@ import Sparkle from "../../../utils/Sparkle"; import TruncateAddress from "@/utils/TruncateAddress"; const tagColors: Record = { - stake: "bg-emerald-100 text-emerald-800 border-emerald-800 dark:bg-emerald-900 dark:text-emerald-400 dark:border-emerald-400", + stake: + "bg-emerald-100 text-emerald-800 border-emerald-800 dark:bg-emerald-900 dark:text-emerald-400 dark:border-emerald-400", swap: "bg-teal-100 text-teal-800 border-teal-800 dark:bg-teal-900 dark:text-teal-400 dark:border-teal-400", - trade: "bg-sky-100 text-sky-800 border-teal-800 dark:bg-sky-900 dark:text-sky-400 dark:border-sky-400", + trade: + "bg-sky-100 text-sky-800 border-teal-800 dark:bg-sky-900 dark:text-sky-400 dark:border-sky-400", lend: "bg-purple-100 text-purple-800 border-purple-800 dark:bg-purple-900 dark:text-purple-400 dark:border-purple-400", - admin: "bg-rose-100 text-rose-800 border-rose-800 dark:bg-rose-900 dark:text-rose-400 dark:border-rose-400", + admin: + "bg-rose-100 text-rose-800 border-rose-800 dark:bg-rose-900 dark:text-rose-400 dark:border-rose-400", }; // Define the type for your row data @@ -42,9 +45,7 @@ export const columns: ColumnDef[] = [ ), cell: ({ row }) => ( -
- -
+
{row.getValue("pubkey")}
), enableSorting: false, enableHiding: false, diff --git a/playground/src/app/access/components/data-table-toolbar.tsx b/playground/src/app/access/components/data-table-toolbar.tsx index bb9bd38b..e619f00b 100644 --- a/playground/src/app/access/components/data-table-toolbar.tsx +++ b/playground/src/app/access/components/data-table-toolbar.tsx @@ -290,9 +290,9 @@ export function DataTableToolbar({ - table.getColumn("name")?.setFilterValue(event.target.value) + table.getColumn("pubkey")?.setFilterValue(event.target.value) } className="h-8 w-[150px] lg:w-[250px]" /> diff --git a/playground/src/app/integrations/page.tsx b/playground/src/app/integrations/page.tsx index 03c263a5..da3d6fd3 100644 --- a/playground/src/app/integrations/page.tsx +++ b/playground/src/app/integrations/page.tsx @@ -331,10 +331,11 @@ export default function Integrations() { [] ); + //TODO: load on chain data and remove this whole useEffect useEffect(() => { let newFundConfig = [[""], [""], [""]]; switch (fundId) { - case "G8NKLJ2Y3TFrjXpfkpGJQZLXvbKKyvNDzc84C8P3DDU8": //gmSOL + case "G8NKLJ2Y3TFrjXpfkpGJQZLXvbKKyvNDzc84C8P3DDU8": // gmSOL case "F22FvADosEScBzKMf5iMmNgyrJfhpy4CgFoPYhVw3SHs": // pSOL newFundConfig = [ [ @@ -355,6 +356,7 @@ export default function Integrations() { integrations[1].active = true; integrations[2].active = false; break; + case "9F7KB5xiFo8bt66Wey5AvNtmLxJYv4oq4tkhgpbgAG9f": // gnUSD case "GXDoZfmdDgB846vYmexuyCEs3C2ByNe7nGcgz4GZa1ZE": // pUSDC newFundConfig = [ [""], diff --git a/playground/src/app/policies/components/policies-list.tsx b/playground/src/app/policies/components/policies-list.tsx deleted file mode 100644 index 4a9a796b..00000000 --- a/playground/src/app/policies/components/policies-list.tsx +++ /dev/null @@ -1,84 +0,0 @@ -import { ComponentProps } from "react" - -import { cn } from "@/lib/utils" -import { Policies } from "../data" -import { usePolicies } from "../use-policy" -import {Badge} from "../../../components/ui/badge"; -import {ScrollArea} from "../../../components/ui/scroll-area"; - -interface PoliciesListProps { - items: Policies[] -} - -export function PoliciesList({ items }: PoliciesListProps) { - const [poilcies, setPolicies] = usePolicies() - - return ( - -
- {items.map((item) => ( - - ))} -
-
- ) -} - -function getBadgeVariantFromLabel( - label: string -): ComponentProps["variant"] { - if (["work"].includes(label.toLowerCase())) { - return "default" - } - - if (["personal"].includes(label.toLowerCase())) { - return "outline" - } - - return "secondary" -} diff --git a/playground/src/app/policies/data.tsx b/playground/src/app/policies/data.tsx deleted file mode 100644 index 15a4ab1b..00000000 --- a/playground/src/app/policies/data.tsx +++ /dev/null @@ -1,25 +0,0 @@ -export const policies = [ - { - id: "1", - name: "Drift", - active: true, - description: "Trade on Drift.", - labels: ["trading","derivatives"] - }, - { - id: "2", - name: "Marinade", - active: false, - description: "Stake on Marinade.", - labels: ["staking"] - }, - { - id: "3", - name: "Jupiter", - active: true, - description: "Swap on Jupiter.", - labels: ["swap","spot"] - }, -] - -export type Policies = (typeof policies)[number] diff --git a/playground/src/app/policies/page.tsx b/playground/src/app/policies/page.tsx index e7fe70e8..0d87e62c 100644 --- a/playground/src/app/policies/page.tsx +++ b/playground/src/app/policies/page.tsx @@ -1,9 +1,16 @@ "use client"; -import {Tabs, TabsContent, TabsList, TabsTrigger} from "../../components/ui/tabs"; -import {PoliciesList} from "./components/policies-list"; -import {policies} from "./data"; +import { + Tabs, + TabsContent, + TabsList, + TabsTrigger, +} from "../../components/ui/tabs"; +import { ShareClassesList } from "../shareclasses/components/shareClasses-list"; +import { shareClasses } from "../shareclasses/data"; import PageContentWrapper from "@/components/PageContentWrapper"; +import DynamicForm from "@/components/DynamicForm"; +import schema from "../../data/glamFormSchema.json"; export default function Policies() { return ( @@ -18,14 +25,21 @@ export default function Policies() { - + - item.active)} /> + item.active)} + /> -
+
+
diff --git a/playground/src/app/policies/use-policy.ts b/playground/src/app/policies/use-policy.ts deleted file mode 100644 index b4cba83c..00000000 --- a/playground/src/app/policies/use-policy.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { atom, useAtom } from "jotai" - -import { Policies, policies } from "./data" - -type Config = { - selected: Policies["id"] | null -} - -const configAtom = atom({ - selected: policies[0].id, -}) - -export function usePolicies() { - return useAtom(configAtom) -} diff --git a/playground/src/app/risk/components/integrations-list.tsx b/playground/src/app/risk/components/integrations-list.tsx index 7dc575da..fe5a8fa9 100644 --- a/playground/src/app/risk/components/integrations-list.tsx +++ b/playground/src/app/risk/components/integrations-list.tsx @@ -1,17 +1,17 @@ -import { ComponentProps } from "react" +import { ComponentProps } from "react"; -import { cn } from "@/lib/utils" +import { cn } from "@/lib/utils"; import { Integrations } from "../data"; import { useIntegrations } from "../use-integration"; -import {Badge} from "../../../components/ui/badge"; -import {ScrollArea} from "../../../components/ui/scroll-area"; +import { Badge } from "../../../components/ui/badge"; +import { ScrollArea } from "../../../components/ui/scroll-area"; interface IntegrationsListProps { - items: Integrations[] + items: Integrations[]; } export function IntegrationsList({ items }: IntegrationsListProps) { - const [integrations, setIntegrations] = useIntegrations() + const [integrations, setIntegrations] = useIntegrations(); return ( @@ -45,8 +45,7 @@ export function IntegrationsList({ items }: IntegrationsListProps) { ? "text-foreground" : "text-muted-foreground" )} - > - + > {/*
{item.subject}
*/} @@ -56,7 +55,11 @@ export function IntegrationsList({ items }: IntegrationsListProps) { {item.labels.length ? (
{item.labels.map((label) => ( - + {label} ))} @@ -66,19 +69,19 @@ export function IntegrationsList({ items }: IntegrationsListProps) { ))}
- ) + ); } function getBadgeVariantFromLabel( label: string ): ComponentProps["variant"] { if (["work"].includes(label.toLowerCase())) { - return "default" + return "default"; } if (["personal"].includes(label.toLowerCase())) { - return "outline" + return "outline"; } - return "secondary" + return "secondary"; } diff --git a/playground/src/app/risk/data.tsx b/playground/src/app/risk/data.tsx index a6c3afc4..6a4c29e7 100644 --- a/playground/src/app/risk/data.tsx +++ b/playground/src/app/risk/data.tsx @@ -1,25 +1,46 @@ export const integrations = [ { - id: "1", + id: 0, name: "Drift", active: true, description: "Trade on Drift.", - labels: ["trading","derivatives"] + labels: ["trade"], }, { - id: "2", + id: 1, + name: "Jupiter", + active: true, + description: "Swap on Jupiter.", + labels: ["swap"], + }, + { + id: 2, name: "Marinade", active: false, description: "Stake on Marinade.", - labels: ["staking"] + labels: ["stake"], }, { - id: "3", - name: "Jupiter", - active: true, - description: "Swap on Jupiter.", - labels: ["swap","spot"] + id: 3, + name: "Sanctum Stake Pools", + active: false, + description: "Stake on Sanctum pools.", + labels: ["stake"], + }, + { + id: 4, + name: "SPL Stake Pools", + active: false, + description: "Stake on SPL pools.", + labels: ["stake"], + }, + { + id: 5, + name: "Native Staking", + active: false, + description: "Stake natively.", + labels: ["stake"], }, -] +]; -export type Integrations = (typeof integrations)[number] +export type Integrations = (typeof integrations)[number]; diff --git a/playground/src/app/risk/page.tsx b/playground/src/app/risk/page.tsx index 2eaab31b..d87e1741 100644 --- a/playground/src/app/risk/page.tsx +++ b/playground/src/app/risk/page.tsx @@ -1,11 +1,52 @@ "use client"; -import {Tabs, TabsContent, TabsList, TabsTrigger} from "../../components/ui/tabs"; -import {IntegrationsList} from "./components/integrations-list"; -import {integrations} from "./data"; +import React, { useState, useCallback, useEffect } from "react"; +import { + Tabs, + TabsContent, + TabsList, + TabsTrigger, +} from "../../components/ui/tabs"; +import { IntegrationsList } from "./components/integrations-list"; +import { integrations } from "./data"; import PageContentWrapper from "@/components/PageContentWrapper"; +import { useGlam } from "@glam/anchor/react"; export default function Risk() { + //@ts-ignore + const { allFunds, activeFund } = useGlam(); + + const fundId = activeFund?.addressStr; + const fund: any = fundId + ? (allFunds || []).find((f: any) => f.idStr === fundId) + : undefined; + + //TODO: load on chain data and remove this whole useEffect + const [rerender, setRerender] = useState(0); + useEffect(() => { + switch (fundId) { + case "G8NKLJ2Y3TFrjXpfkpGJQZLXvbKKyvNDzc84C8P3DDU8": // gmSOL + case "F22FvADosEScBzKMf5iMmNgyrJfhpy4CgFoPYhVw3SHs": // pSOL + integrations[0].active = false; + integrations[1].active = true; + integrations[2].active = true; + integrations[3].active = true; + integrations[4].active = true; + integrations[5].active = false; + break; + case "9F7KB5xiFo8bt66Wey5AvNtmLxJYv4oq4tkhgpbgAG9f": // gnUSD + case "GXDoZfmdDgB846vYmexuyCEs3C2ByNe7nGcgz4GZa1ZE": // pUSDC + integrations[0].active = true; + integrations[1].active = true; + integrations[2].active = false; + integrations[3].active = false; + integrations[4].active = false; + integrations[5].active = false; + break; + } + setRerender(rerender + 1); + }, [fundId]); + return (
@@ -21,12 +62,13 @@ export default function Risk() { - item.active)} /> + item.active)} + />
-
-
+
); diff --git a/playground/src/app/shareclasses/data.tsx b/playground/src/app/shareclasses/data.tsx index 8658ef4b..679e9e12 100644 --- a/playground/src/app/shareclasses/data.tsx +++ b/playground/src/app/shareclasses/data.tsx @@ -1,25 +1,11 @@ export const shareClasses = [ { - id: "1", + id: 0, name: "Share Class 1", active: true, description: "", - labels: ["USD","Accumulating"] + labels: ["Accumulating"], }, - { - id: "2", - name: "Share Class 2", - active: true, - description: "", - labels: ["USD", "Distributing"] - }, - { - id: "3", - name: "Share Class 3", - active: false , - description: "", - labels: ["SOL","Distributing", "Projected"] - }, -] +]; -export type ShareClasses = (typeof shareClasses)[number] +export type ShareClasses = (typeof shareClasses)[number]; diff --git a/playground/src/data/glamFormSchema.json b/playground/src/data/glamFormSchema.json index 97fe7391..f7c5c463 100644 --- a/playground/src/data/glamFormSchema.json +++ b/playground/src/data/glamFormSchema.json @@ -259,10 +259,7 @@ "x-tag": "core", "x-component": "select", "readOnly": false, - "enum": [ - "openEndedFund", - "closedEndedFund" - ], + "enum": ["openEndedFund", "closedEndedFund"], "x-enumSource": "utils/openfundsConstants.tsx", "x-enumValues": "fundStructures", "x-enumValuesLabel": "label", @@ -511,11 +508,7 @@ "x-tag": "core", "x-component": "select", "readOnly": false, - "enum": [ - "accumulating", - "accumulatingAndDistributing", - "distributing" - ], + "enum": ["accumulating", "accumulatingAndDistributing", "distributing"], "x-enumSource": "utils/openfundsConstants.tsx", "x-enumValues": "distributionPolicy", "x-enumValuesLabel": "label", @@ -620,11 +613,7 @@ "x-tag": "core", "x-component": "select", "readOnly": false, - "enum": [ - "shares", - "amount", - "sharesAndAmount" - ], + "enum": ["shares", "amount", "sharesAndAmount"], "x-enumSource": "utils/openfundsConstants.tsx", "x-enumValues": "minimalInitialCategory", "x-enumValuesLabel": "label", @@ -689,11 +678,7 @@ "x-tag": "full", "x-component": "select", "readOnly": false, - "enum": [ - "shares", - "amount", - "sharesAndAmount" - ], + "enum": ["shares", "amount", "sharesAndAmount"], "x-enumSource": "utils/openfundsConstants.tsx", "x-enumValues": "minimalInitialCategory", "x-enumValuesLabel": "label", @@ -782,11 +767,7 @@ "x-tag": "full", "x-component": "select", "readOnly": false, - "enum": [ - "shares", - "cash", - "both" - ], + "enum": ["shares", "cash", "both"], "x-enumSource": "utils/openfundsConstants.tsx", "x-enumValues": "dividendType", "x-enumValuesLabel": "label", @@ -803,15 +784,7 @@ "x-tag": "core", "x-component": "select", "readOnly": false, - "enum": [ - "1", - "2", - "3", - "4", - "5", - "6", - "7" - ], + "enum": ["1", "2", "3", "4", "5", "6", "7"], "x-hidden": false, "x-enforced": false, "minValue": 1, @@ -850,7 +823,7 @@ "x-tag": "full", "x-component": "textarea", "readOnly": false, - "x-hidden": false, + "x-hidden": true, "x-enforced": false, "minLength": 3, "maxLength": 256 @@ -1101,6 +1074,49 @@ } } }, + "shareClassPolicy": { + "type": "object", + "fields": { + "hasPermanentDelegate": { + "x-id": "OFGS410948", + "type": "boolean", + "title": "Has Permanent Delegate", + "description": "Indicates if the share class has a permanent delegate", + "x-order": 1, + "x-tag": "glam", + "x-component": "select", + "readOnly": false, + "x-hidden": false, + "x-enforced": false + }, + "lockUpPeriodInSeconds": { + "x-id": "OFGS410955", + "type": "number", + "title": "Lock-up Period in Seconds", + "description": "Duration of the lock-up period in seconds", + "x-order": 2, + "x-tag": "glam", + "x-component": "input", + "readOnly": false, + "x-hidden": false, + "x-enforced": false + }, + "lockUpComment": { + "x-id": "OFST410952", + "type": "string", + "title": "Lock-up Comment", + "description": "Details about the lock-up period and conditions", + "x-order": 3, + "x-tag": "full", + "x-component": "textarea", + "readOnly": false, + "x-hidden": false, + "x-enforced": false, + "minLength": 3, + "maxLength": 256 + } + } + }, "fundManager": { "type": "object", "fields": {