Skip to main content
GLAM provides a rich set of options to customize a vault. This page explains how to create and configure a vault using the GLAM SDK.

Vault

To create a vault, we use the state sub-client’s create method:
create-vault.ts
import {
  GlamClient,
  WSOL,
  nameToChars,
  StateAccountType
} from "@glamsystems/glam-sdk";

// Initialize the GLAM client
const glamClient = new GlamClient();

// Build a vault state model
const stateModel = {
    accountType: StateAccountType.VAULT,
    name: nameToChars("GLAM Vault Demo"),
    enabled: true,
    assets: [WSOL],
};

// Create the vault
const txSig = await glamClient.state.create(
    stateModel,
    WSOL, // base asset
    { simulate: true },
);
The code above is equivalent to creating the vault with glam-cli using the following template:
vault.json
{
  "state": {
    "accountType": "vault",
    "name": "GLAM Vault Demo",
    "enabled": true,
    "baseAssetMint": "So11111111111111111111111111111111111111112",
    "assets": ["So11111111111111111111111111111111111111112"]
  }
}

Tokenized Vault

We need to use the mint sub-client’s initialize method to create a tokenized vault. The vault state will be automatically created by the underlying initialize_mint instruction through CPI.
create-tokenized-vault.ts
import {
  GlamClient,
  WSOL,
  nameToChars,
  StateAccountType
} from "@glamsystems/glam-sdk";

// Initialize the GLAM client
const glamClient = new GlamClient();

// Build a mint model
const mintModel = {
  name: nameToChars("GLAM Tokenized Vault Demo"),
  symbol: "gtvdSOL",
  baseAssetMint: WSOL,
  maxCap: new BN(1000_000_000_000), // 1000 SOL max cap
  minSubscription: new BN(1_000_000_000), // 1 SOL min subscription
  minRedemption: new BN(100_000_000), // 0.1 share min redemption
  lockupPeriod: new BN(0), // no lockup period on new shares
  feeStructure: {
    vault: {
      subscriptionFeeBps: 10,
      redemptionFeeBps: 20,
    },
    manager: {
      subscriptionFeeBps: 10,
      redemptionFeeBps: 20,
    },
    management: {
      feeBps: 10,
    },
    performance: {
      feeBps: 2000,
      hurdleRateBps: 500,
      hurdleType: { hard: {} },
    },
    protocol: {
      baseFeeBps: 0, // will be overwritten in program with 1
      flowFeeBps: 0, // will be overwritten in program with 2000
    },
  },
  notifyAndSettle: {
    model: { continuous: {} },
    permissionlessFulfillment: false, // only manager can fulfill
    subscribeNoticePeriodType: { soft: {} },
    subscribeNoticePeriod: new BN(0), // not needed for a vault that allows instant subscription
    subscribeSettlementPeriod: new BN(0), // not needed for a vault that allows instant subscription
    subscribeCancellationWindow: new BN(0), // not needed for a vault that allows instant subscription
    redeemNoticePeriodType: { soft: {} },
    redeemNoticePeriod: new BN(0), // not set
    redeemSettlementPeriod: new BN(0), // not set
    redeemCancellationWindow: new BN(0), // not set
    timeUnit: { slot: {} },
    padding: [0, 0, 0],
  }
}

// Create the tokenized vault
const txSig = await glamClient.mint.initialize(
    mintModel,
    StateAccountType.TOKENIZED_VAULT,
    { simulate: true },
);
The code above is equivalent to creating the vault with glam-cli using the following template:
tokenized-vault.json
{
  "state": {
    "accountType": "tokenizedVault",
    "enabled": true
  },
  "mint": {
    "name": "GLAM Tokenized Vault Demo",
    "symbol": "gtvdSOL",
    "baseAssetMint": "So11111111111111111111111111111111111111112",
    "maxCap": 1000000000000,
    "minSubscription": 1000000000,
    "minRedemption": 100000000,
    "lockupPeriod": 0,
    "feeStructure": {
      "vault": {
        "subscriptionFeeBps": 10,
        "redemptionFeeBps": 10
      },
      "manager": {
        "subscriptionFeeBps": 0,
        "redemptionFeeBps": 0
      },
      "management": {
        "feeBps": 0
      },
      "performance": {
        "feeBps": 2000,
        "hurdleRateBps": 5,
        "hurdleType": "hard"
      }
    },
    "notifyAndSettle": {
      "model": "continuous",
      "permissionlessFulfillment": false,
      "subscribeNoticePeriodType": "soft",
      "subscribeNoticePeriod": 0,
      "subscribeSettlementPeriod": 0,
      "subscribeCancellationWindow": 0,
      "redeemNoticePeriodType": "soft",
      "redeemNoticePeriod": 0,
      "redeemSettlementPeriod": 0,
      "redeemCancellationWindow": 0,
      "timeUnit": "slot"
    }
  }
}

State Model

GLAM SDK abstracts onchain vault state using the StateModel. At vault creation time, the StateModel defines the initial configurations of the vault.
state-model.ts
export class StateIdlModel implements StateModelType {
  accountType: StateAccountType; // vault or tokenizedVault
  name: number[];                // vault name encoded as char array
  uri: string | null;            // vault URI
  enabled: boolean | null;       // enabled flag
  assets: PublicKey[] | null;    // allowed assets
  created: CreatedModel | null;  // creation seeds, pubkey, and timestamp
  owner: PublicKey | null;       // vault owner
  portfolioManagerName: number[] | null;    // portfolio manager name encoded as char array
  borrowable: PublicKey[] | null;           // borrowable assets
  timelockDuration: number | null;          // timelock duration in seconds
  integrationAcls: IntegrationAcl[] | null; // integration ACLs
  delegateAcls: DelegateAcl[] | null;       // delegate ACLs
  ...
}
The SDK provides a convenient method for fetching vault state and builds it into a StateModel object:
fetch-vault-state.ts
const stateModel = await glamClient.fetchStateModel();
By default it fetches the state of the active vault glamClient binds to. You can also fetch the state of a specific vault by passing its public key:
fetch-specific-vault-state.ts
const stateModel = await glamClient.fetchStateModel(vaultPubkey);

Mint Model

GLAM SDK represents the onchain mint data using the MintModel. At tokenized vault creation time, the MintModel defines the initial configurations of the tokenized vault.
mint-model.ts
export class MintIdlModel implements MintModelType {
  symbol: string;  // token metadata symbol
  name: number[];  // token metadata name
  uri: string;     // token metadata URI
  yearInSeconds: number | null;         // number of seconds in a year
  permanentDelegate: PublicKey | null;  // permanent delegate
  defaultAccountStateFrozen: boolean | null; // default account state is frozen if true, otherwise active
  feeStructure: FeeStructure | null;    // fee configurations
  notifyAndSettle: NotifyAndSettle | null;// notification and settlement periods 
  lockupPeriod: number | null;            // lockup period in seconds
  maxCap: BN | null;                      // maximum vault capacity
  minSubscription: BN | null;             // minimum subscription amount
  minRedemption: BN | null;               // minimum redemption amount
  allowlist: PublicKey[] | null;          // allowlist of users    
  blocklist: PublicKey[] | null;          // blocklist of users
  ...
}
The MintModel of a tokenized vault can be accessed via stateModel.mintModel.
I