Skip to main content
This guide demonstrates how to use GLAM vaults with popular DeFi protocols on Solana, including Jupiter for swaps, Marinade for liquid staking, and native staking operations.

Jupiter swap integration

Jupiter is the leading swap aggregator on Solana. The GLAM SDK provides seamless integration for token swaps.

Basic swap using quote params

import { GlamClient, WSOL, MSOL } from "@glamsystems/glam-sdk";

const glamClient = new GlamClient({ jupiterApiKey: "your-api-key" });

const txSig = await glamClient.jupiterSwap.swap({
  quoteParams: {
    inputMint: WSOL.toBase58(),
    outputMint: MSOL.toBase58(),
    amount: 50_000_000, // 0.05 SOL in lamports
    swapMode: "ExactIn",
    onlyDirectRoutes: true,
    maxAccounts: 8,
  },
});

console.log("✅ Swap successful:", txSig);

Swap with pre-fetched quote

import { GlamClient, WSOL, USDC } from "@glamsystems/glam-sdk";

const glamClient = new GlamClient({ jupiterApiKey: "your-api-key" });

// Get quote from Jupiter API
const quoteResponse = await glamClient.jupiterSwap.jupApi.getQuoteResponse({
  inputMint: WSOL.toBase58(),
  outputMint: USDC.toBase58(),
  amount: 100_000_000, // 0.1 SOL
  swapMode: "ExactIn",
});

console.log("Quote:", {
  inputAmount: quoteResponse.inAmount,
  outputAmount: quoteResponse.outAmount,
  priceImpact: quoteResponse.priceImpactPct,
});

// Execute swap with quote
const txSig = await glamClient.jupiterSwap.swap({
  quoteResponse,
});

console.log("✅ Swap successful:", txSig);

Swap with custom instructions

For advanced use cases, you can provide pre-built swap instructions.
import { GlamClient, WSOL, MSOL } from "@glamsystems/glam-sdk";

const glamClient = new GlamClient({ jupiterApiKey: "your-api-key" });

const quoteParams = {
  inputMint: WSOL.toBase58(),
  outputMint: MSOL.toBase58(),
  amount: 50_000_000,
  swapMode: "ExactIn" as const,
};

// Get quote and swap instructions
const quoteResponse = await glamClient.jupiterSwap.jupApi.getQuoteResponse(quoteParams);
const swapInstructions = await glamClient.jupiterSwap.jupApi.getSwapInstructions(
  quoteResponse,
  glamClient.vaultPda,
);

// Execute with custom instructions
const txSig = await glamClient.jupiterSwap.swap({
  quoteParams,
  quoteResponse,
  swapInstructions,
});

console.log("✅ Swap successful:", txSig);
The Jupiter API key is optional for basic usage but recommended for production to avoid rate limits.

Marinade liquid staking

Marinade Finance offers liquid staking for SOL. Deposit SOL and receive mSOL (Marinade Staked SOL) tokens.

Deposit SOL to Marinade

import { BN } from "@coral-xyz/anchor";
import { GlamClient } from "@glamsystems/glam-sdk";

const glamClient = new GlamClient();

// Deposit 20 SOL to Marinade
const amount = new BN(20_000_000_000); // 20 SOL in lamports

const txSig = await glamClient.marinade.deposit(amount);
console.log("✅ Deposited 20 SOL to Marinade:", txSig);
The vault will receive mSOL tokens in return, which represent your staked SOL plus accrued rewards.

Native stake deposit to Marinade

You can create a native stake account and authorize Marinade to manage it.
import { BN } from "@coral-xyz/anchor";
import { GlamClient } from "@glamsystems/glam-sdk";

const glamClient = new GlamClient();

// Create and authorize a stake account for Marinade
const amount = new BN(1_000_000_000); // 1 SOL

const txSig = await glamClient.marinade.depositNative(amount);
console.log("✅ Created native stake account:", txSig);

Deposit existing stake account

import { GlamClient, getStakeAccountsWithStates } from "@glamsystems/glam-sdk";

