Vault Hooks
useVaults
Fetch all active vaults with metadata, APY, and TVL.
Source: ~/workspace/source/src/hooks/use-vault-data.ts:13
function useVaults(): {
vaults: LiveVault[];
loading: boolean;
error: string | null;
refresh: () => Promise<void>;
}
Example:
import { useVaults } from '@/hooks/use-vault-data';
function VaultList() {
const { vaults, loading, error, refresh } = useVaults();
if (loading) return <div>Loading...</div>;
if (error) return <div>Error: {error}</div>;
return (
<div>
{vaults.map(vault => (
<div key={vault.id}>
<h3>{vault.name}</h3>
<p>APY: {vault.apy.total.toFixed(2)}%</p>
<p>TVL: ${(vault.tvlUsd / 1e6).toFixed(2)}M</p>
</div>
))}
<button onClick={refresh}>Refresh</button>
</div>
);
}
Features:
- Auto-refreshes every 60 seconds
- Fetches from
/api/vaults
- Returns
LiveVault[] with APY breakdown, TVL, risk level, and strategy info
useVaultDetail
Get a single vault by ID.
function useVaultDetail(vaultId: string): {
vault: LiveVault | null;
loading: boolean;
error: string | null;
}
useVaultRead
Read on-chain vault state (total assets, supply, share balance).
Source: ~/workspace/source/src/hooks/use-vault-contract.ts:34
function useVaultRead(vaultAddress: string): {
getTotalAssets: () => Promise<bigint>;
getTotalSupply: () => Promise<bigint>;
getShareBalance: (account: string) => Promise<bigint>;
previewDeposit: (assets: bigint) => Promise<bigint>;
previewWithdraw: (assets: bigint) => Promise<bigint>;
}
Example:
const { getTotalAssets, previewDeposit } = useVaultRead(SABLE_CONTRACTS.SENTINEL);
const assets = await getTotalAssets(); // Total WBTC in vault
const shares = await previewDeposit(BigInt(100000000)); // Shares for 1 WBTC
useVaultWrite
Write operations: deposit, withdraw, redeem.
Source: ~/workspace/source/src/hooks/use-vault-contract.ts:81
function useVaultWrite(vaultAddress: string, assetAddress: string): {
deposit: (assets: bigint) => Promise<InvokeTransactionReceiptResponse>;
withdraw: (assets: bigint) => Promise<InvokeTransactionReceiptResponse>;
redeem: (shares: bigint) => Promise<InvokeTransactionReceiptResponse>;
}
Example:
const { deposit } = useVaultWrite(
SABLE_CONTRACTS.SENTINEL,
TOKENS.WBTC.address
);
// Deposit 0.5 WBTC
await deposit(BigInt(50000000));
Note: deposit() automatically approves WBTC spending and calls vault.deposit() in a multicall.
useStrategyInfo
Read leverage strategy details (collateral, debt, loops).
Source: ~/workspace/source/src/hooks/use-vault-contract.ts:151
function useStrategyInfo(vaultAddress: string | null): {
collateral: number;
debt: number;
loops: number;
paused: boolean;
} | null
Shielded Vault Hooks
useShieldedDeposit
Deposit WBTC to a shielded pool with privacy.
Source: ~/workspace/source/src/hooks/use-shielded-vault.ts:219
function useShieldedDeposit(poolAddress: string | null | undefined): {
deposit: (
denominationKey: string,
denomination: bigint
) => Promise<{ note: ShieldedNote | null; error: string | null }>;
pending: boolean;
status: string;
error: string | null;
}
Example:
import { useShieldedDeposit } from '@/hooks/use-shielded-vault';
import { SHIELDED_POOLS_V4 } from '@/lib/constants';
function PrivateDeposit() {
const pool = SHIELDED_POOLS_V4.sentinel_1x;
const { deposit, pending, status, error } = useShieldedDeposit(pool.pool);
const handleDeposit = async () => {
const { note, error } = await deposit('sentinel_1x', pool.denomination);
if (note) {
console.log('Note generated:', note.commitment);
console.log('Store this note to withdraw later!');
}
};
return (
<div>
<button onClick={handleDeposit} disabled={pending}>
{status || 'Deposit 0.0002 BTC Privately'}
</button>
{error && <p>Error: {error}</p>}
</div>
);
}
Process:
- Generate note (commitment, nullifier, secret)
- User approves WBTC spending (wallet signature)
- Relayer submits
pool.deposit(commitment, depositor)
- Note is saved to localStorage
- Returns
ShieldedNote for later withdrawal
useShieldedWithdraw
Withdraw WBTC privately using a zero-knowledge proof.
Source: ~/workspace/source/src/hooks/use-shielded-vault.ts:297
function useShieldedWithdraw(poolAddress: string | null | undefined): {
withdraw: (
note: ShieldedNote,
recipient: string,
depositEvents: Array<{ commitment: string; leafIndex: number }>
) => Promise<string | null>;
pending: boolean;
status: string;
error: string | null;
feeInfo: { feeSats: number; totalGasUsd: number } | null;
}
Example:
const { withdraw, pending, status, feeInfo } = useShieldedWithdraw(poolAddress);
const { events } = useDepositEvents(poolAddress);
const handleWithdraw = async (note: ShieldedNote) => {
const recipientAddr = '0x...';
const txHash = await withdraw(note, recipientAddr, events);
if (txHash) {
console.log('Withdrawal tx:', txHash);
console.log('Note has been spent and marked as used');
}
};
Process:
- Estimate relayer fee (~$0.01-0.05 in BTC)
- Build Merkle proof from deposit events
- Generate Groth16 ZK proof (10-30 seconds)
- Serialize proof to calldata
- Submit via relayer API
- Mark note as spent
Public Inputs: [root, nullifierHash, recipient, relayer, fee, batchStart, batchSize]
useShieldedBalance
Get unspent notes and total private balance.
Source: ~/workspace/source/src/hooks/use-shielded-vault.ts:392
function useShieldedBalance(
poolAddress: string | null | undefined,
denominationKey?: string
): {
notes: ShieldedNote[];
noteCount: number;
totalWbtc: bigint;
}
useSyncNotes
Sync note leaf indices and batch info from on-chain events.
Source: ~/workspace/source/src/hooks/use-shielded-vault.ts:414
function useSyncNotes(
poolAddress: string | null | undefined,
fromBlock?: number
): {
syncVersion: number;
}
Usage:
const { syncVersion } = useSyncNotes(poolAddress);
// syncVersion increments when notes are updated
// Use it as a dependency to trigger re-renders
useEffect(() => {
const notes = loadNotes();
console.log('Notes synced:', notes);
}, [syncVersion]);
DCA Hooks
useDcaOrders
Manage DCA orders: create, cancel, and fetch user orders.
Source: ~/workspace/source/src/hooks/use-dca.ts:250
function useDcaOrders(): {
orders: DcaOrder[];
activeOrders: DcaOrder[];
loading: boolean;
createOrder: (params: {
sellToken: string;
sellAmountHuman: string;
frequency: DcaFrequency;
totalOrders: number;
smart: boolean;
}) => Promise<void>;
cancelOrder: (orderId: number) => Promise<void>;
refreshOrders: () => Promise<void>;
txStep: DcaStep;
txHash: string | null;
txError: string | null;
resetTx: () => void;
}
Example:
import { useDcaOrders, TOKENS } from '@/hooks/use-dca';
function DcaManager() {
const { orders, createOrder, cancelOrder, txStep, txHash } = useDcaOrders();
const handleCreate = async () => {
await createOrder({
sellToken: TOKENS.USDC.address,
sellAmountHuman: '100', // 100 USDC per order
frequency: 'weekly',
totalOrders: 10,
smart: true, // Enable Smart DCA (Mayer Multiple)
});
};
return (
<div>
<button onClick={handleCreate}>Create Weekly DCA</button>
{txStep === 'pending' && <p>Transaction pending: {txHash}</p>}
<h3>Active Orders</h3>
{orders.map(order => (
<div key={order.id}>
<p>Order #{order.id}: {order.executedOrders}/{order.totalOrders} executed</p>
<p>Next: {new Date(order.nextExecution * 1000).toLocaleString()}</p>
<button onClick={() => cancelOrder(order.id)}>Cancel</button>
</div>
))}
</div>
);
}
DCA Types:
type DcaFrequency = 'daily' | 'weekly' | 'biweekly' | 'monthly';
interface DcaOrder {
id: number;
owner: string;
sellToken: string;
sellAmountPer: bigint;
frequency: number; // seconds
totalOrders: number;
executedOrders: number;
nextExecution: number; // unix timestamp
active: boolean;
smart: boolean; // Mayer Multiple enabled
deposited: bigint;
spent: bigint;
btcReceived: bigint;
}
useMayerMultiple
Read current Mayer Multiple indicator for Smart DCA.
Source: ~/workspace/source/src/hooks/use-dca.ts:181
function useMayerMultiple(): {
data: MayerMultipleData | null;
loading: boolean;
}
interface MayerMultipleData {
spot: number; // Current BTC price
twap200d: number; // 200-day TWAP
mayerMultiple: number; // spot / twap200d
band: string; // "Very Cheap" | "Below Average" | "Normal" | "Expensive" | "Overheated"
multiplier: number; // 0.5, 0.75, 1.0, 1.25, or 1.5
}
Example:
const { data, loading } = useMayerMultiple();
if (!loading && data) {
console.log(`BTC is ${data.band} (${data.mayerMultiple.toFixed(2)}x MA)`);
console.log(`Smart DCA will buy ${data.multiplier}x the normal amount`);
}
CDP Hooks
useCdpPosition
Read user’s CDP collateral, debt, and health factor.
Source: ~/workspace/source/src/hooks/use-cdp.ts:14
function useCdpPosition(): {
position: {
collateral: bigint; // WBTC sats
debt: bigint; // USDC cents
healthBps: bigint; // Health factor in basis points
maxBorrow: bigint; // Max additional USDC borrowable
} | null;
loading: boolean;
}
Example:
const { position, loading } = useCdpPosition();
if (!loading && position) {
const collateralBtc = Number(position.collateral) / 1e8;
const debtUsdc = Number(position.debt) / 1e6;
const healthFactor = Number(position.healthBps) / 10000;
console.log(`Collateral: ${collateralBtc} BTC`);
console.log(`Debt: ${debtUsdc} USDC`);
console.log(`Health: ${healthFactor.toFixed(2)}x`);
}
useCdpActions
Deposit collateral, borrow USDC, repay, and withdraw.
Source: ~/workspace/source/src/hooks/use-cdp.ts:115
function useCdpActions(): {
depositAndBorrow: (
wbtcAmount: bigint,
usdcBorrowAmount: bigint
) => Promise<string | null>;
repayAndWithdraw: (
usdcRepayAmount: bigint,
wbtcWithdrawAmount: bigint,
fullRepay?: boolean
) => Promise<string | null>;
closePosition: (usdcApproveAmount: bigint) => Promise<string | null>;
pending: boolean;
status: string;
error: string | null;
}
Example:
const { depositAndBorrow, repayAndWithdraw, pending, status } = useCdpActions();
// Deposit 0.1 BTC and borrow 5000 USDC
await depositAndBorrow(
BigInt(10000000), // 0.1 BTC = 10M sats
BigInt(5000000000) // 5000 USDC = 5B cents
);
// Repay 2500 USDC and withdraw 0.05 BTC
await repayAndWithdraw(
BigInt(2500000000),
BigInt(5000000)
);
// Close position entirely (repay all debt, withdraw all collateral)
await closePosition(BigInt(5500000000)); // Approve slightly more for interest
Staking Hooks
useStakingPools
Fetch Vesu lending pool data with APYs.
Source: ~/workspace/source/src/hooks/use-staking.ts:81
function useStakingPools(): {
pools: StakingPoolData[];
loading: boolean;
error: string | null;
refresh: () => Promise<void>;
}
interface StakingPoolData {
config: StakingPoolConfig;
supplyApy: number;
btcFiApr: number;
totalApy: number;
utilization: number;
tvlUsd: number;
totalSuppliedBtc: number;
btcPrice: number;
borrowApr: number;
}
useVesuDeposit / useVesuWithdraw
Deposit to or withdraw from Vesu pools.
Source: ~/workspace/source/src/hooks/use-staking.ts:188
function useVesuDeposit(poolId: string): {
deposit: (amount: bigint) => Promise<InvokeTransactionReceiptResponse>;
}
function useVesuWithdraw(poolId: string): {
withdraw: (amount: bigint) => Promise<InvokeTransactionReceiptResponse>;
}
Example:
import { useVesuDeposit, VESU_POOLS } from '@/hooks/use-staking';
function VesuStaking() {
const { deposit } = useVesuDeposit(VESU_POOLS.PRIME.id);
const handleDeposit = async () => {
await deposit(BigInt(50000000)); // Deposit 0.5 BTC
console.log('Received vWBTC shares');
};
return <button onClick={handleDeposit}>Stake to Vesu PRIME</button>;
}
Bridge Hooks
useBridge
Manage cross-chain bridge operations (1Click protocol).
Source: ~/workspace/source/src/hooks/use-bridge.ts:90
function useBridge(): {
state: BridgeState;
tokens: OneClickToken[];
chains: ChainInfo[];
sourceTokens: OneClickToken[];
destTokens: OneClickToken[];
setDirection: (dir: 'in' | 'out') => void;
setSourceChain: (chain: string) => void;
setSourceToken: (token: OneClickToken) => void;
setAmount: (amount: string) => void;
setDestAddress: (addr: string) => void;
setRefundAddress: (addr: string) => void;
startBridgeIn: () => Promise<void>;
startBridgeOut: () => Promise<void>;
reset: () => void;
}
Example:
import { useBridge } from '@/hooks/use-bridge';
function Bridge() {
const {
state,
chains,
sourceTokens,
setDirection,
setSourceChain,
setSourceToken,
setAmount,
setDestAddress,
startBridgeIn,
} = useBridge();
const handleBridge = async () => {
setDirection('in'); // Bridge to Starknet
setSourceChain('Ethereum');
setSourceToken(sourceTokens.find(t => t.symbol === 'USDC'));
setAmount('100');
setDestAddress('0x...');
await startBridgeIn();
console.log('Deposit address:', state.depositAddress);
};
return (
<div>
<button onClick={handleBridge}>Bridge 100 USDC to Starknet</button>
{state.step === 'awaiting-deposit' && (
<p>Send funds to: {state.depositAddress}</p>
)}
{state.step === 'complete' && <p>Bridge complete!</p>}
</div>
);
}
Bridge Steps:
idle: Form input
quoting: Fetching quote
quoted: Quote ready
awaiting-deposit: Waiting for user to send funds (bridge IN)
awaiting-transfer: User signing wallet (bridge OUT)
awaiting-1click: 1Click processing
complete: Bridge finished
Private Swap Hooks
usePrivateSwap
Execute private token swaps from WBTC pools to other tokens via AVNU.
Source: ~/workspace/source/src/hooks/use-private-swap.ts
function usePrivateSwap(): {
executePrivateSwap: (params: {
sourceNote: ShieldedNote;
sourcePoolId: string;
outputToken: string;
recipient: string;
slippage?: number;
}) => Promise<{ txHash: string; leafIndex: number; outputAmount: string }>;
loading: boolean;
error: string | null;
}
Example:
import { usePrivateSwap } from '@/hooks/use-private-swap';
import { getUnspentNotesByVaultId } from '@/lib/privacy/note';
function PrivateSwap() {
const { executePrivateSwap, loading, error } = usePrivateSwap();
const handleSwap = async () => {
const notes = getUnspentNotesByVaultId('swap_1x');
if (notes.length === 0) {
alert('No unspent notes in swap pool');
return;
}
const result = await executePrivateSwap({
sourceNote: notes[0],
sourcePoolId: 'swap_1x',
outputToken: '0x049d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7', // ETH
recipient: '0x...',
slippage: 0.02, // 2%
});
console.log('Swap TX:', result.txHash);
console.log('Received:', result.outputAmount);
};
return (
<div>
<button onClick={handleSwap} disabled={loading}>
{loading ? 'Swapping...' : 'Private Swap WBTC → ETH'}
</button>
{error && <p style={{ color: 'red' }}>{error}</p>}
</div>
);
}
Private swaps generate a Groth16 proof client-side, then submit to /api/relayer/private-swap which verifies the proof, withdraws WBTC from the source pool, swaps via AVNU, and deposits the output token to the recipient.
useSwapPoolEvents
Fetch all swap deposit events from the shielded swap pool.
Source: ~/workspace/source/src/hooks/use-private-swap.ts:25
function useSwapPoolEvents(): {
events: Array<{
commitment: string;
leafIndex: number;
outputToken: string;
outputAmount: string;
}>;
loading: boolean;
}
Example:
import { useSwapPoolEvents } from '@/hooks/use-private-swap';
function SwapHistory() {
const { events, loading } = useSwapPoolEvents();
if (loading) return <p>Loading swap history...</p>;
return (
<ul>
{events.map((evt, i) => (
<li key={i}>
Leaf {evt.leafIndex}: {evt.outputAmount} of token {evt.outputToken}
</li>
))}
</ul>
);
}