@yo-protocol/core
v1.0.9
Published
TypeScript SDK for interacting with the yield protocol
Readme
@yo-protocol/core
TypeScript SDK for interacting with the Yo Protocol — an ERC-4626 yield vault protocol on Base, Ethereum, and Arbitrum.
Installation
npm install @yo-protocol/core viemQuick Start
import { createYoClient, VAULTS, parseTokenAmount } from "@yo-protocol/core";
const yo = createYoClient({ chainId: 8453 });
// Read vault state
const state = await yo.getVaultState(VAULTS.yoUSD.address);
console.log(state.totalAssets, state.exchangeRate);
// Prepare a deposit (handles allowance check)
const txs = await yo.prepareDepositWithApproval({
vault: VAULTS.yoUSD.address,
token: VAULTS.yoUSD.underlying.address[8453],
owner: userAddress,
recipient: userAddress,
amount: parseTokenAmount("100", 6),
});
// Send each transaction via your wallet
for (const tx of txs) {
const hash = await walletClient.sendTransaction({
to: tx.to,
data: tx.data,
value: tx.value,
});
await yo.waitForTransaction(hash);
}Supported Chains
| Chain | ID | | -------- | ----- | | Ethereum | 1 | | Base | 8453 | | Arbitrum | 42161 |
Vaults
| Vault | Underlying | Decimals | Chains | | ------ | ---------- | -------- | ------------------------ | | yoUSD | USDC | 6 | Ethereum, Base, Arbitrum | | yoETH | WETH | 18 | Ethereum, Base | | yoBTC | cbBTC | 8 | Ethereum, Base | | yoEUR | EURC | 6 | Ethereum, Base | | yoGOLD | XAUt | 6 | Ethereum | | yoUSDT | USDT | 6 | Ethereum |
API
Client
Create a client with createYoClient(config):
// Read-only (default public clients created automatically)
const yo = createYoClient({ chainId: 8453 });
// With custom RPC
import { createPublicClient, http } from "viem";
import { base } from "viem/chains";
const yo = createYoClient({
chainId: 8453,
publicClients: {
8453: createPublicClient({ chain: base, transport: http("https://...") }),
},
partnerId: 9999, // optional, defaults to 9999
});YoClientConfig:
interface YoClientConfig {
chainId: SupportedChainId;
publicClients?: Partial<Record<SupportedChainId, PublicClient>>;
partnerId?: number;
}Vault Reads
// Full vault state (name, symbol, decimals, totalAssets, totalSupply, exchangeRate, etc.)
const state = await yo.getVaultState(vaultAddress);
// Conversion previews
const shares = await yo.previewDeposit(vaultAddress, assets);
const assets = await yo.previewRedeem(vaultAddress, shares);
const assets = await yo.convertToAssets(vaultAddress, shares);
const shares = await yo.convertToShares(vaultAddress, assets);
// Vault status
const paused = await yo.isPaused(vaultAddress);
const idle = await yo.getIdleBalance(vaultAddress);User Reads
// Token balance
const { balance, decimals } = await yo.getTokenBalance(tokenAddress, account);
// Vault share balance
const shares = await yo.getShareBalance(vaultAddress, account);
// Full position (shares + equivalent assets)
const { shares, assets } = await yo.getUserPosition(vaultAddress, account);
// Allowance checks
const { allowance } = await yo.getAllowance(token, owner, spender);
const ok = await yo.hasEnoughAllowance(token, owner, spender, amount);
// Multi-chain positions via multicall
const positions = await yo.getUserPositionsAllChains(account);Prepared Transactions
Core only prepares transactions — it returns PreparedTransaction { to, data, value } objects. The caller sends them via any wallet (wagmi, viem, ethers, Safe SDK, etc.).
// Approve tokens (synchronous, no RPC call)
const tx = yo.prepareApprove({ token, amount });
// tx = { to, data, value }
// Deposit via gateway (queries on-chain for minShares)
const tx = await yo.prepareDeposit({
vault: vaultAddress,
amount: 1_000_000n,
recipient: userAddress,
});
// Redeem via gateway
const tx = await yo.prepareRedeem({
vault: vaultAddress,
shares: 500_000n,
recipient: userAddress,
});With Auto-Approval
The recommended approach — checks allowance on-chain and returns 1-2 transactions:
// Returns [approveTx, depositTx] if approval needed, or [depositTx] if already approved
const txs = await yo.prepareDepositWithApproval({
vault: vaultAddress,
token: usdcAddress,
owner: userAddress,
recipient: userAddress,
amount: 1_000_000n,
slippageBps: 50, // optional, default 50 (0.5%)
});
// Returns [approveTx, redeemTx] if share approval needed, or [redeemTx]
const txs = await yo.prepareRedeemWithApproval({
vault: vaultAddress,
shares: 500_000n,
owner: userAddress,
recipient: userAddress,
});
// Send sequentially, waiting for each to confirm
for (const tx of txs) {
const hash = await walletClient.sendTransaction({
to: tx.to,
data: tx.data,
value: tx.value,
});
await yo.waitForTransaction(hash);
}Redeem Receipts
const receipt = await yo.waitForRedeemReceipt(redeemHash);
// receipt.instant — true if assets were returned immediately
// receipt.assetsOrRequestId — assets amount or queued request IDGateway Quote Helpers
On-chain reads against the Gateway contract (may differ from direct vault reads due to fees):
const shares = await yo.quotePreviewDeposit(vaultAddress, assets);
const assets = await yo.quotePreviewRedeem(vaultAddress, shares);
const assets = await yo.quotePreviewWithdraw(vaultAddress, assets);
const assets = await yo.quoteConvertToAssets(vaultAddress, shares);
const shares = await yo.quoteConvertToShares(vaultAddress, assets);Vault Discovery
import { getVaultsForChain, VAULTS } from "@yo-protocol/core";
const vaults = getVaultsForChain(8453); // all Base vaults
const vaults = yo.getVaults(); // vaults for client's chain
// Get underlying token address for a specific chain
const usdcOnBase = VAULTS.yoUSD.underlying.address[8453];API Data
Historical data, snapshots, and analytics from the Yo API (https://api.yo.xyz):
// Vault data
const snapshot = await yo.getVaultSnapshot(vaultAddress);
const snapshots = await yo.getVaultSnapshots();
const stats = await yo.getVaultStats();
const yieldHistory = await yo.getVaultYieldHistory(vaultAddress);
const tvlHistory = await yo.getVaultTvlHistory(vaultAddress);
const totalTvl = await yo.getTotalTvlTimeseries();
const sharePrices = await yo.getSharePriceHistory(vaultAddress);
const allocations = await yo.getVaultAllocationsTimeSeries(vaultAddress);
const percentile = await yo.getVaultPercentile(vaultAddress);
const performance = await yo.getVaultPerformance(vaultAddress);
const benchmark = await yo.getPerformanceBenchmark(vaultAddress);
const pendingRedeems = await yo.getVaultPendingRedeems(vaultAddress);
// Transaction history
const history = await yo.getVaultHistory(vaultAddress, 50);
const allNetworks = await yo.getVaultHistoryAllNetworks(vaultAddress);
const globalHistory = await yo.getGlobalVaultHistory({ limit: 100 });
// User data
const history = await yo.getUserHistory(vaultAddress, userAddress, 10);
const userPerf = await yo.getUserPerformance(vaultAddress, userAddress);
const snapshots = await yo.getUserSnapshots(vaultAddress, userAddress);
const balances = await yo.getUserBalances(userAddress);
const pending = await yo.getPendingRedemptions(vaultAddress, userAddress);
const rewards = await yo.getUserRewardsByAsset(userAddress, tokenAddress);
// Leaderboard
const weekly = await yo.getWeeklyRewards(tokenAddress);
const allTime = await yo.getAllTimeRewards(tokenAddress);Prices
const prices = await yo.getPrices();
// { "0x...": 3500.12, ... }Merkl Rewards
Query and claim Merkl reward campaigns:
// List active campaigns
const campaigns = await yo.getMerklCampaigns({ status: "LIVE" });
// Check claimable rewards (merges API + on-chain data)
const rewards = await yo.getClaimableRewards(userAddress);
if (rewards && yo.hasMerklClaimableRewards(rewards)) {
const total = yo.getMerklTotalClaimable(rewards);
// Prepare claim transaction
const tx = yo.prepareClaimMerklRewards(userAddress, rewards);
// Send via wallet
const hash = await walletClient.sendTransaction({
to: tx.to,
data: tx.data,
value: tx.value,
});
}Standalone Functions
Every client method is also available as a standalone function for tree-shaking:
import { getVaultState, prepareDeposit, prepareApprove } from "@yo-protocol/core";
const state = await getVaultState(publicClient, vaultAddress);Utilities
import {
formatTokenAmount,
parseTokenAmount,
formatUsd,
formatPercent,
formatCompactNumber,
applySlippage,
} from "@yo-protocol/core";
formatTokenAmount(1000000n, 6); // "1.0"
parseTokenAmount("1.5", 18); // 1500000000000000000n
formatUsd(1234.56); // "$1,234.56"
formatPercent(0.0523); // "5.23%"
formatCompactNumber(1_500_000); // "1.5M"
applySlippage(1000000n, 50); // 995000n (0.5% slippage)Constants
| Export | Description |
| --------------------- | ------------------------------------ |
| YO_GATEWAY_ADDRESS | Gateway contract address |
| REDEEMER_ADDRESS | Redeemer contract address |
| VAULTS | All vault configurations |
| SUPPORTED_CHAINS | Map of chain ID to viem chain config |
| SUPPORTED_CHAIN_IDS | Array of supported chain IDs |
| CHAIN_ID_TO_NETWORK | Map chain IDs to network names |
| erc20Abi | Standard ERC-20 ABI |
| erc4626Abi | ERC-4626 vault ABI |
| yoGatewayAbi | Yo gateway contract ABI |
License
MIT