const glamClient = new GlamClient();

// Get vault's stake accounts
const stakeAccounts = await getStakeAccountsWithStates(
  glamClient.connection,
  glamClient.vaultPda,
);

if (stakeAccounts.length > 0) {
  const txSig = await glamClient.marinade.depositStakeAccount(
    stakeAccounts[0].address
  );
  console.log("✅ Deposited stake account:", txSig);
}

Withdraw from Marinade

Withdraw your stake from Marinade by burning mSOL tokens and receiving a stake account.
import { BN } from "@coral-xyz/anchor";
import { GlamClient } from "@glamsystems/glam-sdk";

const glamClient = new GlamClient();

// Withdraw 1 mSOL (approximately 1 SOL worth of stake)
const amount = new BN(1e9); // 1 mSOL in lamports

const txSig = await glamClient.marinade.withdrawStakeAccount(
  amount,
  true, // deactivate the stake account immediately
);

console.log("✅ Withdrew stake account:", txSig);

Native staking operations

GLAM vaults support native Solana staking operations for maximum control over your stake.

Delegate stake to a validator

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

const glamClient = new GlamClient();

const validatorVote = new PublicKey("GJQjnyhSG9jN1AdMHTSyTxUR44hJHEGCmNzkidw9z3y8");
const amount = new BN(10_000_000_000); // 10 SOL

const txSig = await glamClient.stake.initializeAndDelegateStake(
  validatorVote,
  amount,
);

console.log("✅ Stake delegated to validator:", txSig);

Deactivate stake accounts

import { GlamClient, getStakeAccountsWithStates } from "@glamsystems/glam-sdk";

const glamClient = new GlamClient();

// Get active stake accounts
const stakeAccounts = await getStakeAccountsWithStates(
  glamClient.connection,
  glamClient.vaultPda,
);

const activeStakes = stakeAccounts
  .filter(s => s.state === "active")
  .map(s => s.address);

if (activeStakes.length > 0) {
  const txSig = await glamClient.stake.deactivate(activeStakes);
  console.log("✅ Deactivated stake accounts:", txSig);
}

Withdraw from stake accounts

After deactivation, you can withdraw SOL back to the vault.
import { GlamClient, getStakeAccountsWithStates } from "@glamsystems/glam-sdk";

const glamClient = new GlamClient();

const stakeAccounts = await getStakeAccountsWithStates(
  glamClient.connection,
  glamClient.vaultPda,
);

const inactiveStakes = stakeAccounts
  .filter(s => s.state === "inactive")
  .map(s => s.address);

if (inactiveStakes.length > 0) {
  const txSig = await glamClient.stake.withdraw(inactiveStakes);
  console.log("✅ Withdrew from stake accounts:", txSig);
}

Split stake account

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

const glamClient = new GlamClient();

const existingStake = new PublicKey("existing-stake-account");
const splitAmount = new BN(5_000_000_000); // Split 5 SOL

const { newStake, txSig } = await glamClient.stake.split(
  existingStake,
  splitAmount,
);

console.log("✅ Stake split:", txSig);
console.log("New stake account:", newStake.toBase58());

Merge stake accounts

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

const glamClient = new GlamClient();

const destinationStake = new PublicKey("destination-stake");
const sourceStake = new PublicKey("source-stake");

const txSig = await glamClient.stake.merge(
  destinationStake,
  sourceStake,
);

console.log("✅ Stakes merged:", txSig);

Stake pool operations

GLAM supports deposits and withdrawals from Solana stake pools.

Deposit SOL to stake pool

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

const glamClient = new GlamClient();

const stakePool = new PublicKey("stake-pool-address");
const amount = new BN(10_000_000_000); // 10 SOL

const txSig = await glamClient.stakePool.depositSol(
  stakePool,
  amount,
);

console.log("✅ Deposited SOL to stake pool:", txSig);

Deposit stake account to pool

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

const glamClient = new GlamClient();

const stakePool = new PublicKey("stake-pool-address");
const stakeAccount = new PublicKey("stake-account");

