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]);
| Part | What it contains |
|---|
setupInstructions | Setup instructions that must run before refreshes or the sync step |
preInstructions | Permissionless refresh instructions that must run before the sync step |
instruction | The Squads sync transaction instruction wrapping the vault-signed Orca action |
postInstructions | Permissionless refresh instructions that must run after the sync step |
signers | Extra 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.
| Parameter | Type | Description |
|---|
instruction | TransactionInstruction | Pre-built Orca Whirlpool instruction |
signers | Signer[] | Optional. Extra local signers required by the Orca instruction |
addressLookupTableAddresses | PublicKey[] | Optional. ALT addresses needed when compiling the transaction |
Supported actions
| Method | Orca 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.