Vocs Documentation Framework

repository·main·Indexed 23 days ago

https://github.com/wevm/vocs

A portable, high-performance documentation framework powered by Vite. Vocs provides a flexible foundation for building documentation sites, featuring a scaffolding tool via `create-vocs` and support for interactive project initialization.

Tokens
377.6K
Snippets
1.2K
Records
1.7K
Agent score
81%

What's inside Vocs

  1. Overview of EIP-7702

    main

    EIP-7702 introduces a new transaction type that allows an Externally Owned Account (EOA) to designate a Smart Contract as its "implementation". This is achieved through an "authorization list" property within the transaction, which contains a set of (chain_id, contract_address, nonce, y_parity, r, s) tuples. These tuples define which contracts are delegated to the EOA.

    Key use cases for EIP-7702 include:

    • Batching: Executing multiple operations (e.g., an ERC-20 approval followed by a spend) in a single atomic transaction.
    • Sponsorship: Allowing one account to pay for transactions on behalf of another account.
    • Privilege de-escalation: Enabling users to sign sub-keys with restricted permissions (e.g., permission to spend specific tokens but not ETH, or limiting spending to a certain percentage of the balance).
  2. What is Vocs

    main

    Vocs is a lightweight documentation framework designed for dual consumption: humans navigating via a browser and AI agents consuming content programmatically.

    It optimizes for:

    • Human Experience: Rich, interactive pages using React and MDX, powered by Vite and Waku.
    • Agent Experience: Lightweight, structured outputs like Markdown routes, llms.txt, and Model Context Protocol (MCP) interfaces to minimize token usage and maximize retrieval accuracy.

    Key characteristics include:

    • Source Format: Simple Markdown and MDX.
    • Performance: Fast development loops and static generation support.
    • Maintainability: Documentation stays in the project files alongside source code, allowing agents to inspect, edit, and review documentation changes just like code.
  3. Overview of viem

    main

    viem is a TypeScript interface for Ethereum that provides low-level, stateless primitives for interacting with the blockchain. It is designed as a high-performance, reliable, and tree-shakable alternative to libraries like ethers.js and web3.js.

    Key characteristics include:

    • Modular & Composable: APIs are designed as building blocks that are easy to move, change, or remove.
    • Strongly Typed: Provides automatic type safety, inference, and autocomplete for Ethereum concepts.
    • Tree-shakable: Only the specific modules you import are included in your final bundle, minimizing bundle size.
    • Stateless Primitives: Focuses on reliability and efficiency by avoiding heavy internal state.
    • High Performance: Uses optimized encoding/parsing algorithms and defers heavy asynchronous tasks until required.
  4. What is a WebAuthn Account?

    main

    A WebAuthn Account is a specialized account type used primarily as an owner for Smart Accounts. It is similar to a Local Account but has specific technical constraints and capabilities:

    • Signature Curve: Uses the secp256r1 curve.
    • Output: Signing methods return both a signature and webauthn data.
    • Limitations: It cannot sign transactions directly because transactions do not support secp256r1 signatures.
    • Identity: It does not have a standard Ethereum address.

    WebAuthn Accounts are intended to sign User Operations and messages on behalf of a Smart Account rather than interacting with the blockchain directly.

  5. What is a JSON-RPC Account

    main
    A JSON-RPC Account is a type of Account where the signing keys are not held locally by the application. Instead, signing operations for transactions and messages are deferred to an external Wallet via the JSON-RPC protocol. This pattern is commonly used to interact with Browser Extension Wallets (like MetaMask via window.ethereum) or Mobile Wallets (via WalletConnect).
  6. Overview of Vocs theming layers

    main

    Vocs uses a two-layer theming model to allow for both high-level configuration and granular visual control:

    1. Site Configuration (vocs.config.ts): Used for high-level branding and structural settings such as accentColor, colorScheme, logoUrl, iconUrl, and codeHighlight.themes.
    2. Global CSS (src/pages/_root.css): Used for low-level visual styling, including custom fonts, surface colors, spacing, and overriding default CSS variables.

    A standard workflow involves configuring branding in the site config first, then using _root.css for typography and fine-tuning layout or colors via CSS variables.

  7. Use strict mode in getLogs to ensure argument presence

    main

    By default, getLogs includes logs that might not fully conform to the provided args (meaning some arguments in the returned Log might be undefined).

    To ensure that args are always defined and that only logs strictly conforming to the provided arguments are returned, set strict: true. This acts as a filter that removes non-conforming logs.

    import { parseAbiItem } from 'viem' 
    
    const logs = await publicClient.getLogs({
      address: '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48',
      event: parseAbiItem('event Transfer(address indexed from, address indexed to, uint256 value)'),
      strict: true
    })
    
    // With strict: true, logs[0].args is guaranteed to be defined
  8. Enable Type Inference for ABIs and EIP-712

    main

    viem provides end-to-end type safety (autocomplete, argument validation, etc.) by inferring types from ABIs and EIP-712 definitions.

    To enable this, you must either:

    1. Use a const assertion (as const) on your ABI object.
    2. Define the ABI inline within the function call.

    Note on JSON: TypeScript does not support importing .json files as const. If you are importing ABIs from JSON files, consider using tools like @wagmi/cli to resolve them.

    import { createPublicClient, http } from 'viem'
    
    const client = createPublicClient({ transport: http() })
    
    // Option 1: Using a const assertion
    const abi = [{
      type: 'function',
      name: 'balanceOf',
      stateMutability: 'view',
      inputs: [{ type: 'address' }],
      outputs: [{ type: 'uint256' }],
    }] as const
    
    const result = client.readContract({
      address: '0x27a69ffba1e939ddcfecc8c7e0f967b872bac65c',
      abi,
      functionName: 'balanceOf',
      args: ['0xa5cc3c03994DB5b0d9A5eEdD10CabaB0813678AC']
    })
    
    // Option 2: Defining inline
    const resultInline = client.readContract({
      address: '0x27a69ffba1e939ddcfecc8c7e0f967b872bac65c',
      abi: [{
        type: 'function',
        name: 'balanceOf',
        stateMutability: 'view',
        inputs: [{ type: 'address' }],
        outputs: [{ type: 'uint256' }],
      }],
      functionName: 'balanceOf',
      args: ['0xa5cc3c03994DB5b0d9A5eEdD10CabaB0813678AC']
    })
  9. Supported MDX elements in Vocs

    main

    Vocs supports standard Markdown syntax along with MDX components and specialized callout syntax. This allows for rich documentation including headings, emphasis, lists, and custom components.

    Standard Markdown

    • Headings: Supports # through ######.
    • Emphasis:
      • Italics: *text* or _text_
      • Bold: **text** or __text__
      • Strikethrough: ~~text~~
    • Lists: Supports both ordered and unordered lists.
    • Links and Images: Standard Markdown syntax for [text](url) and ![alt](url).

    Callouts

    Vocs provides a specific syntax for callout blocks using triple colons (:::) followed by a type identifier. These are useful for highlighting specific types of information.

    Supported callout types:

    • :::note
    • :::info
    • :::warning
    • :::danger
    • :::tip
    • :::success

    MDX Components

    Since Vocs uses MDX, you can import and use React components directly within your .mdx files. For example, you can use the Link component from waku for client-side navigation.

    import { Link } from 'waku'
    
    # Title
    
    <Link to="/">Home</Link>
    
    :::note
    This is a note callout.
    :::
    
    :::warning
    This is a warning callout.
    :::
  10. What are Public Actions in viem

    main

    Public Actions are specialized functions in viem that map one-to-one with standard Ethereum RPC methods (such as eth_blockNumber or eth_getBalance). They are designed to be used with a Public Client to retrieve read-only data from the blockchain.

    Key characteristics:

    • No Permissions Required: They do not require user signatures or special permissions.
    • Read-Only: They do not provide signing capabilities and cannot be used to modify state on the blockchain.
    • Use Cases: Common tasks include retrieving account balances, fetching transaction receipts, or getting the current block number.
  11. Scope watchEvent by address, event, or arguments

    main

    You can narrow down the events watchEvent listens to using several scoping options:

    Address

    Scope to a specific contract address or a list of addresses.

    Event

    Scope to a specific event using an AbiEvent object or by using parseAbiItem to convert a human-readable signature into an ABI.

    Arguments

    Scope to specific indexed arguments of an event. You can provide a single value or an array of values (acting as an OR condition) for an argument.

    Note: If you scope to multiple events using the events property, you cannot use the args property.

    import { parseAbiItem, parseAbi } from 'viem'
    import { publicClient } from './client'
    
    // 1. Scoping by Address
    publicClient.watchEvent({
      address: '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48',
      onLogs: logs => console.log(logs)
    })
    
    // 2. Scoping by Event (using parseAbiItem)
    publicClient.watchEvent({
      address: '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48',
      event: parseAbiItem('event Transfer(address indexed from, address indexed to, uint256 value)'),
      onLogs: logs => console.log(logs)
    })
    
    // 3. Scoping by Indexed Arguments
    publicClient.watchEvent({
      address: '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48',
      event: parseAbiItem('event Transfer(address indexed from, address indexed to, uint256 value)'),
      args: {
        from: ['0xd8da6bf26964af9d7eed9e03e53415d37aa96045', '0xa5cc3c03994db5b0d9a5eedd10cabab0813678ac'],
      },
      onLogs: logs => console.log(logs)
    })
    
    // 4. Scoping to Multiple Events
    publicClient.watchEvent({
      events: parseAbi([
        'event Approval(address indexed owner, address indexed sender, uint256 value)',
        'event Transfer(address indexed from, address indexed to, uint256 value)',
      ]),
      onLogs: logs => console.log(logs)
    })