const txSig = await glamClient.stakePool.depositStake(
  stakePool,
  stakeAccount,
);

console.log("✅ Deposited stake to pool:", txSig);

Withdraw stake from pool

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

const glamClient = new GlamClient();

const stakePool = new PublicKey("stake-pool-address");
const amount = new BN(5_000_000_000); // 5 pool tokens

const txSig = await glamClient.stakePool.withdrawStake(
  stakePool,
  amount,
  true, // deactivate immediately
);

console.log("✅ Withdrew stake from pool:", txSig);

Unstake LST tokens

The SDK provides a convenience method to unstake liquid staking tokens.
import { BN } from "@coral-xyz/anchor";
import { MSOL, GlamClient } from "@glamsystems/glam-sdk";

const glamClient = new GlamClient();

// Unstake mSOL (Marinade)
const amount = new BN(1_000_000_000); // 1 mSOL

const txSig = await glamClient.stakePool.unstake(
  MSOL,
  amount,
  true, // deactivate the resulting stake account
);

console.log("✅ Unstaked mSOL:", txSig);

Creating Squads multisig proposals

For vaults controlled by Squads multisig, you can create proposals for GLAM operations.
import {
  PublicKey,
  Transaction,
  TransactionMessage,
} from "@solana/web3.js";
import {
  GlamClient,
  getProgramAndBitflagByProtocolName,
} from "@glamsystems/glam-sdk";
import * as multisig from "@sqds/multisig";

const glamClient = new GlamClient({
  statePda: new PublicKey(process.env.GLAM_STATE!),
});
const multisigPda = new PublicKey(process.env.SQUADS_MULTISIG!);

// Get Squads vault PDA
const [squadsVaultPda] = multisig.getVaultPda({
  multisigPda,
  index: 0,
});

// Prepare GLAM instruction (enable Jupiter Swap)
const permissionsMap = getProgramAndBitflagByProtocolName();
const [integrationProgram, protocolBitflag] = permissionsMap["JupiterSwap"];

const ix = await glamClient.access.txBuilder.enableDisableProtocolsIx(
  new PublicKey(integrationProgram),
  parseInt(protocolBitflag, 2),
  true,
  squadsVaultPda, // Squads vault is the signer
);

// Wrap in transaction message
const blockhash = (await glamClient.blockhashWithCache.get()).blockhash;
const txMessage = new TransactionMessage({
  payerKey: squadsVaultPda,
  recentBlockhash: blockhash,
  instructions: [ix],
});

// Get current transaction index
const multisigInfo = await multisig.accounts.Multisig.fromAccountAddress(
  glamClient.connection,
  multisigPda,
);
const currentTransactionIndex = Number(multisigInfo.transactionIndex);
const newTransactionIndex = BigInt(currentTransactionIndex + 1);

// Create Squads transaction and proposal
const ixCreateSquadsTx = multisig.instructions.vaultTransactionCreate({
  multisigPda,
  transactionIndex: newTransactionIndex,
  creator: glamClient.signer,
  vaultIndex: 0,
  ephemeralSigners: 0,
  transactionMessage: txMessage,
});

const ixCreateSquadsProposal = multisig.instructions.proposalCreate({
  multisigPda,
  creator: glamClient.signer,
  transactionIndex: newTransactionIndex,
});

// Submit transaction
const tx = new Transaction().add(ixCreateSquadsTx, ixCreateSquadsProposal);
const vTx = await glamClient.intoVersionedTransaction(tx);
const txSig = await glamClient.sendAndConfirm(vTx);

console.log("✅ Squads proposal created:", txSig);

// Get proposal URL
const [transactionPda] = multisig.getTransactionPda({
  multisigPda,
  index: newTransactionIndex,
});
console.log(
  "View proposal:",
  `https://app.squads.so/squads/${squadsVaultPda}/transactions/${transactionPda}`
);
Squads integration allows multiple signers to approve GLAM vault operations, adding an extra layer of security for high-value vaults.

Build docs developers (and LLMs) love