Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
57 changes: 51 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,56 @@
# Bloom Docs
<p align="center">
<img src="public/bloom-mark.svg" alt="Bloom" width="96">
</p>

Vocs-powered documentation site for Bloom, configured for Cloudflare Pages.
<h1 align="center">Bloom Docs</h1>

<p align="center">
User-facing documentation for Bloom, the agentic Ethereum wallet mounted as a virtual filesystem.
</p>

<p align="center">
<a href="https://github.com/bloom-directory/docs/actions/workflows/ci.yml"><img alt="CI" src="https://img.shields.io/github/actions/workflow/status/bloom-directory/docs/ci.yml?branch=master&style=flat-square&label=ci"></a>
<a href="https://docs.bloom.directory"><img alt="Live docs" src="https://img.shields.io/badge/docs-live-141310?style=flat-square"></a>
<a href="https://bloom.directory"><img alt="Bloom website" src="https://img.shields.io/badge/bloom-directory-a8324c?style=flat-square"></a>
</p>

<p align="center">
<a href="https://docs.bloom.directory"><strong>Read the docs</strong></a>
·
<a href="https://docs.bloom.directory/getting-started/quickstart"><strong>Quickstart</strong></a>
·
<a href="https://docs.bloom.directory/wallet/use-cases"><strong>Use cases</strong></a>
·
<a href="https://bloom.directory/SKILL.md"><strong>Agent setup skill</strong></a>
</p>

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
Expand Down Expand Up @@ -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.
7 changes: 7 additions & 0 deletions src/components/ExpectedOutput.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
type ExpectedOutputProps = {
children?: string
}

export function ExpectedOutput({ children = 'Expected output' }: ExpectedOutputProps) {
return <p className="bloom-expected-output">{children}</p>
}
33 changes: 33 additions & 0 deletions src/pages/_root.css
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
222 changes: 222 additions & 0 deletions src/pages/wallet/use-cases.mdx
Original file line number Diff line number Diff line change
@@ -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
```

<ExpectedOutput />

```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 .
```

<ExpectedOutput />

```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)'
```

<ExpectedOutput />

```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 .
```

<ExpectedOutput />

```text
# plan.md
Send <half the wallet balance> ETH to <treasury address> 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"
```

<ExpectedOutput />

```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"
```

<ExpectedOutput>Expected output: allowance already high enough</ExpectedOutput>

```text
Current allowance: 2500
Allowance is already above threshold; no transaction staged.
```

<ExpectedOutput>Expected output: top-up staged</ExpectedOutput>

```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.
3 changes: 2 additions & 1 deletion vocs.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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: '/' },
Expand All @@ -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' },
Expand Down
Loading