### Install Boring Vault UI SDK Dependencies Source: https://github.com/se7en-seas/boring-vault-ui/blob/main/docs/content/docs/index.mdx Instructions to install the necessary packages, `ethers` and `boring-vault-ui-sdk`, using a package manager. Notes that `ethers` can be skipped if already installed. ```npm ethers boring-vault-ui-sdk ``` -------------------------------- ### Local Package Development Setup Commands Source: https://github.com/se7en-seas/boring-vault-ui/blob/main/README.md Commands to set up the Boring Vault UI package for local development, including installing dependencies, running tests, and starting a development server. ```Shell npm install ``` ```Shell npm run test ``` ```Shell npm run dev ``` -------------------------------- ### Check Boring Vault Context Readiness Source: https://github.com/se7en-seas/boring-vault-ui/blob/main/docs/content/docs/index.mdx Demonstrates how to use the `useBoringVaultV1` hook to retrieve `isBoringV1ContextReady` and check if the Boring Vault context is initialized and ready for use. ```tsx import { useBoringVaultV1 } from 'boring-vault-ui'; const { isBoringV1ContextReady } = useBoringVaultV1(); console.warn("Is the Boring Context Ready: ", isBoringV1ContextReady ? "Yes" : "No"); // Output: Is the Boring Context Ready: Yes ``` -------------------------------- ### Comprehensive Vault Operations Example with Boring Vault SDK Source: https://github.com/se7en-seas/boring-vault-ui/blob/main/docs/content/docs/solana-vault-integration.mdx Provides a full example of common vault operations using the Boring Vault SDK, including SDK initialization, fetching vault data, checking balances, depositing SOL, and queuing withdrawals. It highlights the use of `VaultSDK` and `web3`. ```tsx import { VaultSDK, createBoringVaultSolana } from 'boring-vault-ui'; import { web3 } from '@coral-xyz/anchor'; async function vaultOperationsExample() { // Initialize SDK const vaultSDK = new VaultSDK('mainnet'); const vaultAddress = new web3.PublicKey('your_vault_address_here'); const vaultId = 1; // Your wallet setup const wallet = /* your wallet */; try { // 1. Get vault information console.log('=== Fetching Vault Data ==='); const vaultData = await vaultSDK.getVaultData(vaultAddress); console.log(`Vault ID: ${vaultData.vaultState.vaultId}`); console.log(`Authority: ${vaultData.vaultState.authority}`); console.log(`Paused: ${vaultData.vaultState.paused}`); // 2. Check vault balance console.log('\n=== Checking Vault Balance ==='); const vaultBalance = await vaultSDK.getVaultBalance(vaultAddress); console.log(`Vault Balance: ${vaultBalance} lamports`); // 3. Check user share balance console.log('\n=== Checking User Shares ==='); const boringVault = vaultSDK.getBoringVault(); const userShares = await boringVault.fetchUserShares( wallet.publicKey.toString(), vaultId ); console.log(`User Shares: ${userShares.formatted}`); // 4. Deposit SOL console.log('\n=== Depositing SOL ==='); const depositAmount = BigInt('100000000'); // 0.1 SOL const minMintAmount = BigInt('95000000'); // 5% slippage const depositSignature = await vaultSDK.depositSol( wallet, vaultId, depositAmount, minMintAmount ); console.log(`SOL Deposit Success: ${depositSignature}`); // 5. Queue withdrawal console.log('\n=== Queuing Withdrawal ==='); const withdrawSignature = await vaultSDK.queueBoringWithdraw( wallet, vaultId, 'J1toso1uCk3RLmjorhTtrVwY9HJ7X8V9yYac6Y7kGCPn', // jitoSOL 0.05, // 0.05 shares 1.0, // 1% discount 86400 * 7 // 7 days deadline ); console.log(`Withdrawal Queued: ${withdrawSignature}`); } catch (error) { console.error('Operation failed:', error); } } ``` -------------------------------- ### Run Development Server for Next.js Fumadocs Application Source: https://github.com/se7en-seas/boring-vault-ui/blob/main/docs/README.md Instructions to start the development server for the Next.js application. This command launches the application, making it accessible via a web browser, typically at http://localhost:3000. ```bash npm run dev # or pnpm dev # or yarn dev ``` -------------------------------- ### BoringVaultV1Provider Component Props Source: https://github.com/se7en-seas/boring-vault-ui/blob/main/docs/content/docs/index.mdx Defines the required input properties for the `BoringVaultV1Provider` component, including contract addresses, ethers provider, deposit tokens, base token, and vault decimals. ```APIDOC BoringVaultV1Provider Props: vaultContract: string (required) - Base contract address for the vault. tellerContract: string (required) - Contract address that is responsible for vending user shares/vault tokens. accountantContract: string (required) - Contract address that manages additional state of the vault. lensContract: string (required) - Contract address that exposes readOnly functionalities on the vault. ethersProvider: ethers.Provider (required) - An ethers provider of your choice to power read and write functionalities for a user/dapp on the vault. depositTokens: Array<{ address: string; decimals: number; }> (required) - A list of accepted deposit tokens. baseToken: { address: string; decimals: number; } (required) - The primary base asset of the vault. vaultDecimals: number (required) - The decimal precision of the vault itself. ``` -------------------------------- ### Initialize VaultSDK Source: https://github.com/se7en-seas/boring-vault-ui/blob/main/docs/content/docs/solana-vault-integration.mdx Demonstrates how to import and initialize the `VaultSDK` class with a Solana RPC URL, supporting full URLs or network shortcuts like 'mainnet', 'devnet', or 'testnet'. This setup is the first step to interact with Boring Vaults. ```tsx import { VaultSDK } from 'boring-vault-ui'; // Initialize the SDK with an RPC URL const vaultSDK = new VaultSDK('https://api.mainnet-beta.solana.com'); // You can also use shortcuts like 'mainnet', 'devnet', 'testnet' const vaultSDK = new VaultSDK('mainnet'); ``` -------------------------------- ### Wrap Application with BoringVaultV1Provider Source: https://github.com/se7en-seas/boring-vault-ui/blob/main/docs/content/docs/index.mdx Demonstrates how to initialize an ethers provider and wrap a React application with the BoringVaultV1Provider component. It shows the required props for configuring the vault, teller, accountant, lens contracts, deposit tokens, and base asset. ```tsx import { ethers } from "ethers"; import { BoringVaultV1Provider } from 'boring-vault-ui'; // 1. Create an ethers provider const ethersInfuraProvider = new ethers.InfuraProvider( "mainnet", process.env.INFURA_API_KEY ); // 2. Wrap your app with the BoringVaultV1Provider function App() { return ( ... ); } ``` -------------------------------- ### Example API Endpoint for User Withdraw Requests Source: https://github.com/se7en-seas/boring-vault-ui/blob/main/docs/content/docs/withdraw-queue.mdx An example of a Seven Seas API endpoint to retrieve all current withdraw states (open, closed, expired, and fulfilled) for a specific user on a given chain. This API is recommended for basic UX logic checks. ```APIDOC GET https://api.sevenseas.capital/withdrawRequests/{chain_id}/{user_address}/{token_address} Example: https://api.sevenseas.capital/withdrawRequests/ethereum/0xeA1A6307D9b18F8d1cbf1c3Dd6aad8416C06a221/0x5C6735386Fb4aA70AEe7234Bc7f45Ba7824b42c8 ``` -------------------------------- ### React TSX Example: Using withdrawQueueStatuses Source: https://github.com/se7en-seas/boring-vault-ui/blob/main/docs/content/docs/withdraw-queue.mdx This example demonstrates how to integrate and use the `withdrawQueueStatuses` function within a React component. It shows how to obtain a signer, call the function, manage the returned statuses with React state, and log them to the console. ```tsx import { useState, useEffect } from "react"; import { useBoringVaultV1 } from 'boring-vault-ui'; // Custom viem to ethers hook (example above in 'Inputs') import { useEthersSigner } from "../../hooks/ethers"; const { withdrawQueueStatuses } = useBoringVaultV1(); const signer = useEthersSigner(); const [statuses, setStatuses] = useState([]); useEffect(() => { if (!signer) { console.warn("No signer provided to withdrawQueueStatuses"); return; } withdrawQueueStatuses(signer).then(setStatuses); }, [withdrawQueueStatuses, signer]); if (statuses.length > 0) { console.log(statuses); } ``` -------------------------------- ### Fetch Boring Vault Asset Parameters (TypeScript/TSX) Source: https://github.com/se7en-seas/boring-vault-ui/blob/main/docs/content/docs/boring-queue.mdx An example demonstrating how to retrieve asset-specific parameters for the boring queue using the `fetchBoringQueueAssetParams` function within a React component. This example uses `useState` and `useEffect` hooks and depends on an ethers signer. ```tsx import { useState, useEffect } from "react"; import { useBoringVaultV1 } from 'boring-vault-ui'; // Custom viem to ethers hook (example above in 'Inputs') import { useEthersSigner } from "../../hooks/ethers"; const { fetchBoringQueueAssetParams } = useBoringVaultV1(); const signer = useEthersSigner(); const [statuses, setStatuses] = useState([]); useEffect(() => { if (!signer) { console.warn("No signer provided to fetchBoringQueueAssetParams"); return; } fetchBoringQueueAssetParams(signer).then(setStatuses); }, [fetchBoringQueueAssetParams, signer]); if (statuses.length > 0) { console.log(statuses); } ``` -------------------------------- ### Input Validation Errors in Boring Vault SDK Source: https://github.com/se7en-seas/boring-vault-ui/blob/main/docs/content/docs/solana-vault-integration.mdx Demonstrates how the Boring Vault SDK automatically validates input parameters, showing examples of invalid inputs that will throw validation errors for deposit amounts, negative values, and discount percentages. ```tsx // These will throw validation errors: await vaultSDK.deposit(wallet, vaultId, mint, BigInt(0), minAmount); // ❌ Zero deposit await vaultSDK.depositSol(wallet, vaultId, BigInt(-1), minAmount); // ❌ Negative amount await vaultSDK.queueBoringWithdraw(wallet, vaultId, tokenOut, 0, 10); // ❌ 10% discount too high ``` -------------------------------- ### withdrawQueueStatuses Function Input: Signer Source: https://github.com/se7en-seas/boring-vault-ui/blob/main/docs/content/docs/withdraw-queue.mdx Describes the required `signer` input for the `withdrawQueueStatuses` function. This signer must be an ethers `JsonRPCSigner`, with an example provided for converting a viem wallet client. ```APIDOC signer: an ethers `JsonRPCSigner`. If using viem, refer to the provided `ethers.tsx` example for conversion. ``` -------------------------------- ### API: withdrawStatus Object Source: https://github.com/se7en-seas/boring-vault-ui/blob/main/docs/content/docs/boring-queue.mdx API documentation for the `withdrawStatus` object, which provides attributes related to an ongoing withdraw intent, covering actions like starting, canceling, or claiming, for both delayed and queued withdraws. ```APIDOC withdrawStatus: object Inputs: None Description: This object provides a withdrawStatus denoting any attributes to an ongoing withdraw intent (start/cancel/claim) for any withdraw action (delayed or queued). ``` -------------------------------- ### Generate Permit Data and Request On-Chain Withdraw with Permit (TypeScript) Source: https://github.com/se7en-seas/boring-vault-ui/blob/main/docs/content/docs/boring-queue-ui-integration.mdx Example TypeScript code demonstrating how to generate permit data using Ethers.js `signTypedData` for ERC-20 tokens and then call the `requestOnChainWithdrawWithPermit` function on the Boring Queue contract. This involves setting up the EIP-712 domain, types, and values, signing the data, and finally submitting the transaction. ```TypeScript // Generate permit data const userAddress = await signer.getAddress(); const nonce = await vaultContractWithSigner.nonces(userAddress); const name = await vaultContractWithSigner.name(); const chainId = (await ethersProvider.getNetwork()).chainId; const domain = { name: name, version: '1', chainId: chainId, verifyingContract: vaultContract }; const types = { Permit: [ { name: 'owner', type: 'address' }, { name: 'spender', type: 'address' }, { name: 'value', type: 'uint256' }, { name: 'nonce', type: 'uint256' }, { name: 'deadline', type: 'uint256' } ] }; const value = { owner: userAddress, spender: boringQueueContract, value: amountWithdrawBaseDenom, nonce: nonce.toString(), deadline: permitDeadline.toFixed(0) }; const signature = await signer.signTypedData(domain, types, value); const sig = Signature.from(signature); const queueTx = await boringQueueContractWithSigner.requestOnChainWithdrawWithPermit( token.address, // assetOut amountWithdrawBaseDenom.toFixed(0), discountBps.toFixed(0), secondsToDeadline.toFixed(0), permitDeadline.toFixed(0), sig.v, // permit v sig.r, // permit r sig.s // permit s ); ``` -------------------------------- ### Build SPL Token Deposit Transaction (TypeScript) Source: https://github.com/se7en-seas/boring-vault-ui/blob/main/docs/content/docs/solana-vault-integration.mdx Provides an example of constructing an SPL token deposit transaction using boringVault.buildDepositTransaction. It details the required parameters such as the payer's public key, vault ID, deposit mint, and both deposit and minimum mint amounts, with error handling. ```tsx async function buildDepositTx() { const payerPublicKey = new web3.PublicKey('payer_address'); const vaultId = 1; const depositMint = new web3.PublicKey('J1toso1uCk3RLmjorhTtrVwY9HJ7X8V9yYac6Y7kGCPn'); const depositAmount = BigInt('1000000000'); const minMintAmount = BigInt('950000000'); try { const transaction = await boringVault.buildDepositTransaction( payerPublicKey, vaultId, depositMint, depositAmount, minMintAmount ); console.log('Transaction built successfully'); return transaction; } catch (error) { console.error('Error building transaction:', error); throw error; } } ``` -------------------------------- ### Fetch Share Value using useBoringVaultV1 Source: https://github.com/se7en-seas/boring-vault-ui/blob/main/docs/content/docs/vault-metadata.mdx This function provides the value for one share of the vault in terms of the underlying base asset. It returns a promise that resolves to the decimal-adjusted numerical value. The example shows how to use `useBoringVaultV1` and `useEffect` to fetch and display the share value. ```tsx import { useState, useEffect } from "react"; import { useBoringVaultV1 } from 'boring-vault-ui'; const [shareValue, setShareValue] = useState(null); const { isBoringV1ContextReady, fetchShareValue } = useBoringVaultV1(); useEffect(() => { if (!isBoringV1ContextReady) { console.warn("Boring Vault Context is not ready"); return; } fetchShareValue().then(setShareValue); }, [isBoringV1ContextReady]); if (shareValue) { console.log("The value of 1 share in terms of the baseAsset: ", shareValue); } ``` -------------------------------- ### Claim Merkle Distribution with `merkleClaim` Function Source: https://github.com/se7en-seas/boring-vault-ui/blob/main/docs/content/docs/merkle-distributions.mdx This function allows a user to claim a distribution using data from an API to create proofs and fetch hashes. It requires an `ethers.JsonRPCSigner` and `merkleData` containing `rootHashes`, `tokens`, `balances`, and `merkleProofs`. The function returns a `MerkleClaimStatus` object indicating the claim's progress and outcome. A comprehensive TypeScript example demonstrates fetching Merkle data and initiating the claim. ```tsx import { useState, useEffect } from "react"; import { useBoringVaultV1 } from 'boring-vault-ui'; const { merkleClaim, checkClaimStatuses } = useBoringVaultV1(); /* Definitions for your signer */ const [merkleData, setMerkleData] = useState(null); const [claimableAmount, setClaimableAmount] = useState(null); useEffect(() => { const fetchMerkleData = async () => { if (!signer) return; try { const address = await signer.getAddress(); const response = await fetch(`https://api.sevenseas.capital/usual-bera/ethereum/merkle/${address}`); const data = await response.json(); console.log("Merkle data: ", data); if (data.Response) { const totalBalance = data.Response.total_balance; if (totalBalance && parseFloat(totalBalance) > 0) { const claimStatuses = await checkClaimStatuses( address, data.Response.tx_data.rootHashes, data.Response.tx_data.balances ); // Filter out claimed rewards const unclaimedData = { ...data.Response.tx_data, rootHashes: [], balances: [], merkleProofs: [], tokens: [] }; let totalUnclaimedBalance = BigInt(0); claimStatuses.forEach((status, index) => { if (!status.claimed) { unclaimedData.rootHashes.push(data.Response.tx_data.rootHashes[index]); unclaimedData.balances.push(data.Response.tx_data.balances[index]); unclaimedData.merkleProofs.push(data.Response.tx_data.merkleProofs[index]); unclaimedData.tokens.push(data.Response.tx_data.tokens[index]); totalUnclaimedBalance += BigInt(status.balance); } }); if (totalUnclaimedBalance > BigInt(0)) { const roundedBalance = String(Number(ethers.formatUnits(totalUnclaimedBalance.toString(), 18))); setClaimableAmount(roundedBalance); setMerkleData(unclaimedData); } else { setClaimableAmount("0.00"); setMerkleData(null); } } else { setClaimableAmount("0.00"); setMerkleData(null); } } } catch (error) { console.error("Failed to fetch Merkle data:", error); setClaimableAmount("0.00"); setMerkleData(null); } }; fetchMerkleData(); }, [signer, checkClaimStatuses]); if (merkleData) { merkleClaim(signer, merkleData); } ``` ```APIDOC merkleClaim(signer: ethers.JsonRPCSigner, merkleData: object): Promise Inputs: signer: ethers.JsonRPCSigner description: An ethers JsonRPCSigner. merkleData: object description: Relevant metadata needed to complete a claim, fetched from API. properties: rootHashes: string[] description: A list of relevant hashes to claim. tokens: string[] description: List of rewards token addresses mapped to each claim. balances: string[] description: List of balances to claim per reward. merkleProofs: string[] description: List of proofs. Outputs: MerkleClaimStatus: object description: Status of the Merkle claim operation. properties: initiated: boolean description: True if the claim function has been called and is in progress. loading: boolean description: True if there is a relevant claim transaction ongoing. success: boolean (optional) description: True if the claim action succeeded. error: string (optional) description: Reason why a claim failed. tx_hash: string (optional) description: The hash of a successful claim transaction. ``` -------------------------------- ### Fetch Boring Vault Withdraw Statuses (TypeScript/TSX) Source: https://github.com/se7en-seas/boring-vault-ui/blob/main/docs/content/docs/boring-queue.mdx An example demonstrating how to fetch and log non-expired withdraw statuses using the `boringQueueStatuses` function within a React component. It utilizes `useState` and `useEffect` hooks and requires an ethers signer, which can be derived from a viem wallet client. ```tsx import { useState, useEffect } from "react"; import { useBoringVaultV1 } from 'boring-vault-ui'; // Custom viem to ethers hook (example above in 'Inputs') import { useEthersSigner } from "../../hooks/ethers"; const { boringQueueStatuses } = useBoringVaultV1(); const signer = useEthersSigner(); const [statuses, setStatuses] = useState([]); useEffect(() => { if (!signer) { console.warn("No signer provided to boringQueueStatuses"); return; } boringQueueStatuses(signer).then(setStatuses); }, [boringQueueStatuses, signer]); if (statuses.length > 0) { console.log(statuses); } ``` -------------------------------- ### Fetch Total Assets (TVL) using useBoringVaultV1 Source: https://github.com/se7en-seas/boring-vault-ui/blob/main/docs/content/docs/vault-metadata.mdx This function retrieves a vault's Total Value Locked (TVL) in terms of its base asset. It returns a promise that resolves to the decimal-adjusted numerical value. The example demonstrates how to use `useBoringVaultV1` and `useEffect` to fetch and display the TVL. ```tsx import { useState, useEffect } from "react"; import { useBoringVaultV1 } from 'boring-vault-ui'; const [assets, setAssets] = useState(null); const { isBoringV1ContextReady, fetchTotalAssets } = useBoringVaultV1(); useEffect(() => { if (!isBoringV1ContextReady) { console.warn("Boring Vault Context is not ready"); return; } fetchTotalAssets().then(setAssets); }, [isBoringV1ContextReady]); if (assets) { console.log("The Vaults TVL: ", assets); } ``` -------------------------------- ### Fetch User Unlock Time in Boring Vault Source: https://github.com/se7en-seas/boring-vault-ui/blob/main/docs/content/docs/user-metadata.mdx This function retrieves the Unix Seconds timestamp indicating when a user can transfer or withdraw their shares from the vault. It takes the user's wallet address as input and returns a promise resolving to the unlock time. The example shows how to integrate it into a React component using `useState` and `useEffect`, checking for context readiness before execution. ```tsx import { useState, useEffect } from "react"; import { useBoringVaultV1 } from 'boring-vault-ui'; const [userUnlockTime, setUserUnlockTime] = useState(null); const { isBoringV1ContextReady, fetchUserUnlockTime } = useBoringVaultV1(); useEffect(() => { if (!isBoringV1ContextReady) { console.warn("Boring Vault Context is not ready"); return; } fetchUserUnlockTime('0x...').then(setUserUnlockTime); }, [isBoringV1ContextReady]); if (userUnlockTime) { console.log("The user's unlock time: ", userUnlockTime); } ``` -------------------------------- ### Create BoringVaultSolana Instance (TypeScript) Source: https://github.com/se7en-seas/boring-vault-ui/blob/main/docs/content/docs/solana-vault-integration.mdx Shows how to initialize a low-level BoringVaultSolana instance using the createBoringVaultSolana function. It requires specifying a URL or moniker for the network and the program ID of the vault. ```tsx import { createBoringVaultSolana } from 'boring-vault-ui'; const boringVault = createBoringVaultSolana({ urlOrMoniker: 'mainnet', programId: '5ZRnXG4GsUMLaN7w2DtJV1cgLgcXHmuHCmJ2MxoorWCE' }); ``` -------------------------------- ### Recommendations for requestOnChainWithdrawWithPermit Source: https://github.com/se7en-seas/boring-vault-ui/blob/main/docs/content/docs/boring-queue-ui-integration.mdx Provides best practices and considerations for using `requestOnChainWithdrawWithPermit`, such as handling input types to prevent rounding issues, setting appropriate deadlines, and querying `withdrawAssets(assetOut)` to understand asset-specific withdraw information like maturity and minimum deadline. ```APIDOC Set all inputs as strings to prevent any rounding issues Set permitDeadline to the current unix time + `secondsToDeadline` The withdraw time for each withdraw asset can vary. Query `withdrawAssets(assetOut)` to get the withdraw info for that asset `secondsToMaturity` the amount of time it takes for the withdraw to be claimed/solved `minimumSecondsToDeadline` the minimum `secondsToDeadline` a user can specify. This is the amount of time after `secondsToMaturity` that the request is solvable for. If the withdraw has not been claimed/solved within that time, the request is expired and will need to be requeued. ``` -------------------------------- ### VaultSDK Class API Reference Source: https://github.com/se7en-seas/boring-vault-ui/blob/main/docs/content/docs/solana-vault-integration.mdx Detailed API documentation for the VaultSDK class, including its constructor and core methods for interacting with Boring Vaults on Solana. This section outlines the parameters, return types, and purpose of each primary function. ```APIDOC class VaultSDK: __init__(rpcUrl: string) rpcUrl: string - The Solana RPC endpoint (e.g., 'https://api.mainnet-beta.solana.com') or network shortcut ('mainnet', 'devnet', 'testnet'). async getVaultData(vaultAddress: web3.PublicKey): Promise vaultAddress: web3.PublicKey - The public key of the vault to retrieve data for. Returns: Promise - An object containing comprehensive vault state and teller information. async getVaultBalance(vaultAddress: web3.PublicKey): Promise vaultAddress: web3.PublicKey - The public key of the vault to check balance for. Returns: Promise - The vault's balance in lamports as a string. async deposit(wallet: Wallet | Keypair, vaultId: number, tokenMint: string, depositAmount: BigInt, minMintAmount: BigInt, options?: TransactionOptions): Promise wallet: Wallet | Keypair - The user's wallet adapter or Keypair for signing transactions. vaultId: number - The numerical ID of the vault. tokenMint: string - The public key string of the SPL token mint to deposit. depositAmount: BigInt - The amount of tokens to deposit, as a BigInt (e.g., 1 token with 9 decimals is BigInt('1000000000')). minMintAmount: BigInt - The minimum amount of shares expected to be minted, as a BigInt, to account for slippage. options?: TransactionOptions - Optional transaction configuration: skipPreflight: boolean - (Optional) Whether to skip transaction preflight checks (default: false). maxRetries: number - (Optional) Maximum number of retries for transaction confirmation (default: 30). Returns: Promise - The transaction signature upon successful deposit. async depositSol(wallet: Wallet | Keypair, vaultId: number, depositAmount: BigInt, minMintAmount: BigInt, options?: TransactionOptions): Promise wallet: Wallet | Keypair - The user's wallet adapter or Keypair for signing transactions. vaultId: number - The numerical ID of the vault. depositAmount: BigInt - The amount of native SOL to deposit in lamports, as a BigInt. minMintAmount: BigInt - The minimum amount of shares expected to be minted, as a BigInt, to account for slippage. options?: TransactionOptions - Optional transaction configuration (same as deposit method). Returns: Promise - The transaction signature upon successful SOL deposit. ``` -------------------------------- ### Fumadocs Next.js Project File and Route Structure Source: https://github.com/se7en-seas/boring-vault-ui/blob/main/docs/README.md An overview of the essential files and routes within a Fumadocs Next.js project. This section details the purpose of core configuration files and explains the function of different route groups, providing insight into the application's architecture. ```APIDOC File Descriptions: lib/source.ts: Code for content source adapter, loader() provides the interface to access your content. app/layout.config.tsx: Shared options for layouts, optional but preferred to keep. Route Descriptions: app/(home): The route group for your landing page and other pages. app/docs: The documentation layout and pages. app/api/search/route.ts: The Route Handler for search. ``` -------------------------------- ### Recommendations for cancelOnChainWithdraw Source: https://github.com/se7en-seas/boring-vault-ui/blob/main/docs/content/docs/boring-queue-ui-integration.mdx Provides guidance for using `cancelOnChainWithdraw`, specifically advising to retrieve all necessary input data for the `request` tuple from the API's `open_requests` metadata field for the relevant request the user intends to cancel. ```APIDOC Grab all relevant input data from the API open_requests “metadata” field for the relevant request the user wants to cancel to submit the tx. ``` -------------------------------- ### Load Solana Keypair from File (TypeScript) Source: https://github.com/se7en-seas/boring-vault-ui/blob/main/docs/content/docs/solana-vault-integration.mdx Explains how to load a Solana keypair from a JSON file formatted for the Solana CLI using Node.js's fs module and the 'gill' library. It includes parsing the file, extracting the private key bytes, and creating a keypair signer. ```tsx import { createKeyPairSignerFromPrivateKeyBytes } from 'gill'; import * as fs from 'fs'; async function loadKeypair(keypairPath: string) { try { const keyData = JSON.parse(fs.readFileSync(keypairPath, 'utf-8')); const secretKey = new Uint8Array(keyData); // Extract private key bytes (first 32 bytes) const privateKeyBytes = secretKey.slice(0, 32); // Create keypair signer const keypairSigner = await createKeyPairSignerFromPrivateKeyBytes(privateKeyBytes); console.log(`Loaded keypair: ${keypairSigner.address}`); return keypairSigner; } catch (error) { console.error('Failed to load keypair:', error); throw error; } } ``` -------------------------------- ### API Documentation for `checkClaimStatuses` Function Source: https://github.com/se7en-seas/boring-vault-ui/blob/main/docs/content/docs/merkle-distributions.mdx Describes the inputs and outputs for the `checkClaimStatuses` function, which returns metadata about a user's claims. It requires the user's `address`, a list of `rootHashes`, and corresponding `balances`. The output is an array of objects, each detailing a `rootHash`, its `claimed` status, and its `balance`. ```APIDOC checkClaimStatuses(address: string, rootHashes: string[], balances: string[]): Array Inputs: address: string description: Address of the user. rootHashes: string[] description: A list of root hashes to check. balances: string[] description: A list of balances corresponding to each root hash. Outputs: Array: description: An array of relevant metadata for a user's claims. properties: rootHash: string description: The relevant root hash. claimed: boolean description: True if the root hash has been claimed. balance: string description: The balance of the reward at the root hash. ``` -------------------------------- ### APIDOC: `depositWithPermit` function signature and parameters Source: https://github.com/se7en-seas/boring-vault-ui/blob/main/docs/content/docs/deposits.mdx Documents the `depositWithPermit` function, detailing its required `signer`, `depositAmount`, `selectedToken` inputs, optional `initialDeadline`, and its return of a `DepositStatus` object. ```APIDOC depositWithPermit(signer: ethers.JsonRPCSigner, depositAmount: string, selectedToken: object, initialDeadline?: number): Promise signer: an ethers JsonRPCSigner. depositAmount: a decimal adjusted (human readable) string that represents the amount of selectedTokens the user wants to deposit into the vault. selectedToken: the token a user wants to deposit in the format address: token contract address decimals: decimal precision of the token initialDeadline: Unix timestamp (in seconds) for the permit's deadline. Defaults to now + 15 minutes. ``` -------------------------------- ### requestOnChainWithdrawWithPermit Function Inputs Source: https://github.com/se7en-seas/boring-vault-ui/blob/main/docs/content/docs/boring-queue-ui-integration.mdx Defines the required input parameters for the `requestOnChainWithdrawWithPermit` function, including the token address to withdraw, the amount of shares, the discount applied, and deadlines for both the request validity and the permit expiration. ```APIDOC assetOut (string): the address of the token amountOfShares (uint128): the amount of shares the user wants to withdraw in the base denom of the vault discount (uint16): the discount to apply to the withdraw in bps adjusted to 5 decimals (e.g. 1% = 10000) secondsToDeadline (uint24): the time in seconds the request is valid for after it is available to solve permitDeadline (uint256): the unix second deadline at which the permit expires ``` -------------------------------- ### Queue a Withdrawal with BoringVault SDK (TypeScript) Source: https://github.com/se7en-seas/boring-vault-ui/blob/main/docs/content/docs/solana-vault-integration.mdx Demonstrates how to queue a withdrawal using the vaultSDK.queueBoringWithdraw method. It covers essential parameters like wallet, vault ID, token output, share amount, discount percentage, and deadline, along with robust error handling for transaction failures. ```tsx async function queueWithdrawal() { const wallet = /* your wallet */; const vaultId = 1; const tokenOut = 'J1toso1uCk3RLmjorhTtrVwY9HJ7X8V9yYac6Y7kGCPn'; // jitoSOL const shareAmount = 0.5; // Human-readable amount (0.5 shares) const discountPercent = 2.5; // 2.5% discount for solvers const secondsToDeadline = 86400 * 7; // 7 days try { const signature = await vaultSDK.queueBoringWithdraw( wallet, vaultId, tokenOut, shareAmount, discountPercent, secondsToDeadline, { skipPreflight: false, maxRetries: 30 } ); console.log(`Withdrawal queued! Transaction: ${signature}`); console.log(`View on explorer: https://solscan.io/tx/${signature}`); return signature; } catch (error) { console.error('Queue withdrawal failed:', error); throw error; } } ``` -------------------------------- ### Accessing Constants in Boring Vault SDK Source: https://github.com/se7en-seas/boring-vault-ui/blob/main/docs/content/docs/solana-vault-integration.mdx Shows how to import and use predefined constants provided by the Boring Vault SDK, such as program IDs, mint addresses, and default decimals, useful for Solana operations. ```tsx import { BORING_VAULT_PROGRAM_ID, BORING_QUEUE_PROGRAM_ID, JITO_SOL_MINT_ADDRESS, TOKEN_2022_PROGRAM_ID, DEFAULT_DECIMALS } from 'boring-vault-ui'; console.log('Boring Vault Program:', BORING_VAULT_PROGRAM_ID); console.log('Boring Queue Program:', BORING_QUEUE_PROGRAM_ID); console.log('JitoSOL Mint:', JITO_SOL_MINT_ADDRESS); console.log('Default Decimals:', DEFAULT_DECIMALS); ``` -------------------------------- ### Crank Pyth Oracle for JitoSOL/SOL Price Update (TypeScript/Solana) Source: https://github.com/se7en-seas/boring-vault-ui/blob/main/docs/content/docs/solana-vault-integration.mdx This code snippet demonstrates how to build and execute transactions to crank the Pyth oracle for the JitoSOL/SOL price feed. It uses `buildPythOracleCrankTransactions` from `boring-vault-ui/solana` to generate the necessary transactions, which are then signed and sent to the Solana network. This ensures the price data is up-to-date before critical operations. ```tsx import { buildPythOracleCrankTransactions } from 'boring-vault-ui/solana/'; import { JITOSOL_SOL_PYTH_FEED } from 'boring-vault-ui'; const { transactions, signers } = await buildPythOracleCrankTransactions( connection, payer.publicKey, [JITOSOL_SOL_PYTH_FEED] ); for (let i = 0; i < transactions.length; i++) { transactions[i].sign(...signers[i], keypair); await connection.sendRawTransaction(transactions[i].serialize()); } ``` -------------------------------- ### Fetch User Shares in Boring Vault Source: https://github.com/se7en-seas/boring-vault-ui/blob/main/docs/content/docs/user-metadata.mdx This function retrieves the decimal-adjusted numerical value of vault shares owned by a user. It requires the user's wallet address as input and returns a promise resolving to the total human-readable shares. The example demonstrates its usage with React's `useState` and `useEffect` hooks, ensuring the Boring Vault context is ready before fetching data. ```tsx import { useState, useEffect } from "react"; import { useBoringVaultV1 } from 'boring-vault-ui'; const [userShares, setUserShares] = useState(null); const { isBoringV1ContextReady, fetchUserShares } = useBoringVaultV1(); useEffect(() => { if (!isBoringV1ContextReady) { console.warn("Boring Vault Context is not ready"); return; } fetchUserShares('0x...').then(setUserShares); }, [isBoringV1ContextReady]); if (userShares) { console.log("The user's shares: ", userShares); } ``` -------------------------------- ### API Documentation for queueWithdraw Function Source: https://github.com/se7en-seas/boring-vault-ui/blob/main/docs/content/docs/withdraw-queue.mdx Details the parameters and return type for the `queueWithdraw` function. It outlines the required inputs such as signer, amount, token details, discount, and validity period, and describes the structure of the `WithdrawStatus` promise returned upon completion. ```APIDOC queueWithdraw(signer: ethers.JsonRPCSigner, amountHumanReadable: string, tokenOut: { address: string, decimals: number }, discountPercent: string, daysValid: string): Promise Inputs: - signer: an ethers JsonRPCSigner. - amountHumanReadable: a decimal adjusted (human readable) string that represents the amount of vault shares a user wants to withdraw. - tokenOut: the token the user wants to receive. - address: token contract address. - decimals: decimal precision of the token. - discountPercent: a human readable percent (e.g. 1 = 1%) as a string that represents the max discount from the share price the user is willing to accept. - daysValid: a string indicating how many days the request should be valid from the moment the request is submitted (1 = 1 day). Outputs: - Promise: - initiated: boolean representing if the withdraw function has been called and is in progress of being executed. - loading: boolean representing if there is a relevant withdraw transaction ongoing. - success (optional): boolean representing if the withdraw intent action succeeded. - error (optional): string representing why a withdraw failed. - tx_hash (optional): the string of a successful withdraw transaction hash. ``` -------------------------------- ### APIDOC: `deposit` function signature and parameters Source: https://github.com/se7en-seas/boring-vault-ui/blob/main/docs/content/docs/deposits.mdx Documents the `deposit` function, detailing its required `signer`, `depositAmount`, and `selectedToken` inputs, and its return of a `DepositStatus` object. ```APIDOC deposit(signer: ethers.JsonRPCSigner, depositAmount: string, selectedToken: object): Promise signer: an ethers JsonRPCSigner. depositAmount: a decimal adjusted (human readable) string that represents the amount of selectedTokens the user wants to deposit into the vault. selectedToken: the token a user wants to deposit in the format address: token contract address decimals: decimal precision of the token ``` -------------------------------- ### API Documentation for withdrawQueueCancel Function Source: https://github.com/se7en-seas/boring-vault-ui/blob/main/docs/content/docs/withdraw-queue.mdx Details the parameters and return type for the `withdrawQueueCancel` function. It outlines the required inputs such as signer and token details, and describes the structure of the `WithdrawStatus` promise returned upon completion. ```APIDOC withdrawQueueCancel(signer: ethers.JsonRPCSigner, tokenOut: { address: string, decimals: number }): Promise Inputs: - signer: an ethers JsonRPCSigner. - tokenOut: the output token to cancel the request for. - address: token contract address. - decimals: decimal precision of the token. Outputs: - Promise: - initiated: boolean representing if the withdraw function has been called and is in progress of being executed. - loading: boolean representing if there is a relevant withdraw transaction ongoing. - success (optional): boolean representing if the withdraw intent action succeeded. - error (optional): string representing why a withdraw failed. - tx_hash (optional): the string of a successful withdraw transaction hash. ``` -------------------------------- ### TransactionOptions Interface for Boring Vault SDK Source: https://github.com/se7en-seas/boring-vault-ui/blob/main/docs/content/docs/solana-vault-integration.mdx Documents the `TransactionOptions` interface, which defines optional parameters for all transaction methods in the Boring Vault SDK, including `skipPreflight`, `maxRetries`, and `skipStatusCheck`. ```APIDOC interface TransactionOptions: skipPreflight?: boolean Description: Skip transaction simulation (default: false) maxRetries?: number Description: Maximum retry attempts (default: 30) skipStatusCheck?: boolean Description: Skip status polling (default: false) ``` -------------------------------- ### API: fetchBoringQueueAssetParams Function Source: https://github.com/se7en-seas/boring-vault-ui/blob/main/docs/content/docs/boring-queue.mdx API documentation for `fetchBoringQueueAssetParams`, a function that returns the boring queue parameters for a specified asset. It details the required input (token address and decimals) and the structure of the `BoringQueueAssetParams` object returned, including withdrawal allowances, maturity times, discount ranges, and minimum share requirements. ```APIDOC fetchBoringQueueAssetParams(token: object): Promise Inputs: token: object address: string (token contract address) decimals: number (decimal precision of the token) Outputs: Promise: A promise that returns a BoringQueueAssetParams object. allowWithdraws: boolean (if asset is allowed to be requested out) secondsToMaturity: number (seconds until withdraw can be fulfilled) minimumSecondsToDeadline: number (seconds after maturity withdraw remains valid) minDiscount: number (minimum discount under set share price) maxDiscount: number (maximum discount under set share price) minimumShares: number (minimum vault shares required) Output Object Structure: { allowWithdraws: rawAssetParams[0], secondsToMaturity: Number(rawAssetParams[1]), minimumSecondsToDeadline: Number(rawAssetParams[2]), minDiscount: Number(rawAssetParams[3]), maxDiscount: Number(rawAssetParams[4]), minimumShares: Number(rawAssetParams[5]) } ``` -------------------------------- ### Deposit SPL Tokens into Vault Source: https://github.com/se7en-seas/boring-vault-ui/blob/main/docs/content/docs/solana-vault-integration.mdx Illustrates how to deposit a specified amount of SPL tokens into a vault using a wallet or keypair. This function requires the vault ID, token mint address, deposit amount, and a minimum expected mint amount for slippage control. It also demonstrates how to handle transaction options and provides a link to the transaction on Solscan. ```tsx import { web3 } from '@coral-xyz/anchor'; async function depositTokens() { // Your wallet (can be wallet adapter or keypair) const wallet = { publicKey: new web3.PublicKey('user_wallet_address'), signTransaction: async (tx: web3.Transaction) => { // Wallet adapter signing logic return signedTransaction; } }; // Or use a keypair directly // const wallet = web3.Keypair.fromSecretKey(secretKey); const vaultId = 1; const tokenMint = 'J1toso1uCk3RLmjorhTtrVwY9HJ7X8V9yYac6Y7kGCPn'; // jitoSOL const depositAmount = BigInt('1000000000'); // 1 token (with 9 decimals) const minMintAmount = BigInt('950000000'); // 5% slippage tolerance try { const signature = await vaultSDK.deposit( wallet, vaultId, tokenMint, depositAmount, minMintAmount, { skipPreflight: false, maxRetries: 30 } ); console.log(`Deposit successful! Transaction: ${signature}`); console.log(`View on explorer: https://solscan.io/tx/${signature}`); return signature; } catch (error) { console.error('Deposit failed:', error); throw error; } } ```