Skip to main content
The access sub-client provides methods for managing vault permissions, enabling integrations, and configuring delegate access. This guide covers how to use the SDK to implement granular access control for your vault.

When to Use Access Control

Access control is essential when you need to:
  • Delegate operations - Allow bots, managers, or multisig members to perform specific actions
  • Enable protocol integrations - Activate DeFi protocols (Drift, Jupiter, Kamino) for your vault
  • Enforce guardrails - Set allowlists/blocklists for transfers and swaps
  • Emergency management - Quickly revoke compromised delegate access

Permission Hierarchy

  • Integration ACLs define which external programs (Drift, Jupiter, Kamino) can interact with your vault and what protocol-specific policies apply.
  • Delegate ACLs control which external accounts can act on behalf of the vault owner, with permissions scoped per integration and protocol.

Enabling Protocols for Integrations

Before a vault can interact with DeFi protocols, you must enable them at the integration level.

Enable Protocols

import { GlamClient, getProgramAndBitflagByProtocolName } from "@glamsystems/glam-sdk";
import { PublicKey } from "@solana/web3.js";

const glamClient = new GlamClient({ statePda: vaultStatePubkey });

// Get protocol info by name
const permissionsMap = getProgramAndBitflagByProtocolName();
const [integrationProgram, protocolBitflag] = permissionsMap["JupiterSwap"];

// Enable Jupiter Swap for the vault
const txSig = await glamClient.access.enableProtocols(
  new PublicKey(integrationProgram),
  parseInt(protocolBitflag, 2)
);

Disable Protocols

// Disable Jupiter Swap
const txSig = await glamClient.access.disableProtocols(
  new PublicKey(integrationProgram),
  parseInt(protocolBitflag, 2)
);

Managing Delegate Permissions

Delegates start with no permissions and must be explicitly granted access.

Grant Permissions

import { GlamClient, getProgramAndBitflagByProtocolName } from "@glamsystems/glam-sdk";
import { PublicKey } from "@solana/web3.js";
import { BN } from "@coral-xyz/anchor";

const glamClient = new GlamClient({ statePda: vaultStatePubkey });

// Grant delegate permission to swap tokens via Jupiter
const delegatePubkey = new PublicKey("De1egate111111111111111111111111111111111111");
const permissionsMap = getProgramAndBitflagByProtocolName();
const [integrationProgram, protocolBitflag] = permissionsMap["JupiterSwap"];

// Permission bits: SwapAny=0b001, SwapLst=0b010, SwapAllowlisted=0b100
const permissions = new BN(0b001); // SwapAny permission

const txSig = await glamClient.access.grantDelegatePermissions(
  delegatePubkey,
  new PublicKey(integrationProgram),
  parseInt(protocolBitflag, 2),
  permissions
);

Revoke Permissions

// Revoke specific permissions from delegate
const txSig = await glamClient.access.revokeDelegatePermissions(
  delegatePubkey,
  new PublicKey(integrationProgram),
  parseInt(protocolBitflag, 2),
  permissions // permissions to revoke
);

Protocol Policies

Policies add parameter-level access control through allowlists and blocklists.

Set Transfer Allowlist

import { GlamClient, getProgramAndBitflagByProtocolName, TransferPolicy } from "@glamsystems/glam-sdk";
import { PublicKey } from "@solana/web3.js";

const glamClient = new GlamClient({ statePda: vaultStatePubkey });
const permissionsMap = getProgramAndBitflagByProtocolName();

// Create policy with allowed destination addresses
const destinationAddress1 = new PublicKey("Dest1nation11111111111111111111111111111111");
const destinationAddress2 = new PublicKey("Dest2nation11111111111111111111111111111111");

const policy = new TransferPolicy([]);
policy.allowlist.push(destinationAddress1);
policy.allowlist.push(destinationAddress2);

// Get SPL Token protocol info
const [splProgram, tokenBitflag] = permissionsMap["Token"];

const txSig = await glamClient.access.setProtocolPolicy(
  new PublicKey(splProgram),
  parseInt(tokenBitflag, 2),
  policy.encode()
);

Set Swap Policy

import { GlamClient, getProgramAndBitflagByProtocolName, SwapPolicy } from "@glamsystems/glam-sdk";
import { PublicKey } from "@solana/web3.js";

const glamClient = new GlamClient({ statePda: vaultStatePubkey });
const permissionsMap = getProgramAndBitflagByProtocolName();

// Create policy with allowed tokens for swapping
const allowedTokenMint1 = new PublicKey("Token1Mint1111111111111111111111111111111111");
const allowedTokenMint2 = new PublicKey("Token2Mint1111111111111111111111111111111111");

const policy = new SwapPolicy([]);
policy.allowlist.push(allowedTokenMint1);
policy.allowlist.push(allowedTokenMint2);

