Solana Actions
Query, deposit into, and redeem from Solana vaults with the Upshift SDK, plus low-level Anchor utilities and constants.
Overview
Solana vault interactions use the same pattern as EVM:
- Use
sdk.getVault()to query vault data - Use
sdk.solana.vaultDeposit()to deposit - Use
sdk.solana.vaultRedeem()to withdraw
The SDK handles all Solana-specific complexities (PDAs, token accounts, etc.) automatically.
Setup
Basic Initialization
Include Solana RPC endpoint when initializing the SDK:
import AugustSDK from '@augustdigital/sdk';
const sdk = new AugustSDK({
appName: '<APP_NAME>', // required
providers: {
-1: 'https://api.mainnet-beta.solana.com', // Solana Mainnet
},
});
// Access Solana adapter
const solana = sdk.solana;Custom RPC Endpoint
const sdk = new AugustSDK({
appName: '<APP_NAME>', // required
providers: {
-1: 'https://solana-mainnet.g.alchemy.com/v2/YOUR_KEY',
},
});For Write Operations
To execute transactions, you need to set a wallet provider:
import { useWallet } from '@solana/wallet-adapter-react';
// In your React component
const { publicKey, signTransaction } = useWallet();
// Set wallet for signing transactions
if (publicKey && signTransaction) {
sdk.solana.setWalletProvider(publicKey, signTransaction);
}Adapter API
Methods
setWalletProvider()
Set the wallet provider for write operations.
sdk.solana.setWalletProvider(
publicKey: PublicKey | string,
signTransaction: (tx: Transaction) => Promise<Transaction>
): voidParameters:
publicKey: User's Solana public keysignTransaction: Function to sign transactions (from wallet adapter)
Example:
import { useWallet } from '@solana/wallet-adapter-react';
function MyComponent() {
const { publicKey, signTransaction } = useWallet();
useEffect(() => {
if (publicKey && signTransaction) {
sdk.solana.setWalletProvider(publicKey, signTransaction);
}
}, [publicKey, signTransaction]);
}Get Vault Data
Query Solana vault information using the same sdk.getVault() method as EVM vaults.
sdk.getVault({
vault: string; // Solana program ID
chainId?: number; // -1 for mainnet
options?: {
solanaWallet?: string; // For user position data
};
}): Promise<IVault>Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
vault | string | Yes | Solana vault program ID |
options.solanaWallet | string | No | User's Solana public key for position data |
Example
// Get vault details
const vault = await sdk.getVault({
vault: 'VaultProgramId...',
chainId: -1, // Solana mainnet
});
console.log('Name:', vault.name);
console.log('Version:', vault.version); // "sol-0"
console.log('Total Assets:', vault.totalAssets.normalized);
console.log('APY:', vault.apy.apy);
console.log('Deposit Token:', vault.depositAssets[0].symbol);
// Get vault with user position
const vaultWithPosition = await sdk.getVault({
vault: 'VaultProgramId...',
chainId: -1,
options: {
solanaWallet: 'UserPublicKey...',
},
});
if (vaultWithPosition.position) {
console.log(
'Your balance:',
vaultWithPosition.position.walletBalance.normalized,
);
}Get All Solana Vaults
const solanaVaults = await sdk.getVaults({
chainIds: [-1], // Filter to Solana mainnet only
solanaWallet: 'UserPublicKey...', // Optional: include positions
});
solanaVaults.forEach((vault) => {
console.log(`${vault.name}: ${vault.totalAssets.normalized} TVL`);
});Get User Positions
const positions = await sdk.getVaultPositions({
solanaWallet: 'UserPublicKey...',
chainId: -1,
});
positions.forEach((position) => {
console.log(`Vault: ${position.vault}`);
console.log(`Balance: ${position.walletBalance.normalized}`);
});Vault Deposit
Deposit tokens into a Solana vault. The SDK automatically handles token accounts, PDAs, and Anchor program interactions.
sdk.solana.vaultDeposit({
vault: string;
amount: string | number | bigint;
wallet: string;
wait?: boolean;
}): Promise<string>Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
vault | string | Yes | Solana vault program ID |
amount | string | number | bigint | Yes | Amount to deposit |
wallet | string | Yes | User's Solana public key |
wait | boolean | No | Wait for confirmation (default: false) |
Returns
Transaction signature as string
Example
import { useWallet } from '@solana/wallet-adapter-react';
// In your React component
const { publicKey, signTransaction } = useWallet();
// Set wallet provider (once per session)
if (publicKey && signTransaction) {
sdk.solana.setWalletProvider(publicKey, signTransaction);
}
// Get vault info
const vault = await sdk.getVault({
vault: 'VaultProgramId...',
chainId: -1,
});
// Deposit
const signature = await sdk.solana.vaultDeposit({
vault: vault.address,
amount: '100', // 100 tokens
wallet: publicKey.toString(),
wait: true,
});
console.log('Deposit successful:', signature);Behavior
The SDK automatically:
- Fetches vault state and PDAs
- Gets or creates associated token accounts
- Handles token approvals if needed
- Converts amount to proper decimals
- Submits transaction via wallet adapter
- Optionally waits for confirmation
Vault Withdraw
Request withdrawal from a Solana vault.
sdk.solana.vaultRedeem({
vault: string;
amount: string | number | bigint;
wallet: string;
wait?: boolean;
}): Promise<string>Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
vault | string | Yes | Solana vault program ID |
amount | string | number | bigint | Yes | Amount of shares to redeem |
wallet | string | Yes | User's Solana public key |
wait | boolean | No | Wait for confirmation |
Returns
Transaction signature as string
Example
// Get user's vault balance
const position = await sdk.getVaultPositions({
solanaWallet: publicKey.toString(),
chainId: -1,
});
if (position[0].walletBalance.raw === '0') {
throw new Error('No balance to withdraw');
}
// Request redemption
const signature = await sdk.solana.vaultRedeem({
vault: 'VaultProgramId...',
amount: '50', // Redeem 50 shares
wallet: publicKey.toString(),
wait: true,
});
console.log('Redemption requested:', signature);Examples
Complete Deposit Flow
import AugustSDK from '@augustdigital/sdk';
import { useWallet } from '@solana/wallet-adapter-react';
import { PublicKey } from '@solana/web3.js';
function SolanaVaultDeposit() {
const { publicKey, signTransaction } = useWallet();
const [loading, setLoading] = useState(false);
const sdk = new AugustSDK({
appName: '<APP_NAME>', // required
providers: {
-1: 'https://api.mainnet-beta.solana.com',
},
});
const deposit = async (vaultId: string, amount: string) => {
if (!publicKey || !signTransaction) {
throw new Error('Wallet not connected');
}
setLoading(true);
try {
// 1. Set wallet provider
sdk.solana.setWalletProvider(publicKey, signTransaction);
// 2. Get vault details
const vault = await sdk.getVault({
vault: vaultId,
chainId: -1,
});
console.log(`Depositing to ${vault.name}`);
// 3. Execute deposit (SDK handles everything)
const signature = await sdk.solana.vaultDeposit({
vault: vaultId,
amount,
wallet: publicKey.toString(),
wait: true,
});
console.log('Deposit successful:', signature);
return signature;
} catch (error) {
console.error('Deposit failed:', error);
throw error;
} finally {
setLoading(false);
}
};
return (
<button
onClick={() => deposit('VaultProgramId...', '100')}
disabled={loading || !publicKey}
>
{loading ? 'Depositing...' : 'Deposit 100 Tokens'}
</button>
);
}Complete Withdrawal Flow
function SolanaVaultWithdraw() {
const { publicKey, signTransaction } = useWallet();
const sdk = new AugustSDK({
appName: '<APP_NAME>', // required
providers: {
-1: 'https://api.mainnet-beta.solana.com',
},
});
const withdraw = async (vaultId: string) => {
if (!publicKey || !signTransaction) {
throw new Error('Wallet not connected');
}
try {
// 1. Set wallet provider
sdk.solana.setWalletProvider(publicKey, signTransaction);
// 2. Check user's position
const position = await sdk.getVaultPositions({
solanaWallet: publicKey.toString(),
chainId: -1,
});
if (!position[0] || position[0].walletBalance.raw === '0') {
throw new Error('No balance to withdraw');
}
const balance = position[0].walletBalance.normalized;
console.log(`Withdrawing ${balance} shares`);
// 3. Execute redemption
const signature = await sdk.solana.vaultRedeem({
vault: vaultId,
amount: balance, // Withdraw all
wallet: publicKey.toString(),
wait: true,
});
console.log('Withdrawal successful:', signature);
return signature;
} catch (error) {
console.error('Withdrawal failed:', error);
throw error;
}
};
return (
<button onClick={() => withdraw('VaultProgramId...')}>
Withdraw All
</button>
);
}Query Vault Before Depositing
// 1. Get vault info
const vault = await sdk.getVault({
vault: 'VaultProgramId...',
chainId: -1,
});
// 2. Check if deposits are enabled
if (vault.isDepositPaused) {
throw new Error('Vault deposits are paused');
}
// 3. Show user the vault details
console.log(`Vault: ${vault.name}`);
console.log(`APY: ${vault.apy.apy}%`);
console.log(`TVL: ${vault.totalAssets.normalized}`);
console.log(`Deposit token: ${vault.depositAssets[0].symbol}`);
// 4. Deposit
await sdk.solana.vaultDeposit({
vault: vault.address,
amount: '100',
wallet: publicKey.toString(),
wait: true,
});Advanced Operations
For advanced use cases, the Solana adapter exposes low-level methods and utilities.
Direct Program Access
Access Solana connection and provider for custom operations:
// Get connection
const connection = sdk.solana.connection;
const balance = await connection.getBalance(publicKey);
// Get Anchor provider
const provider = sdk.solana.provider;
// Get program instance
import { vaultIdl } from '@augustdigital/sdk';
const program = sdk.solana.getProgram(vaultIdl);
// Query vault account directly
const vaultState = await program.account.vault.fetch(vaultPda);Utility Functions
import { Solana } from '@augustdigital/sdk';deriveShareMintPda()
Derive the share mint PDA for a vault.
const shareMintPda = Solana.utils.deriveShareMintPda('VaultProgramId...');
console.log('Share Mint PDA:', shareMintPda.toString());getToken()
Get token metadata from mint address.
const token = await Solana.utils.getToken({
mintAddress: 'MintPublicKey...',
endpoint: 'https://api.mainnet-beta.solana.com',
connection: sdk.solana.connection,
});
console.log('Symbol:', token.symbol);
console.log('Decimals:', token.decimals);
console.log('Supply:', token.supply);getVaultStateReadOnly()
Get vault state without a wallet provider.
const vaultState = await Solana.utils.getVaultStateReadOnly({
vaultProgramId: 'VaultProgramId...',
idl: vaultIdl,
endpoint: 'https://api.mainnet-beta.solana.com',
connection: sdk.solana.connection,
});getProvider()
Create an Anchor provider with wallet.
import { PublicKey } from '@solana/web3.js';
const provider = Solana.utils.getProvider({
network: 'mainnet-beta',
connection: sdk.solana.connection,
publicKey: new PublicKey('UserPublicKey...'),
signTransaction: signTransactionFunction,
});getReadOnlyProvider()
Create a read-only Anchor provider.
const provider = Solana.utils.getReadOnlyProvider({
network: 'mainnet-beta',
connection: sdk.solana.connection,
});getProgram()
Create an Anchor program instance.
const program = Solana.utils.getProgram({
network: 'mainnet-beta',
provider: anchorProvider,
idl: programIdl,
});Constants
The Solana adapter provides useful constants:
import { Solana } from '@augustdigital/sdk';Vault IDL
const vaultIdl = Solana.constants.vaultIdl;Program IDs
const programIds = Solana.constants.programIds;
console.log('Vault Program:', programIds.vaultProgram);Fallback Values
const fallbackDecimals = Solana.constants.fallbackDecimals; // 9
const fallbackNetwork = Solana.utils.fallbackNetwork; // 'mainnet-beta'Error Handling
Connection Errors
try {
const vaultState = await sdk.solana.getVaultState('VaultId...', vaultIdl);
} catch (error) {
if (error.message.includes('404')) {
console.error('Vault program not found');
} else if (error.message.includes('Network request failed')) {
console.error('RPC connection failed');
} else {
console.error('Unknown error:', error);
}
}Transaction Errors
try {
await handleSolanaDeposit({
connection: sdk.solana.connection,
provider: sdk.solana.provider,
vaultProgramId: 'VaultId...',
amount: 1000000000,
userTokenAccount: 'TokenAccount...',
idl: vaultIdl,
});
} catch (error) {
if (error.message.includes('User rejected')) {
console.error('Transaction cancelled by user');
} else if (error.message.includes('insufficient funds')) {
console.error('Not enough SOL for transaction');
} else {
console.error('Transaction failed:', error);
}
}