diff --git a/README.md b/README.md index efa8bd7..475d12c 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,56 @@ -# Bloom Docs +

+ Bloom +

-Vocs-powered documentation site for Bloom, configured for Cloudflare Pages. +

Bloom Docs

+ +

+ User-facing documentation for Bloom, the agentic Ethereum wallet mounted as a virtual filesystem. +

+ +

+ CI + Live docs + Bloom website +

+ +

+ Read the docs + · + Quickstart + · + Use cases + · + Agent setup skill +

+ +Bloom turns Ethereum into a directory your agent can inspect and write to with ordinary filesystem tools. Reads are onchain queries, writes are staged wallet intents, and every meaningful action leaves reviewable files behind. + +If you are here to use Bloom, start with the **[live docs](https://docs.bloom.directory)**. The docs cover setup, the mounted `/bloom` filesystem, wallet transaction review, policy controls, and power-user workflows that combine chain reads, encoding helpers, simulations, watches, and transaction staging. + +## What you can do with Bloom + +- Ask agents to query chain state without writing custom Web3 SDK glue. +- Read balances, blocks, gas, contract ABIs, method calls, events, ENS records, prices, and daemon status as files. +- Stage wallet actions by writing plain-language or structured intents, then inspect `plan.md` before confirmation. +- Pipe Bloom files through standard shell tools like `jq`, `awk`, `xargs`, `comm`, and `sort`. +- Use `/bloom/tools/` helpers for selectors, ABI/RLP/EIP-712 encoding, unit conversion, hashing, checksums, hex, and base64. +- Keep private keys out of the filesystem while still giving agents a safe, auditable operating surface. + +Bloom is **experimental, unaudited alpha software**. Treat docs examples as workflows to adapt and review, not as production financial advice. Never use funds you cannot afford to lose. + +## Useful links + +- **Live docs:** https://docs.bloom.directory +- **Bloom website:** https://bloom.directory +- **Bloom runtime repo:** https://github.com/bloom-directory/bloom +- **Docs repo:** https://github.com/bloom-directory/docs +- **Agent setup skill:** https://bloom.directory/SKILL.md ## Local development +This repository is the Vocs-powered documentation site for Bloom, configured for Cloudflare Pages. + ```sh npm install npm run dev @@ -39,9 +86,7 @@ Pages will create preview deployments automatically for pull requests when the P The docs are seeded from: -- Bloom wallet/VFS source docs in `../bloom` -- Existing docs content from this repository -- Product framing from `../pitch` -- Public website copy from `../website` +- Bloom wallet/VFS source docs in [`../bloom`](../bloom) +- Public website copy from [bloom.directory](https://bloom.directory) Do not copy secrets, private keys, RPC credentials, or unpublished operational details into this public docs site. diff --git a/src/components/ExpectedOutput.tsx b/src/components/ExpectedOutput.tsx new file mode 100644 index 0000000..5712aa0 --- /dev/null +++ b/src/components/ExpectedOutput.tsx @@ -0,0 +1,7 @@ +type ExpectedOutputProps = { + children?: string +} + +export function ExpectedOutput({ children = 'Expected output' }: ExpectedOutputProps) { + return

{children}

+} diff --git a/src/pages/_root.css b/src/pages/_root.css index 6c6eedd..96fb988 100644 --- a/src/pages/_root.css +++ b/src/pages/_root.css @@ -12,3 +12,36 @@ object-fit: contain; } } + +.bloom-expected-output { + display: inline-flex; + align-items: center; + gap: 0.45rem; + margin: 0.25rem 0 0; + border: 1px solid color-mix(in srgb, var(--vocs-color_border, #30363d) 72%, transparent); + border-bottom: 0; + border-radius: 0.65rem 0.65rem 0 0; + padding: 0.36rem 0.7rem 0.32rem; + background: color-mix(in srgb, var(--vocs-color_background2, #161b22) 88%, var(--vocs-color_background, #0d1117) 12%); + color: var(--vocs-color_text2, #8b949e); + font-family: var(--vocs-fontFamily_mono, ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace); + font-size: 0.75rem; + font-weight: 600; + letter-spacing: 0.02em; +} + +.bloom-expected-output::before { + content: ''; + width: 0.48rem; + height: 0.48rem; + border-radius: 999px; + background: var(--vocs-color_green, #22c55e); + box-shadow: + 0 0 0 1px color-mix(in srgb, var(--vocs-color_green, #22c55e) 45%, transparent), + 0 0 12px color-mix(in srgb, var(--vocs-color_green, #22c55e) 28%, transparent); +} + +.bloom-expected-output + div, +.bloom-expected-output + pre { + margin-top: 0 !important; +} diff --git a/src/pages/wallet/use-cases.mdx b/src/pages/wallet/use-cases.mdx new file mode 100644 index 0000000..8e9f9ad --- /dev/null +++ b/src/pages/wallet/use-cases.mdx @@ -0,0 +1,222 @@ +import { ExpectedOutput } from '../../components/ExpectedOutput' + +# Use cases + +Bloom’s filesystem model lets Ethereum power users compose chain reads, wallet state, encoding helpers, and transaction staging with ordinary shell tooling. The examples below assume Bloom is mounted at `/bloom` and that you review every generated plan before signing. + +## Compare live balances across chains + +Use Bloom paths as data sources and let GNU tools do the shaping: + +```sh +for chain in ethereum base arbitrum optimism; do + wei=$(cat "/bloom/chains/$chain/addresses/$ADDRESS/balance") + eth=$(cat "/bloom/tools/unit/format/$wei/eth") + printf '%-10s %s ETH\n' "$chain" "$eth" +done | sort -k2,2nr +``` + + + +```text +ethereum 1.284 ETH +base 0.420 ETH +arbitrum 0.137 ETH +optimism 0.052 ETH +``` + +That pattern is useful when you want an agent to answer “where is this wallet funded right now?” without teaching it chain-specific RPC calls. + +## Build calldata from contract metadata and tools + +Bloom can fetch contract ABI-backed method surfaces and Bloom tools can derive the same low-level primitives. You can inspect both before using the calldata anywhere side-effecting: + +```sh +TOKEN=0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48 # USDC +RECIPIENT=$(cat /bloom/tools/address/checksum/0xd8da6bf26964af9d7eed9e03e53415d37aa96045) +AMOUNT=$(cat /bloom/tools/unit/parse/25/6) + +cat /bloom/chains/ethereum/contracts/$TOKEN/methods/transfer.sig +printf '{"args":["%s","%s"]}\n' "$RECIPIENT" "$AMOUNT" \ + > /bloom/chains/ethereum/contracts/$TOKEN/methods/transfer.tx +cat /bloom/chains/ethereum/contracts/$TOKEN/methods/transfer.tx | jq . +``` + + + +```text +# /bloom/chains/ethereum/contracts/$TOKEN/methods/transfer.sig +transfer(address,uint256) -> 0xa9059cbb + +# /bloom/chains/ethereum/contracts/$TOKEN/methods/transfer.tx +{ + "to": "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", + "selector": "0xa9059cbb", + "calldata": "0xa9059cbb...", + "args": ["0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045", "25000000"] +} +``` + +For quick checks or ABI-less prep, helper files are enough: + +```sh +cat /bloom/tools/selector/'transfer(address,uint256)' +cat /bloom/tools/keccak/'Permit(address,address,uint256,uint256,uint8,bytes32,bytes32)' +``` + + + +```text +0xa9059cbb +0xaa0501e5e80cba255794aa8e245e2cf7b57401397d6837fd31fb38bbb8ca8a41 +``` + +## Read, transform, then stage a wallet intent + +Because writes are just files, a shell pipeline can query state, compute an amount, and stage a transaction while leaving the final decision to the review/confirm step: + +```sh +WALLET=alice +CHAIN=anvil +RECIPIENT=$(cat /bloom/addressbook/treasury) +BALANCE_WEI=$(cat /bloom/wallets/$WALLET/chains/$CHAIN/balance) +HALF_WEI=$(printf '%s\n' "$BALANCE_WEI" | awk '{ print int($1 / 2) }') +AMOUNT_ETH=$(cat /bloom/tools/unit/format/$HALF_WEI/eth) + +printf 'send %s eth to %s on %s\n' "$AMOUNT_ETH" "$RECIPIENT" "$CHAIN" \ + > /bloom/wallets/$WALLET/chains/$CHAIN/outbox/new.tx + +PENDING=$(ls -t /bloom/wallets/$WALLET/chains/$CHAIN/outbox/pending | head -n1) +cat "/bloom/wallets/$WALLET/chains/$CHAIN/outbox/pending/$PENDING/plan.md" +cat "/bloom/wallets/$WALLET/chains/$CHAIN/outbox/pending/$PENDING/policy_check.json" | jq . +``` + + + +```text +# plan.md +Send ETH to on anvil +Status: staged, not confirmed + +# policy_check.json +{ + "allowed": true, + "checks": [ + { "name": "spend_cap", "status": "pass" }, + { "name": "recipient", "status": "pass" } + ] +} +``` + +Nothing is confirmed by this pipeline. It creates a pending plan that a human or policy-aware agent can inspect before writing to `confirm` or calling the CLI confirmation flow. + +## Encode ABI input in a subshell + +Some tool helpers use write-then-read sessions so complex JSON does not have to fit inside a path. `mktemp` gives each shell invocation a unique Bloom tool session: + +```sh +session=$(basename "$(mktemp -u bloom-abi.XXXXXX)") +cat > "/bloom/tools/abi/encode/$session/in.json" <<'JSON' +{ + "sig": "transfer(address,uint256)", + "args": ["0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045", "1000000"] +} +JSON + +calldata=$(cat "/bloom/tools/abi/encode/$session/out.hex") +selector=$(cat /bloom/tools/selector/'transfer(address,uint256)') +printf 'selector=%s\ncalldata=%s\n' "$selector" "$calldata" +``` + + + +```text +selector=0xa9059cbb +calldata=0xa9059cbb000000000000000000000000d8da6bf26964af9d7eed9e03e53415d37aa9604500000000000000000000000000000000000000000000000000000000000f4240 +``` + +This is handy for scripts that need deterministic low-level calldata but still want Bloom to provide the crypto/ABI primitive as a file. + +## Full GNU shell script: watch allowance and stage a top-up + +The following script combines standard GNU utilities with Bloom files. It reads token metadata, queries an allowance, compares it to a threshold, uses `/bloom/tools/` in subshells, and stages an approval intent only when needed. + +```bash +#!/usr/bin/env bash +set -euo pipefail + +CHAIN=${CHAIN:-ethereum} +WALLET=${WALLET:-alice} +TOKEN=${TOKEN:-0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48} # USDC +SPENDER=${SPENDER:-0x111111125421cA6dc452d289314280a0f8842A65} +MIN_HUMAN=${MIN_HUMAN:-1000} +TARGET_HUMAN=${TARGET_HUMAN:-5000} + +extract_decoded_uint() { + # Pull the first integer from a Bloom method response's decoded array using GNU tr/sed. + tr -d '\n' | sed -n 's/.*"decoded"[[:space:]]*:[[:space:]]*\[[^0-9]*\([0-9][0-9]*\).*/\1/p' +} + +ge_uint() { + # Decimal unsigned integer comparison without overflowing shell arithmetic. + local a=${1#0} b=${2#0} + a=${a:-0}; b=${b:-0} + (( ${#a} > ${#b} )) || { (( ${#a} == ${#b} )) && [[ "$a" > "$b" || "$a" == "$b" ]]; } +} + +owner=$(cat "/bloom/wallets/$WALLET/address") +spender=$(cat "/bloom/tools/address/checksum/$SPENDER") +decimals=$(cat "/bloom/chains/$CHAIN/contracts/$TOKEN/methods/decimals.read" | extract_decoded_uint) + +min_raw=$(cat "/bloom/tools/unit/parse/$MIN_HUMAN/$decimals") +target_raw=$(cat "/bloom/tools/unit/parse/$TARGET_HUMAN/$decimals") + +printf '{"args":["%s","%s"]}\n' "$owner" "$spender" \ + > "/bloom/chains/$CHAIN/contracts/$TOKEN/methods/allowance.read" +allowance=$(cat "/bloom/chains/$CHAIN/contracts/$TOKEN/methods/allowance.read" | extract_decoded_uint) + +printf 'Current allowance: %s\n' "$(cat "/bloom/tools/unit/format/$allowance/$decimals")" + +if ge_uint "$allowance" "$min_raw"; then + echo "Allowance is already above threshold; no transaction staged." + exit 0 +fi + +session=$(basename "$(mktemp -u bloom-approve.XXXXXX)") +printf '{"sig":"approve(address,uint256)","args":["%s","%s"]}\n' \ + "$spender" "$target_raw" \ + > "/bloom/tools/abi/encode/$session/in.json" +calldata=$(cat "/bloom/tools/abi/encode/$session/out.hex") + +printf '{"chain":"%s","to":"%s","data":"%s","value":"0","description":"approve spender up to %s units"}\n' \ + "$CHAIN" "$TOKEN" "$calldata" "$TARGET_HUMAN" \ + > "/bloom/wallets/$WALLET/chains/$CHAIN/outbox/new.tx" + +pending=$(ls -t "/bloom/wallets/$WALLET/chains/$CHAIN/outbox/pending" | head -n1) +echo "Staged approval intent: $pending" +cat "/bloom/wallets/$WALLET/chains/$CHAIN/outbox/pending/$pending/plan.md" +``` + +Expected output: allowance already high enough + +```text +Current allowance: 2500 +Allowance is already above threshold; no transaction staged. +``` + +Expected output: top-up staged + +```text +Current allowance: 125 +Staged approval intent: 01J... + +# plan.md +# Transaction plan + +Chain: ethereum +To: 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48 +Action: approve spender up to 5000 units +Status: staged, not confirmed +``` + +The same pattern works for liquidation monitors, treasury rebalancing, batched allowance hygiene, post-deploy contract checks, or any workflow where you want normal Unix composition around a wallet that remains policy-gated. diff --git a/vocs.config.ts b/vocs.config.ts index bb38998..dd2a709 100644 --- a/vocs.config.ts +++ b/vocs.config.ts @@ -26,7 +26,7 @@ export default defineConfig({ ], topNav: [ { text: 'Website', link: 'https://bloom.directory' }, - { text: 'GitHub', link: 'https://github.com/bloom-directory/bloom' }, + { text: 'GitHub', link: 'https://github.com/bloom-directory/docs' }, ], sidebar: [ { text: 'Overview', link: '/' }, @@ -50,6 +50,7 @@ export default defineConfig({ items: [ { text: 'Filesystem guide', link: '/wallet/filesystem-guide' }, { text: 'Wallets and transactions', link: '/wallet/wallets-and-transactions' }, + { text: 'Use cases', link: '/wallet/use-cases' }, { text: 'DeFi intents', link: '/wallet/defi-intents' }, { text: 'Watches and simulation', link: '/wallet/watches-and-simulation' }, { text: 'Security model', link: '/wallet/security-model' },