Frontend Integration Reference

This guide provides information for integrating Vault into frontend applications.

1) Provider

BoringVaultV1Provider (required)

Props (exact names):

  • vaultContract: string
  • tellerContract: string
  • accountantContract: string
  • lensContract: string
  • ethersProvider: EthersProvider
  • depositTokens: Array<{ address: string; decimals: number }>
  • baseToken: { address: string; decimals: number }
  • vaultDecimals: number

Example:

import { BoringVaultV1Provider } from 'boring-vault-ui'
import { JsonRpcProvider } from 'ethers'

<BoringVaultV1Provider
  vaultContract="0x..."
  tellerContract="0x..."
  accountantContract="0x..."
  lensContract="0x..."
  ethersProvider={new JsonRpcProvider(process.env.NEXT_PUBLIC_RPC)}
  depositTokens={[
    { address: "0xC02aaA...", decimals: 18 },
    { address: "0xa0b869...", decimals: 6 }
  ]}
  baseToken={{ address: "0xC02aaA...", decimals: 18 }}
  vaultDecimals={18}
>
  {/* your app */}
</BoringVaultV1Provider>

2) Readiness

isBoringV1ContextReady(): boolean

Use this to gate all reads/writes.

import { useBoringVaultV1 } from 'boring-vault-ui'

const { isBoringV1ContextReady } = useBoringVaultV1()
if (!isBoringV1ContextReady()) return <div>Loading…</div>

3) Vault reads (no wallet)

fetchTotalAssets(): Promise<number>

Human-readable TVL in base token units.

const { isBoringV1ContextReady, fetchTotalAssets } = useBoringVaultV1()
if (isBoringV1ContextReady()) {
  const tvl = await fetchTotalAssets()
}

fetchShareValue(): Promise<number>

Human-readable value of 1 share in the base token.

const { isBoringV1ContextReady, fetchShareValue } = useBoringVaultV1()
if (isBoringV1ContextReady()) {
  const oneShareValue = await fetchShareValue()
}

4) User reads (wallet)

fetchUserShares(userAddress): Promise<number>

Human-readable share balance.

const { fetchUserShares } = useBoringVaultV1()
const shares = await fetchUserShares('0xUser...')

fetchUserUnlockTime(userAddress): Promise<number>

Unix timestamp for share unlock.

const { fetchUserUnlockTime } = useBoringVaultV1()
const unlockTs = await fetchUserUnlockTime('0xUser...')

5) Writes — Supply (Deposit)

deposit(signer, depositAmount, selectedToken): Promise<TxStatus>

  • depositAmount: human-readable string (e.g., "1.25")
  • selectedToken: { address, decimals }
const { deposit, depositStatus } = useBoringVaultV1()
await deposit(signer, "1.25", { address: "0xToken...", decimals: 18 })
// depositStatus: { initiated, loading, success?, error?, tx_hash? }

6) Writes — Delayed Withdrawals (T+1 to T+5 business days)

Lifecycle: request → list/view → cancel (optional) → complete (after maturity).

const {
  delayWithdraw,
  delayWithdrawStatuses,
  delayWithdrawCancel,
  delayWithdrawComplete,
  withdrawStatus
} = useBoringVaultV1()

// request
await delayWithdraw(
  signer,
  "10.0",
  { address: "0xTokenOut...", decimals: 18 },
  "1",
  false
)

// list active
const pending = await delayWithdrawStatuses(signer)

// cancel
await delayWithdrawCancel(signer, { address: "0xTokenOut...", decimals: 18 })

// complete — only after maturity
await delayWithdrawComplete(signer, { address: "0xTokenOut...", decimals: 18 })

7) Signer (if starting from viem)

import { BrowserProvider } from 'ethers'
// viemWalletClient is your app's instance
const ethersProvider = new BrowserProvider(viemWalletClient.transport)
const signer = await ethersProvider.getSigner()

8) Product rules (must-implement)

  • Gate on isBoringV1ContextReady().
  • Respect share-lock via fetchUserUnlockTime.
  • Treat delayed withdrawals as T+1 to T+5 business days; only enable Complete after maturity.
  • Use SDK helpers for decimals/rates; don’t hand-roll conversions.
  • Surface status objects for all actions: { initiated, loading, success?, error?, tx_hash? }.

API Surface (Canonical) (Corrected)

This page is the single source of truth for names, signatures, and return shapes. Positioning: technology & liquidity infrastructure; no guarantee of returns.

Provider

BoringVaultV1Provider (required)

Props:

  • vaultContract: string
  • tellerContract: string
  • accountantContract: string
  • lensContract: string
  • ethersProvider: EthersProvider
  • depositTokens: Array<{ address: string; decimals: number }>
  • baseToken: { address: string; decimals: number }
  • vaultDecimals: number
<BoringVaultV1Provider
  vaultContract="0x..."
  tellerContract="0x..."
  accountantContract="0x..."
  lensContract="0x..."
  ethersProvider={ethersProvider}
  depositTokens={[{ address:"0x...", decimals:18 }]}
  baseToken={{ address:"0x...", decimals:18 }}
  vaultDecimals={18}
>
  {/* app */}
</BoringVaultV1Provider>

Hook

useBoringVaultV1()

Readiness

isBoringV1ContextReady(): boolean

Vault reads

fetchTotalAssets(): Promise<number>  // human-readable in baseToken units
fetchShareValue():  Promise<number>  // value of 1 share in baseToken (HR)

User reads

fetchUserShares(userAddress: string):     Promise<number>  // HR shares
fetchUserUnlockTime(userAddress: string): Promise<number>  // unix seconds

Writes & Status

Status object (all writes)

type TxStatus = {
  initiated: boolean
  loading:   boolean
  success?:  boolean
  error?:    string
  tx_hash?:  string
}

Supply (Deposit)

deposit(
  signer: JsonRpcSigner,
  depositAmount: string,                            // human-readable
  selectedToken: { address: string; decimals: number }
): Promise<TxStatus>

Delayed Withdrawals

delayWithdraw(
  signer: JsonRpcSigner,
  shareAmount: string,                              // human-readable
  tokenOut: { address: string; decimals: number },
  maxLoss: string,                                  // percent as string ("1" => 1%)
  thirdPartyClaimer: boolean
): Promise<TxStatus>

type DelayWithdrawEntry = {
  allowThirdPartyToComplete: boolean
  maxLoss: number
  maturity: number
  shares: string
  exchangeRateAtTimeOfRequest: string
  token: { address: string; decimals: number }
}

delayWithdrawStatuses(signer: JsonRpcSigner): Promise<DelayWithdrawEntry[]>

delayWithdrawCancel(
  signer: JsonRpcSigner,
  tokenOut: { address: string; decimals: number }
): Promise<TxStatus>

delayWithdrawComplete(
  signer: JsonRpcSigner,
  tokenOut: { address: string; decimals: number }
): Promise<TxStatus>

Signer (from viem)

import { BrowserProvider } from 'ethers'
const ethersProvider = new BrowserProvider(viemWalletClient.transport)
const signer = await ethersProvider.getSigner()

Product Rules

  • Gate everything on isBoringV1ContextReady().
  • Honor share-lock via fetchUserUnlockTime.
  • Delayed withdraws: T+1 to T+5 business days; complete only after maturity.
  • Use SDK helpers for decimals/rates.
  • Always reflect TxStatus in UI.

What’s Next