0x0x230x

Untitled

Feb 22nd, 2026
56
0
Never
8
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 26.50 KB | None | 0 0
  1. # Yo Protocol SDK — Complete Reference
  2.  
  3. ERC-4626 yield vault protocol on Ethereum, Base, and Arbitrum. All deposits/redeems route through a single Gateway contract. The SDK (`@yo-protocol/core`) wraps on-chain reads, write actions, prepared transactions, REST API queries, and Merkl reward claims.
  4.  
  5. ## Table of Contents
  6.  
  7. 1. [Installation & Initialization](#installation--initialization)
  8. 2. [Contract Addresses](#contract-addresses)
  9. 3. [Supported Chains](#supported-chains)
  10. 4. [Vault Registry](#vault-registry)
  11. 5. [API Reference — Vault Reads](#vault-reads-on-chain)
  12. 6. [API Reference — User Reads](#user-reads-on-chain)
  13. 7. [API Reference — Write Actions](#write-actions-require-wallet)
  14. 8. [API Reference — Prepared Transactions](#prepared-transactions-calldata-mode)
  15. 9. [API Reference — Gateway Quotes](#gateway-quote-helpers)
  16. 10. [API Reference — REST API](#rest-api-methods)
  17. 11. [API Reference — Merkl Rewards](#merkl-reward-methods)
  18. 12. [API Reference — Transaction Helpers](#transaction-helpers)
  19. 13. [TypeScript Interfaces](#typescript-interfaces)
  20. 14. [Utilities](#utilities)
  21. 15. [Workflow Examples](#workflow-examples)
  22. 16. [CLI Reference](#cli-yo-protocolcli)
  23. 17. [Important Gotchas](#important-gotchas)
  24.  
  25. ---
  26.  
  27. ## Installation & Initialization
  28.  
  29. ```bash
  30. npm install @yo-protocol/core viem
  31. ```
  32.  
  33. ```ts
  34. import { createYoClient } from '@yo-protocol/core'
  35.  
  36. // Read-only (no wallet needed)
  37. const client = createYoClient({ chainId: 1 })
  38.  
  39. // With wallet
  40. const client = createYoClient({ chainId: 8453, walletClient })
  41.  
  42. // Custom RPC
  43. import { createPublicClient, http } from 'viem'
  44. import { mainnet } from 'viem/chains'
  45. const publicClient = createPublicClient({ chain: mainnet, transport: http('https://...') })
  46. const client = createYoClient({ chainId: 1, publicClient })
  47. ```
  48.  
  49. `YoClientConfig`: `{ chainId: SupportedChainId, publicClient?: PublicClient, walletClient?: WalletClient, partnerId?: number }`
  50.  
  51. ---
  52.  
  53. ## Contract Addresses
  54.  
  55. | Contract | Address |
  56. |----------|---------|
  57. | **Gateway** | `0xF1EeE0957267b1A474323Ff9CfF7719E964969FA` |
  58. | **Vault Registry** | `0x56c3119DC3B1a75763C87D5B0A2C55E489502232` |
  59. | **Oracle** | `0x6E879d0CcC85085A709eBf5539224f53d0D396B0` |
  60. | **Redeemer** | `0x0439e941841f97dc1334d1a433379c6fcdcc2162` |
  61. | **Merkl Distributor** (Base) | `0x3Ef3D8bA38EBe18DB133cEc108f4D14CE00Dd9Ae` |
  62. | **Merkl Creator** | `0x8C9200d94Cf7A1B201068c4deDa6239F15FED480` |
  63. | **YO Token** (Base) | `0x3C1a1c9C2D073E5bC4e7AF97f0d7caC7a82E2262` |
  64.  
  65. Merkl API base: `https://api.merkl.xyz/v4`
  66. REST API base: `https://api.yo.xyz`
  67.  
  68. ---
  69.  
  70. ## Supported Chains
  71.  
  72. | Chain | ID | Network Name |
  73. |-------|-----|-------------|
  74. | Ethereum | `1` | `ethereum` |
  75. | Base | `8453` | `base` |
  76. | Arbitrum | `42161` | `arbitrum` |
  77.  
  78. Type: `SupportedChainId = 1 | 8453 | 42161`
  79.  
  80. ---
  81.  
  82. ## Vault Registry
  83.  
  84. ### yoETH
  85. - **Address**: `0x3a43aec53490cb9fa922847385d82fe25d0e9de7`
  86. - **Underlying**: WETH (18 decimals)
  87. - **Chains**: Ethereum, Base
  88. - **Token addresses**:
  89. - Ethereum (1): `0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2`
  90. - Base (8453): `0x4200000000000000000000000000000000000006`
  91.  
  92. ### yoBTC
  93. - **Address**: `0xbcbc8cb4d1e8ed048a6276a5e94a3e952660bcbc`
  94. - **Underlying**: cbBTC (8 decimals)
  95. - **Chains**: Ethereum, Base
  96. - **Token addresses**:
  97. - Ethereum (1): `0xcbb7c0000ab88b473b1f5afd9ef808440eed33bf`
  98. - Base (8453): `0xcbb7c0000ab88b473b1f5afd9ef808440eed33bf`
  99.  
  100. ### yoUSD
  101. - **Address**: `0x0000000f2eb9f69274678c76222b35eec7588a65`
  102. - **Underlying**: USDC (6 decimals)
  103. - **Chains**: Ethereum, Base, Arbitrum
  104. - **Token addresses**:
  105. - Ethereum (1): `0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48`
  106. - Base (8453): `0x833589fcd6edb6e08f4c7c32d4f71b54bda02913`
  107. - Arbitrum (42161): `0xaf88d065e77c8cC2239327C5EDb3A432268e5831`
  108.  
  109. ### yoEUR
  110. - **Address**: `0x50c749ae210d3977adc824ae11f3c7fd10c871e9`
  111. - **Underlying**: EURC (6 decimals)
  112. - **Chains**: Ethereum, Base
  113. - **Token addresses**:
  114. - Ethereum (1): `0x1aBaEA1f7C830bD89Acc67eC4af516284b1bC33c`
  115. - Base (8453): `0x60a3E35Cc302bFA44Cb288Bc5a4F316Fdb1adb42`
  116.  
  117. ### yoGOLD
  118. - **Address**: `0x586675A3a46B008d8408933cf42d8ff6c9CC61a1`
  119. - **Underlying**: XAUt (6 decimals)
  120. - **Chains**: Ethereum only
  121. - **Token addresses**:
  122. - Ethereum (1): `0x68749665FF8D2d112Fa859AA293F07A622782F38`
  123.  
  124. ### yoUSDT
  125. - **Address**: `0xb9a7da9e90d3b428083bae04b860faa6325b721e`
  126. - **Underlying**: USDT (6 decimals)
  127. - **Chains**: Ethereum only
  128. - **Token addresses**:
  129. - Ethereum (1): `0xdac17f958d2ee523a2206206994597c13d831ec7`
  130.  
  131. ### Programmatic Access
  132.  
  133. ```ts
  134. import { VAULTS, getVaultsForChain, getVaultByAddress, YO_GATEWAY_ADDRESS } from '@yo-protocol/core'
  135.  
  136. // Get all vaults for a chain
  137. const baseVaults = getVaultsForChain(8453)
  138.  
  139. // Look up by address
  140. const vault = getVaultByAddress('0x0000000f2eb9f69274678c76222b35eec7588a65')
  141.  
  142. // Get underlying token address for a specific chain
  143. const usdcOnBase = VAULTS.yoUSD.underlying.address[8453]
  144. ```
  145.  
  146. ---
  147.  
  148. ## Vault Reads (on-chain)
  149.  
  150. ### `getVaults(): VaultConfig[]`
  151. Return known vault configs for the client's chain. No RPC call.
  152.  
  153. ### `getVaultState(vault: Address): Promise<VaultState>`
  154. Full on-chain vault state: name, symbol, decimals, totalAssets, totalSupply, asset address, exchangeRate.
  155.  
  156. ### `previewDeposit(vault: Address, assets: bigint): Promise<bigint>`
  157. ERC-4626 `previewDeposit` — how many shares for a given asset amount.
  158.  
  159. ### `previewRedeem(vault: Address, shares: bigint): Promise<bigint>`
  160. ERC-4626 `previewRedeem` — how many assets for a given share amount.
  161.  
  162. ### `convertToAssets(vault: Address, shares: bigint): Promise<bigint>`
  163. ERC-4626 `convertToAssets` — share-to-asset conversion without fees.
  164.  
  165. ### `convertToShares(vault: Address, assets: bigint): Promise<bigint>`
  166. ERC-4626 `convertToShares` — asset-to-share conversion without fees.
  167.  
  168. ### `isPaused(vault: Address): Promise<boolean>`
  169. Check if vault deposits are paused.
  170.  
  171. ### `getIdleBalance(vault: Address): Promise<bigint>`
  172. Get vault's idle (uninvested) balance.
  173.  
  174. ---
  175.  
  176. ## User Reads (on-chain)
  177.  
  178. ### `getTokenBalance(token: Address, account: Address): Promise<TokenBalance>`
  179. ERC-20 balance. Returns `{ token, balance, decimals }`.
  180.  
  181. ### `getShareBalance(vault: Address, account: Address): Promise<bigint>`
  182. User's vault share balance (raw bigint).
  183.  
  184. ### `getUserPosition(vault: Address, account: Address): Promise<UserVaultPosition>`
  185. User's position as `{ shares, assets }` — shares held and their asset value.
  186.  
  187. ### `getAllowance(token: Address, owner: Address, spender: Address): Promise<TokenAllowance>`
  188. ERC-20 allowance. Returns `{ token, owner, spender, allowance }`.
  189.  
  190. ### `hasEnoughAllowance(token: Address, owner: Address, spender: Address, amount: bigint): Promise<boolean>`
  191. Check if allowance >= amount.
  192.  
  193. ---
  194.  
  195. ## Write Actions (require wallet)
  196.  
  197. All write methods require `walletClient` set via constructor or `setWalletClient()`.
  198.  
  199. ### `approve(token: Address, amount: bigint, spender?: Address): Promise<ApproveResult>`
  200. ERC-20 approve. Spender defaults to Gateway. Returns `{ hash }`.
  201.  
  202. ### `approveMax(token: Address, spender?: Address): Promise<ApproveResult>`
  203. Approve max uint256. Spender defaults to Gateway. Returns `{ hash }`.
  204.  
  205. ### `deposit(params): Promise<DepositResult>`
  206. Deposit assets via Gateway. Returns `{ hash, shares }`.
  207.  
  208. ```ts
  209. params: {
  210. vault: Address
  211. amount: bigint // asset amount to deposit
  212. recipient?: Address // defaults to wallet account
  213. slippageBps?: number // default 50 (0.5%)
  214. partnerId?: number // default from client config
  215. }
  216. ```
  217.  
  218. ### `depositWithApproval(params): Promise<DepositWithApprovalResult>`
  219. Approve (if needed) + deposit in one call. Returns `{ approveHash?, depositHash, shares }`.
  220.  
  221. ```ts
  222. params: {
  223. vault: Address
  224. token: Address // token to approve
  225. amount: bigint
  226. recipient?: Address
  227. slippageBps?: number
  228. partnerId?: number
  229. }
  230. ```
  231.  
  232. ### `redeem(params): Promise<RedeemResult>`
  233. Redeem shares via Gateway. Returns `{ hash, assets }`.
  234.  
  235. ```ts
  236. params: {
  237. vault: Address
  238. shares: bigint // shares to redeem
  239. recipient?: Address // defaults to wallet account
  240. slippageBps?: number // default 50
  241. minAssetsOut?: bigint // override slippage calc
  242. partnerId?: number
  243. }
  244. ```
  245.  
  246. ---
  247.  
  248. ## Prepared Transactions (calldata mode)
  249.  
  250. For Safe multisig, Account Abstraction, or batched transactions. Returns `PreparedTransaction { to, data, value }`.
  251.  
  252. ### `prepareApprove(params: { token, amount, spender? }): PreparedTransaction`
  253. Synchronous. No RPC call.
  254.  
  255. ### `prepareDeposit(params): Promise<PreparedTransaction>`
  256. **Requires `recipient`** (unlike `deposit()`). Queries gateway for minShares.
  257.  
  258. ### `prepareRedeem(params): Promise<PreparedTransaction>`
  259. **Requires `recipient`**. Queries gateway for minAssetsOut.
  260.  
  261. ### `prepareDepositWithApproval(params): Promise<PreparedTransaction[]>`
  262. Returns array: `[approveTx?, depositTx]`. Checks on-chain allowance.
  263.  
  264. ```ts
  265. params: {
  266. vault: Address
  267. token: Address
  268. owner: Address // token owner for allowance check
  269. amount: bigint
  270. recipient?: Address
  271. slippageBps?: number
  272. partnerId?: number
  273. }
  274. ```
  275.  
  276. ---
  277.  
  278. ## Gateway Quote Helpers
  279.  
  280. On-chain reads against the Gateway contract (may differ from direct vault reads due to fees).
  281.  
  282. ### `quotePreviewDeposit(vault: Address, assets: bigint): Promise<bigint>`
  283. ### `quotePreviewRedeem(vault: Address, shares: bigint): Promise<bigint>`
  284. ### `quotePreviewWithdraw(vault: Address, assets: bigint): Promise<bigint>`
  285. ### `quoteConvertToAssets(vault: Address, shares: bigint): Promise<bigint>`
  286. ### `quoteConvertToShares(vault: Address, assets: bigint): Promise<bigint>`
  287.  
  288. ---
  289.  
  290. ## Gateway Allowance Helpers
  291.  
  292. ### `getShareAllowance(vault: Address, owner: Address): Promise<bigint>`
  293. Share allowance granted to the Gateway.
  294.  
  295. ### `getAssetAllowance(vault: Address, owner: Address): Promise<bigint>`
  296. Asset allowance granted to the Gateway.
  297.  
  298. ---
  299.  
  300. ## REST API Methods
  301.  
  302. Off-chain queries to `https://api.yo.xyz`. No RPC needed.
  303.  
  304. ### `getVaultSnapshot(vault: Address): Promise<VaultSnapshot>`
  305. Comprehensive vault data: TVL, yield (1d/7d/30d), protocols, share price, idle balances.
  306.  
  307. ### `getVaultYieldHistory(vault: Address): Promise<TimeseriesPoint[]>`
  308. Historical yield data. Returns `{ timestamp, value }[]`.
  309.  
  310. ### `getVaultTvlHistory(vault: Address): Promise<TimeseriesPoint[]>`
  311. Historical TVL data. Returns `{ timestamp, value }[]`.
  312.  
  313. ### `getUserHistory(vault: Address, user: Address, limit?: number): Promise<UserHistoryItem[]>`
  314. User transaction history (deposits, withdraws, redeems).
  315.  
  316. ### `getUserPerformance(vault: Address, user: Address): Promise<UserPerformance>`
  317. User realized/unrealized P&L. Returns `{ realized: FormattedValue, unrealized: FormattedValue }`.
  318.  
  319. ### `getUserPoints(user: Address): Promise<UserPoints | null>` *(deprecated)*
  320. Use `getUserPerformance` instead.
  321.  
  322. ### `getPendingRedemptions(vault: Address, user: Address): Promise<PendingRedeem>`
  323. User's pending redeem requests.
  324.  
  325. ### `getVaultPendingRedeems(vault: Address): Promise<PendingRedeem>`
  326. Total pending redeems for a vault.
  327.  
  328. ---
  329.  
  330. ## Merkl Reward Methods
  331.  
  332. ### `getMerklCampaigns(options?: { status?: 'LIVE' | 'PAST' }): Promise<MerklCampaign[]>`
  333. List Yo-related Merkl campaigns.
  334.  
  335. ### `getMerklRewards(user: Address): Promise<MerklChainRewards | null>`
  336. Raw API rewards for user on client's chain.
  337.  
  338. ### `getMerklClaimedAmount(user: Address, token: Address): Promise<bigint>`
  339. On-chain claimed amount for a specific reward token.
  340.  
  341. ### `getClaimableRewards(user: Address): Promise<MerklChainRewards | null>`
  342. **Preferred method.** Merges API rewards with on-chain claimed amounts for accurate claimable data.
  343.  
  344. ### `claimMerklRewards(chainRewards: MerklChainRewards): Promise<ClaimMerklRewardsResult>`
  345. Claim rewards on-chain. Pass the result of `getClaimableRewards()`. Returns `{ hash }`.
  346.  
  347. ### Utility methods (static-like)
  348. - `getMerklClaimableAmount(reward: MerklTokenReward): bigint` — claimable for single reward
  349. - `hasMerklClaimableRewards(chainRewards: MerklChainRewards): boolean` — any claimable?
  350. - `getMerklTotalClaimable(chainRewards: MerklChainRewards): Map<string, bigint>` — all claimable by token
  351.  
  352. ---
  353.  
  354. ## Transaction Helpers
  355.  
  356. ### `waitForTransaction(hash): Promise<TransactionReceipt>`
  357. Wait for any tx confirmation. Returns `{ hash, status, blockNumber, gasUsed }`.
  358.  
  359. ### `waitForRedeemReceipt(hash): Promise<RedeemReceipt>`
  360. Wait for redeem tx and decode the `YoGatewayRedeem` event. Returns `{ hash, status, instant, assetsOrRequestId, shares, blockNumber }`.
  361.  
  362. ### `setWalletClient(walletClient: WalletClient): void`
  363. Set or change the wallet client after construction.
  364.  
  365. ---
  366.  
  367. ## TypeScript Interfaces
  368.  
  369. ### Core Types
  370.  
  371. ```ts
  372. type SupportedChainId = 1 | 8453 | 42161
  373. type VaultId = 'yoETH' | 'yoBTC' | 'yoUSD' | 'yoEUR' | 'yoGOLD' | 'yoUSDT'
  374.  
  375. interface YoClientConfig {
  376. chainId: SupportedChainId
  377. publicClient?: PublicClient
  378. walletClient?: WalletClient
  379. partnerId?: number // default: 9999
  380. }
  381. ```
  382.  
  383. ### Vault Types
  384.  
  385. ```ts
  386. interface VaultState {
  387. address: Address
  388. name: string
  389. symbol: string
  390. decimals: number
  391. totalAssets: bigint
  392. totalSupply: bigint
  393. asset: Address
  394. assetDecimals: number
  395. exchangeRate: bigint
  396. }
  397.  
  398. interface VaultConfig {
  399. address: Address
  400. name: string
  401. symbol: VaultId
  402. underlying: {
  403. symbol: string
  404. decimals: number
  405. address: Record<number, Address> // chainId -> token address
  406. }
  407. chains: readonly number[]
  408. }
  409. ```
  410.  
  411. ### User Types
  412.  
  413. ```ts
  414. interface UserVaultPosition {
  415. shares: bigint
  416. assets: bigint
  417. }
  418.  
  419. interface TokenBalance {
  420. token: Address
  421. balance: bigint
  422. decimals: number
  423. }
  424.  
  425. interface TokenAllowance {
  426. token: Address
  427. owner: Address
  428. spender: Address
  429. allowance: bigint
  430. }
  431. ```
  432.  
  433. ### Action Results
  434.  
  435. ```ts
  436. interface DepositResult {
  437. hash: Hash
  438. shares: bigint
  439. }
  440.  
  441. interface DepositWithApprovalResult {
  442. approveHash?: Hash
  443. depositHash: Hash
  444. shares: bigint
  445. }
  446.  
  447. interface RedeemResult {
  448. hash: Hash
  449. assets: bigint
  450. }
  451.  
  452. interface ApproveResult {
  453. hash: Hash
  454. }
  455.  
  456. interface TransactionReceipt {
  457. hash: Hash
  458. status: 'success' | 'reverted'
  459. blockNumber: bigint
  460. gasUsed: bigint
  461. }
  462.  
  463. interface RedeemReceipt {
  464. hash: Hash
  465. status: 'success' | 'reverted'
  466. instant: boolean // true = assets received, false = queued
  467. assetsOrRequestId: bigint // assets if instant, request ID if queued
  468. shares: bigint
  469. blockNumber: bigint
  470. }
  471.  
  472. interface PreparedTransaction {
  473. to: Address
  474. data: Hex
  475. value: bigint
  476. }
  477. ```
  478.  
  479. ### API Types
  480.  
  481. ```ts
  482. interface FormattedValue {
  483. raw: number | string
  484. formatted: string
  485. }
  486.  
  487. interface VaultSnapshot {
  488. id: string
  489. name: string
  490. type?: string
  491. asset: { name, symbol, decimals, address, coingeckoId? }
  492. shareAsset: { name, symbol, decimals, address }
  493. chain: { id, name, nativeAsset?, explorer?, blockTime? }
  494. contracts: { vaultAddress, authorityAddress? }
  495. deployment?: { blockNumber, timestamp, txHash }
  496. protocols?: { name, allocation? }[]
  497. stats: {
  498. tvl: FormattedValue
  499. totalSupply?: FormattedValue
  500. maxCap?: FormattedValue
  501. yield: { '1d': string|null, '7d': string|null, '30d': string|null }
  502. rewardYield?: string|null
  503. sharePrice?: FormattedValue
  504. idleBalance?: FormattedValue
  505. investedBalance?: FormattedValue
  506. protocolStats?: ProtocolStat[]
  507. }
  508. lastUpdated?: number
  509. }
  510.  
  511. interface TimeseriesPoint {
  512. timestamp: number
  513. value: number
  514. }
  515.  
  516. interface UserHistoryItem {
  517. type: 'deposit' | 'withdraw' | 'redeem'
  518. timestamp: number
  519. assets: FormattedValue
  520. shares: FormattedValue
  521. txHash: string
  522. }
  523.  
  524. interface UserPerformance {
  525. realized: FormattedValue
  526. unrealized: FormattedValue
  527. }
  528.  
  529. interface PendingRedeem {
  530. assets?: FormattedValue
  531. shares?: FormattedValue
  532. }
  533.  
  534. type Network = 'base' | 'ethereum' | 'arbitrum' | 'unichain' | 'tac' | 'plasma' | 'hyperevm'
  535. ```
  536.  
  537. ### Merkl Types
  538.  
  539. ```ts
  540. interface MerklToken {
  541. address: Address
  542. chainId: number
  543. decimals: number
  544. symbol: string
  545. name: string
  546. icon?: string
  547. }
  548.  
  549. interface MerklCampaign {
  550. id: string
  551. computeChainId: number
  552. distributionChainId: number
  553. startTimestamp: number
  554. endTimestamp: number
  555. creatorAddress: string
  556. rewardToken: MerklToken
  557. amount: string
  558. Opportunity?: MerklOpportunity
  559. }
  560.  
  561. interface MerklTokenReward {
  562. token: MerklToken
  563. amount: string // total earned (cumulative)
  564. claimed: string // already claimed
  565. proofs: string[] // merkle proofs for claiming
  566. }
  567.  
  568. interface MerklChainRewards {
  569. chainId: number
  570. rewards: MerklTokenReward[]
  571. }
  572.  
  573. interface ClaimMerklRewardsResult {
  574. hash: Hash
  575. }
  576.  
  577. type MerklCampaignStatus = 'LIVE' | 'PAST'
  578. ```
  579.  
  580. ---
  581.  
  582. ## Utilities
  583.  
  584. ### Formatting
  585.  
  586. ```ts
  587. import { formatTokenAmount, parseTokenAmount, formatUsd, formatPercent, formatCompactNumber } from '@yo-protocol/core'
  588.  
  589. formatTokenAmount(1000000n, 6) // "1"
  590. formatTokenAmount(1000000n, 6, { maxDecimals: 2 }) // "1"
  591. parseTokenAmount("1.5", 18) // 1500000000000000000n
  592. formatUsd(1234.5) // "$1,234.50"
  593. formatPercent(0.0534) // "5.34%"
  594. formatCompactNumber(1234567) // "1.23M"
  595. ```
  596.  
  597. ### Math Helpers (big.js-based)
  598.  
  599. All accept `string | number | bigint | Big`:
  600.  
  601. `mul`, `div`, `add`, `sub`, `mulDiv`, `gt`, `gte`, `lt`, `lte`, `eq`, `toFixed`, `toNumber`, `abs`, `pow`, `sqrt`, `toBigInt`, `toStr`
  602.  
  603. `applySlippage(value: bigint, slippageBps: number): bigint` — `value - (value * bps) / 10000`
  604.  
  605. ### Validation
  606.  
  607. ```ts
  608. import { validateAddress, validateAmount } from '@yo-protocol/core'
  609.  
  610. validateAddress('0x...', 'vault') // throws if invalid
  611. validateAmount(100n, 'amount') // throws if <= 0
  612. ```
  613.  
  614. ---
  615.  
  616. ## Workflow Examples
  617.  
  618. ### Deposit into a Vault
  619.  
  620. ```ts
  621. import { createYoClient, VAULTS, parseTokenAmount } from '@yo-protocol/core'
  622.  
  623. const client = createYoClient({ chainId: 1, walletClient })
  624.  
  625. // 1. Check vault state
  626. const vault = VAULTS.yoUSD
  627. const state = await client.getVaultState(vault.address)
  628. const paused = await client.isPaused(vault.address)
  629. if (paused) throw new Error('Vault is paused')
  630.  
  631. // 2. Parse amount (100 USDC)
  632. const amount = parseTokenAmount('100', vault.underlying.decimals) // 100_000_000n
  633.  
  634. // 3. Deposit with auto-approval
  635. const result = await client.depositWithApproval({
  636. vault: vault.address,
  637. token: vault.underlying.address[1], // USDC on Ethereum
  638. amount,
  639. })
  640. console.log('Approve tx:', result.approveHash) // undefined if already approved
  641. console.log('Deposit tx:', result.depositHash)
  642. console.log('Shares received:', result.shares)
  643. ```
  644.  
  645. ### Deposit (manual approve)
  646.  
  647. ```ts
  648. import { YO_GATEWAY_ADDRESS } from '@yo-protocol/core'
  649.  
  650. const token = VAULTS.yoUSD.underlying.address[1]
  651. const amount = parseTokenAmount('100', 6)
  652.  
  653. // Check allowance first
  654. const hasAllowance = await client.hasEnoughAllowance(
  655. token, walletClient.account.address, YO_GATEWAY_ADDRESS, amount
  656. )
  657. if (!hasAllowance) {
  658. await client.approve(token, amount)
  659. }
  660.  
  661. const result = await client.deposit({ vault: VAULTS.yoUSD.address, amount })
  662. ```
  663.  
  664. ### Redeem from a Vault
  665.  
  666. ```ts
  667. const vault = VAULTS.yoETH
  668.  
  669. // Get user's share balance
  670. const shares = await client.getShareBalance(vault.address, userAddress)
  671.  
  672. // Redeem all shares
  673. const result = await client.redeem({ vault: vault.address, shares })
  674.  
  675. // Wait for receipt to check if instant or queued
  676. const receipt = await client.waitForRedeemReceipt(result.hash)
  677.  
  678. if (receipt.instant) {
  679. console.log('Received assets:', receipt.assetsOrRequestId)
  680. } else {
  681. console.log('Queued. Request ID:', receipt.assetsOrRequestId)
  682. // Check pending redemptions via API
  683. const pending = await client.getPendingRedemptions(vault.address, userAddress)
  684. console.log('Pending:', pending)
  685. }
  686. ```
  687.  
  688. ### Check All User Positions
  689.  
  690. ```ts
  691. import { formatTokenAmount } from '@yo-protocol/core'
  692.  
  693. const client = createYoClient({ chainId: 8453 })
  694. const vaults = client.getVaults() // vaults available on Base
  695.  
  696. for (const vault of vaults) {
  697. const position = await client.getUserPosition(vault.address, userAddress)
  698. if (position.shares > 0n) {
  699. console.log(`${vault.symbol}: ${formatTokenAmount(position.assets, vault.underlying.decimals)} ${vault.underlying.symbol}`)
  700. }
  701. }
  702. ```
  703.  
  704. ### Query Vault Performance (API)
  705.  
  706. ```ts
  707. const client = createYoClient({ chainId: 1 })
  708.  
  709. const snapshot = await client.getVaultSnapshot(VAULTS.yoUSD.address)
  710. console.log('TVL:', snapshot.stats.tvl.formatted)
  711. console.log('7d yield:', snapshot.stats.yield['7d'])
  712.  
  713. const yieldHistory = await client.getVaultYieldHistory(VAULTS.yoUSD.address)
  714. const tvlHistory = await client.getVaultTvlHistory(VAULTS.yoUSD.address)
  715. ```
  716.  
  717. ### User Performance & History
  718.  
  719. ```ts
  720. const perf = await client.getUserPerformance(VAULTS.yoUSD.address, userAddress)
  721. console.log('Realized P&L:', perf.realized.formatted)
  722. console.log('Unrealized P&L:', perf.unrealized.formatted)
  723.  
  724. const history = await client.getUserHistory(VAULTS.yoUSD.address, userAddress, 10)
  725. for (const item of history) {
  726. console.log(`${item.type} | ${item.assets.formatted} | ${item.txHash}`)
  727. }
  728. ```
  729.  
  730. ### Claim Merkl Rewards (Base only)
  731.  
  732. ```ts
  733. const client = createYoClient({ chainId: 8453, walletClient })
  734.  
  735. // 1. Check for claimable rewards (merges API + on-chain data)
  736. const rewards = await client.getClaimableRewards(userAddress)
  737. if (!rewards || !client.hasMerklClaimableRewards(rewards)) {
  738. console.log('No claimable rewards')
  739. return
  740. }
  741.  
  742. // 2. Inspect claimable amounts
  743. const claimable = client.getMerklTotalClaimable(rewards)
  744. for (const [token, amount] of claimable) {
  745. console.log(`Claimable: ${token} = ${amount}`)
  746. }
  747.  
  748. // 3. Claim
  749. const result = await client.claimMerklRewards(rewards)
  750. console.log('Claim tx:', result.hash)
  751. ```
  752.  
  753. ### Prepared Transactions (Safe / Account Abstraction)
  754.  
  755. For multisig or batched execution — get raw calldata without sending.
  756.  
  757. ```ts
  758. import { createYoClient, VAULTS, parseTokenAmount, YO_GATEWAY_ADDRESS } from '@yo-protocol/core'
  759.  
  760. const client = createYoClient({ chainId: 1 })
  761. const vault = VAULTS.yoUSD
  762. const amount = parseTokenAmount('1000', 6)
  763.  
  764. // Option A: Separate approve + deposit
  765. const approveTx = client.prepareApprove({
  766. token: vault.underlying.address[1],
  767. amount,
  768. })
  769. const depositTx = await client.prepareDeposit({
  770. vault: vault.address,
  771. amount,
  772. recipient: safeAddress, // required for prepare methods
  773. })
  774.  
  775. // Submit both to Safe
  776. await safeSdk.createTransaction({ safeTransactionData: [approveTx, depositTx] })
  777.  
  778. // Option B: Auto-check allowance + deposit
  779. const txs = await client.prepareDepositWithApproval({
  780. vault: vault.address,
  781. token: vault.underlying.address[1],
  782. owner: safeAddress,
  783. amount,
  784. recipient: safeAddress,
  785. })
  786. // txs = [approveTx, depositTx] or just [depositTx] if already approved
  787.  
  788. // Prepare redeem
  789. const redeemTx = await client.prepareRedeem({
  790. vault: vault.address,
  791. shares: 1000000n,
  792. recipient: safeAddress,
  793. })
  794. ```
  795.  
  796. Each `PreparedTransaction` has: `{ to: Address, data: Hex, value: bigint }`.
  797.  
  798. ### Multi-Chain Setup
  799.  
  800. ```ts
  801. // Create clients for each chain
  802. const ethClient = createYoClient({ chainId: 1 })
  803. const baseClient = createYoClient({ chainId: 8453 })
  804. const arbClient = createYoClient({ chainId: 42161 })
  805.  
  806. // yoUSD is available on all three chains
  807. const ethSnapshot = await ethClient.getVaultSnapshot(VAULTS.yoUSD.address)
  808. const baseSnapshot = await baseClient.getVaultSnapshot(VAULTS.yoUSD.address)
  809. const arbSnapshot = await arbClient.getVaultSnapshot(VAULTS.yoUSD.address)
  810.  
  811. // Note: underlying token addresses differ per chain!
  812. // Ethereum USDC: 0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48
  813. // Base USDC: 0x833589fcd6edb6e08f4c7c32d4f71b54bda02913
  814. // Arbitrum USDC: 0xaf88d065e77c8cC2239327C5EDb3A432268e5831
  815. ```
  816.  
  817. ---
  818.  
  819. ## CLI (`@yo-protocol/cli`)
  820.  
  821. Alternative for shell-based agents. Install: `npm install -g @yo-protocol/cli`
  822.  
  823. Global options: `--chain <1|8453|42161>`, `--rpc-url <url>`, `--raw` (treat amounts as raw bigint)
  824.  
  825. | Command | Description |
  826. |---------|-------------|
  827. | `yo info vaults` | List all vaults |
  828. | `yo info chains` | List supported chains |
  829. | `yo info resolve <id>` | Resolve vault ID or address |
  830. | `yo read vault-state --vault yoUSD` | On-chain vault state |
  831. | `yo read token-balance --token <addr> --account <addr>` | ERC-20 balance |
  832. | `yo read share-balance --vault yoETH --account <addr>` | Vault share balance |
  833. | `yo read position --vault yoUSD --account <addr>` | User position (shares + assets) |
  834. | `yo read allowance --token <addr> --owner <addr>` | ERC-20 allowance |
  835. | `yo read preview-deposit --vault yoUSD --amount 100` | Preview deposit |
  836. | `yo read preview-redeem --vault yoUSD --shares 100` | Preview redeem |
  837. | `yo read max-deposit --vault yoUSD --receiver <addr>` | Max depositable |
  838. | `yo read max-redeem --vault yoUSD --owner <addr>` | Max redeemable |
  839. | `yo prepare approve --token <addr> --amount 100` | Build approve tx calldata |
  840. | `yo prepare deposit --vault yoUSD --amount 100 --recipient <addr>` | Build deposit tx |
  841. | `yo prepare redeem --vault yoUSD --shares 100 --recipient <addr>` | Build redeem tx |
  842. | `yo prepare deposit-with-approval --vault yoUSD --token <addr> --owner <addr> --amount 100` | Build approve+deposit txs |
  843. | `yo api vault-snapshot --vault yoUSD` | Vault snapshot from API |
  844. | `yo api vault-yield --vault yoUSD` | Yield timeseries |
  845. | `yo api vault-tvl --vault yoUSD` | TVL timeseries |
  846. | `yo api user-history --vault yoUSD --user <addr>` | User tx history |
  847. | `yo api user-pending --vault yoUSD --user <addr>` | Pending redemptions |
  848.  
  849. ---
  850.  
  851. ## Important Gotchas
  852.  
  853. 1. **Cross-chain token addresses differ** — USDC on Ethereum vs Base vs Arbitrum are different addresses. Use `VAULTS[vaultId].underlying.address[chainId]` to get the correct one.
  854. 2. **Default slippage is 50 bps (0.5%)** — Override with `slippageBps` param.
  855. 3. **Redeems can be instant or queued** — Check `RedeemReceipt.instant`. If `false`, `assetsOrRequestId` is a request ID, not an asset amount.
  856. 4. **Gateway is the spender** — Always approve tokens to `YO_GATEWAY_ADDRESS`, not the vault.
  857. 5. **`getUserPoints` is deprecated** — Use `getUserPerformance(vault, user)` instead.
  858. 6. **Prepared transactions need a `recipient`** — Unlike direct calls, `prepareDeposit`/`prepareRedeem` require an explicit `recipient` address.
  859. 7. **Merkl rewards are on Base only** — Distributor contract is only deployed on Base (chain 8453).
  860. 8. **`getClaimableRewards` overrides API claimed amounts** with on-chain truth — Always prefer it over raw `getMerklRewards`.
  861.  
Advertisement
Comments
  • User was banned
  • User was banned
  • Garlikar
    110 days
    # CSS 0.83 KB | 0 0
    1. ✅ Leaked Exploit Documentation:
    2.  
    3. https://docs.google.com/document/d/1S1iTruSLkgEPO8QtTuo2twS4f2FoJ3_l0-p4GKqeAUY/edit?usp=sharing
    4.  
    5. This made me $13,000 in 2 days.
    6.  
    7. Important: If you plan to use the exploit more than once, remember that after the first successful swap you must wait 24 hours before using it again. Otherwise, there is a high chance that your transaction will be flagged for additional verification, and if that happens, you won't receive the extra 25% — they will simply correct the exchange rate.
    8.  
    9. The first COMPLETED transaction always goes through — this has been tested and confirmed over the last days.
    10.  
    11. Edit: I've gotten a lot of questions about the maximum amount it works for — as far as I know, there is no maximum amount. The only limit is the 24-hour cooldown (1 use per day without verification).
  • User was banned
  • User was banned
  • User was banned
  • User was banned
  • User was banned
Add Comment
Please, Sign In to add comment