Skip to main content
Use these instructions when your strategy vault should interact with Orca Whirlpools. The Exponent SDK does not build Orca instructions directly. Build the Orca TransactionInstruction with the Orca SDK or your own client, then wrap it with orcaWhirlpoolAction before passing it to createVaultSyncTransaction. The vault hook validates Orca Whirlpool instructions, checks vault-owned token accounts, and records opened positions so they can be included in AUM calculations.

Transaction structure

Every Orca Whirlpool action goes through createVaultSyncTransaction.
import {
  createVaultSyncTransaction,
  orcaWhirlpoolAction,
} from "@exponent-labs/exponent-sdk";
import { Transaction, sendAndConfirmTransaction } from "@solana/web3.js";

const {
  setupInstructions,
  preInstructions,
  instruction,
  postInstructions,
  signers,
} = await createVaultSyncTransaction({
  instructions: [
    orcaWhirlpoolAction.openPositionWithTokenExtensions({
      instruction: openPositionIx,
      signers: [positionMintKeypair],
      addressLookupTableAddresses,
    }),
  ],
  owner: vaultPda,
  connection,
  policyPda,
  vaultPda,
  signer: wallet.publicKey,
  vaultAddress,
});

const tx = new Transaction().add(
  ...setupInstructions,
  ...preInstructions,
  instruction,
  ...postInstructions,
);
await sendAndConfirmTransaction(connection, tx, [wallet, ...signers]);
PartWhat it contains
setupInstructionsSetup instructions that must run before refreshes or the sync step
preInstructionsPermissionless refresh instructions that must run before the sync step
instructionThe Squads sync transaction instruction wrapping the vault-signed Orca action
postInstructionsPermissionless refresh instructions that must run after the sync step
signersExtra signers forwarded from the wrapped Orca action
Include any Orca signers in the signers field passed to orcaWhirlpoolAction. createVaultSyncTransaction returns them in result.signers so they can sign the final transaction.

Action builder parameters

Each orcaWhirlpoolAction method accepts the same parameter shape. The examples below assume you already built the Orca instruction with the Orca SDK or client.
ParameterTypeDescription
instructionTransactionInstructionPre-built Orca Whirlpool instruction
signersSigner[]Optional. Extra local signers required by the Orca instruction
addressLookupTableAddressesPublicKey[]Optional. ALT addresses needed when compiling the transaction

Supported actions

MethodOrca action
orcaWhirlpoolAction.openPositionWithTokenExtensions(...)Open a Whirlpool position
orcaWhirlpoolAction.increaseLiquidityV2(...)Increase liquidity on an existing position
orcaWhirlpoolAction.increaseLiquidityByTokenAmountsV2(...)Increase liquidity from token amount inputs
orcaWhirlpoolAction.decreaseLiquidityV2(...)Decrease liquidity on an existing position
orcaWhirlpoolAction.collectFeesV2(...)Collect accrued trading fees
orcaWhirlpoolAction.collectRewardV2(...)Collect one Whirlpool reward
orcaWhirlpoolAction.closePositionWithTokenExtensions(...)Close a tracked Whirlpool position
orcaWhirlpoolAction.swapV2(...)Swap through an Orca Whirlpool

Open a position

Wrap the Orca open-position instruction with the matching Orca action helper.
const result = await createVaultSyncTransaction({
  instructions: [
    orcaWhirlpoolAction.openPositionWithTokenExtensions({
      instruction: openPositionIx,
      signers: [positionMintKeypair],
      addressLookupTableAddresses,
    }),
  ],
  owner: vaultPda,
  connection,
  policyPda,
  vaultPda,
  signer: wallet.publicKey,
  vaultAddress,
});

const tx = new Transaction().add(
  ...result.setupInstructions,
  ...result.preInstructions,
  result.instruction,
  ...result.postInstructions,
);
await sendAndConfirmTransaction(connection, tx, [wallet, ...result.signers]);
The SDK tracks opened Orca positions for vault AUM routing. Keep using the same vault owner and vault-owned token accounts when you later modify or close the position.

Increase liquidity

Use increaseLiquidityV2 or increaseLiquidityByTokenAmountsV2 depending on the Orca instruction you built.
const result = await createVaultSyncTransaction({
  instructions: [
    orcaWhirlpoolAction.increaseLiquidityV2({
      instruction: increaseLiquidityIx,
      addressLookupTableAddresses,
    }),
  ],
  owner: vaultPda,
  connection,
  policyPda,
  vaultPda,
  signer: wallet.publicKey,
  vaultAddress,
});

Decrease liquidity

Use decreaseLiquidityV2 when the vault should remove liquidity from a tracked Orca position.
const result = await createVaultSyncTransaction({
  instructions: [
    orcaWhirlpoolAction.decreaseLiquidityV2({
      instruction: decreaseLiquidityIx,
      addressLookupTableAddresses,
    }),
  ],
  owner: vaultPda,
  connection,
  policyPda,
  vaultPda,
  signer: wallet.publicKey,
  vaultAddress,
});

Collect fees and rewards

Use collectFeesV2 for trading fees and collectRewardV2 for Whirlpool rewards.
const result = await createVaultSyncTransaction({
  instructions: [
    orcaWhirlpoolAction.collectFeesV2({ instruction: collectFeesIx }),
    orcaWhirlpoolAction.collectRewardV2({ instruction: collectRewardIx }),
  ],
  owner: vaultPda,
  connection,
  policyPda,
  vaultPda,
  signer: wallet.publicKey,
  vaultAddress,
});

Swap

Use swapV2 when the vault should trade between the Whirlpool token pair.
const result = await createVaultSyncTransaction({
  instructions: [
    orcaWhirlpoolAction.swapV2({
      instruction: swapIx,
      addressLookupTableAddresses,
    }),
  ],
  owner: vaultPda,
  connection,
  policyPda,
  vaultPda,
  signer: wallet.publicKey,
  vaultAddress,
});

Close a position

Close the tracked position after liquidity, fees, and rewards are withdrawn.
const result = await createVaultSyncTransaction({
  instructions: [
    orcaWhirlpoolAction.closePositionWithTokenExtensions({
      instruction: closePositionIx,
      addressLookupTableAddresses,
    }),
  ],
  owner: vaultPda,
  connection,
  policyPda,
  vaultPda,
  signer: wallet.publicKey,
  vaultAddress,
});
A matching policy must exist before executing. See Policy Builders.