const [jupiterProgram, swapBitflag] = permissionsMap["JupiterSwap"];

const txSig = await glamClient.access.setProtocolPolicy(
  new PublicKey(jupiterProgram),
  parseInt(swapBitflag, 2),
  policy.encode()
);

Emergency Access

Emergency updates bypass timelock for critical security situations.
import { GlamClient } from "@glamsystems/glam-sdk";
import { PublicKey } from "@solana/web3.js";

const glamClient = new GlamClient({ statePda: vaultStatePubkey });

// Emergency disable a compromised delegate
const compromisedDelegatePubkey = new PublicKey("Compromised11111111111111111111111111111111");

const txSig = await glamClient.access.emergencyAccessUpdate({
  disabledIntegrations: [],
  disabledDelegates: [compromisedDelegatePubkey],
  stateEnabled: true // keep vault enabled, just disable delegate
});
Emergency access updates bypass the timelock and should only be used when immediate action is required.

Common Patterns

Trading Bot Setup

import { GlamClient, getProgramAndBitflagByProtocolName } from "@glamsystems/glam-sdk";
import { PublicKey } from "@solana/web3.js";
import { BN } from "@coral-xyz/anchor";

const glamClient = new GlamClient({ statePda: vaultStatePubkey });
const permissionsMap = getProgramAndBitflagByProtocolName();

// 1. Enable Jupiter Swap for the vault
const [jupiterProgram, jupiterBitflag] = permissionsMap["JupiterSwap"];
await glamClient.access.enableProtocols(
  new PublicKey(jupiterProgram),
  parseInt(jupiterBitflag, 2)
);

// 2. Grant bot delegate swap permissions
const botWallet = new PublicKey("TradingBot11111111111111111111111111111111");
await glamClient.access.grantDelegatePermissions(
  botWallet,
  new PublicKey(jupiterProgram),
  parseInt(jupiterBitflag, 2),
  new BN(0b001) // SwapAny permission
);

Multisig Manager Setup

import { GlamClient, getProgramAndBitflagByProtocolName } from "@glamsystems/glam-sdk";
import { PublicKey } from "@solana/web3.js";
import { BN } from "@coral-xyz/anchor";

const glamClient = new GlamClient({ statePda: vaultStatePubkey });
const permissionsMap = getProgramAndBitflagByProtocolName();

// Different managers with different responsibilities
const treasuryManager = new PublicKey("Treasury111111111111111111111111111111111");
const tradingManager = new PublicKey("TradingMgr11111111111111111111111111111111");

// Enable Drift for the vault
const [driftProgram, driftBitflag] = permissionsMap["DriftProtocol"];
await glamClient.access.enableProtocols(
  new PublicKey(driftProgram),
  parseInt(driftBitflag, 2)
);

// Treasury manager: deposit/withdraw only
await glamClient.access.grantDelegatePermissions(
  treasuryManager,
  new PublicKey(driftProgram),
  parseInt(driftBitflag, 2),
  new BN(0b0000011000) // Deposit + Withdraw
);

// Trading manager: order management only
await glamClient.access.grantDelegatePermissions(
  tradingManager,
  new PublicKey(driftProgram),
  parseInt(driftBitflag, 2),
  new BN(0b1111000000) // CreateModifyOrders + CancelOrders + PerpMarkets + SpotMarkets
);

AI Yield Optimizer

import { GlamClient, getProgramAndBitflagByProtocolName } from "@glamsystems/glam-sdk";
import { PublicKey } from "@solana/web3.js";
import { BN } from "@coral-xyz/anchor";

const glamClient = new GlamClient({ statePda: vaultStatePubkey });
const permissionsMap = getProgramAndBitflagByProtocolName();

// Enable Kamino lending and vaults
const [kaminoLendingProgram, lendingBitflag] = permissionsMap["KaminoLending"];
const [kaminoVaultsProgram, vaultsBitflag] = permissionsMap["KaminoVaults"];

await glamClient.access.enableProtocols(
  new PublicKey(kaminoLendingProgram),
  parseInt(lendingBitflag, 2)
);

await glamClient.access.enableProtocols(
  new PublicKey(kaminoVaultsProgram),
  parseInt(vaultsBitflag, 2)
);

// Grant AI agent permission to deposit/withdraw across protocols
const aiAgent = new PublicKey("AiAgent1111111111111111111111111111111111111");

await glamClient.access.grantDelegatePermissions(
  aiAgent,
  new PublicKey(kaminoLendingProgram),
  parseInt(lendingBitflag, 2),
  new BN(0b00110) // Deposit + Withdraw
);

await glamClient.access.grantDelegatePermissions(
  aiAgent,
  new PublicKey(kaminoVaultsProgram),
  parseInt(vaultsBitflag, 2),
  new BN(0b11) // Deposit + Withdraw
);

References