For Integration Partners - Start Here

This guide will help you quickly integrate Vault into your application.

What you’re building

A lightweight frontend that lets your users:

  • View vault information (TVL, share value)
  • See their position (shares, value, unlock timer)
  • Supply supported assets to the vault
  • Request and complete delayed withdrawals (T+1 to T+5 business days)

Use the React Provider + hooks defined below. Raw ABI reads via wagmi/viem are fine, but the Provider path is the recommended/maintained interface.

What we provide

  • Contract set (per vault)

    • vaultContract (BoringVault)
    • tellerContract (TellerWithMultiAssetSupport)
    • accountantContract (AccountantWithRateProviders)
    • lensContract (read batching)
  • Configuration

    • depositTokens: [{ address, decimals }]
    • baseToken: { address, decimals }
    • vaultDecimals: number
  • Allowlist/KYC flag (for gated vaults) – you’ll get a simple check to call before enabling supply.

  • Support – real-time channel with the Coinchange engineering team.

See Contract Addresses for live networks and share-lock settings.

Recommended architecture

  • Provider (required): BoringVaultV1Provider wrapping your app
  • Hooks (required): useBoringVaultV1
  • Web3: wagmi/viem for wallet connection (you’ll bridge to an Ethers v6 signer for writes)
  • State: your choice (React Query, Zustand, etc.)
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:"0xToken...", decimals:18 }]}
  baseToken={{ address:"0xBase...", decimals:18 }}
  vaultDecimals={18}
>
  {/* your app */}
</BoringVaultV1Provider>

Core SDK surface

Readiness

const { isBoringV1ContextReady } = useBoringVaultV1();

Vault reads (no wallet)

const { fetchTotalAssets, fetchShareValue } = useBoringVaultV1();
// returns human-readable strings

User reads (wallet)

const { fetchUserShares, fetchUserUnlockTime } = useBoringVaultV1();
// shares (HR), unlock time (unix seconds)

Supply (deposit) – positional args

const { deposit, depositStatus } = useBoringVaultV1();
// deposit(signer, depositAmountHr, { address, decimals })
await deposit(signer, "1.25", { address:"0xToken...", decimals:18 });
// depositStatus: { initiated, loading, success?, error?, tx_hash? }

Delayed withdrawals – lifecycle (positional args)

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

// 1) request
await delayWithdraw(
  signer,
  "10.0",                                 // shareAmount (HR)
  { address:"0xTokenOut...", decimals:18 },// tokenOut
  "1",                                     // maxLoss (%) as string
  false                                    // thirdPartyClaimer
);

// 2) list active intents
const pending = await delayWithdrawStatuses(signer);
// entries: { allowThirdPartyToComplete, maxLoss, maturity, shares, exchangeRateAtTimeOfRequest, token { address, decimals } }

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

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

// withdrawStatus mirrors request/cancel/complete: { initiated, loading, success?, error?, tx_hash? }

Signer (viem → Ethers)

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

Product rules to implement

  • T+1 to T+5 business days: surface the expected processing window in your UI and enable Complete only after maturity.
  • Share-lock: respect fetchUserUnlockTime before enabling transfers/withdraws.
  • Allowlist (if enabled): block supply for non-allowed wallets and display a friendly “Contact support to enable access.”
  • Decimals & rates: use SDK helpers for rate math; do not hand-roll conversions.
  • Status UX: always reflect { initiated, loading, success, error, tx_hash } for deposit/withdraw flows.

Security & compliance checklist

  • Validate amounts and addresses (no negatives, NaN, or zero amounts).
  • Never request unlimited approvals by default; request the exact amount when possible.
  • Confirm network and chainId before writes.
  • Compute a minimum-mint buffer for deposits (SDK helpers do this for you).
  • Provide clear error messages and recovery actions (e.g., insufficient balance, approval rejected).
  • Positioning: “No guarantee of returns, rewards are variable and derived from blockchain protocol incentives and CeFi/DeFi strategies on CEX/DEX infrastructure.”

Acceptance criteria (ready for go-live)

  • isBoringV1ContextReady() gates the app before any reads/writes.
  • TVL and share value display correctly and auto-refresh.
  • User shares and unlock timer render with connected wallet.
  • Supply flow completes with accurate depositStatus.
  • Delayed withdraw: request → list → cancel → complete flows work with correct withdrawStatus.
  • Allowlist/lock checks enforced; error states localized and user-friendly.