# Treechat for HTML ordinals

An HTML ordinal shown on Treechat runs in a frame inside the Treechat page. It can talk to that page over `postMessage`: learn where it is, find out who is viewing it, show the Treechat names and avatars behind Bitcoin addresses, open profiles, and ask the viewer's Treechat wallet to pay. No API key or server is involved; the ordinal and Treechat speak directly in the viewer's browser.

It works for every viewer signed in to Treechat. Signed out, the ordinal still loads and gets its context; calls that need an account (names, Connect, payments) answer with an error.

## Quick start

1. Download the client library: https://treechat.com/treechat-ordinal.js (one file, no dependencies, about 8 KB).
2. Paste it into your ordinal's HTML as a module script, or keep it as a separate module if your build bundles one in.
3. Use it:

```html
<script type="module">
    // paste treechat-ordinal.js here, or bundle it in
    const context = await treechat.context()
    if (!context) {
        // not running inside Treechat
    } else if (await treechat.supports('getUsers')) {
        const users = await treechat.users(['1BoatSLRHtKNngkdXEeobR76b53LETtpyT'])
        // { '1Boat…': { username, avatarUrl } } or null for an address with no account
    }
</script>
```

Inline the library rather than loading it from a URL: an inscription lasts, and no other address is sure to serve the same file later.

## What you can call

| Call | Returns | Asks the viewer |
| --- | --- | --- |
| `treechat.context()` | `{ version, capabilities, ordinal, creator, owner, viewerIsOwner, post, theme }`, or `null` outside Treechat | No |
| `treechat.supports(name)` | Whether this Treechat answers a call, from `capabilities` | No |
| `treechat.viewer()` | `{ username, avatarUrl, identityKey, paymentAddress }` | Yes: Connect, once per ordinal per visit |
| `treechat.users(addresses)` | `{ [address]: { username, avatarUrl } \| null }` | No |
| `treechat.openProfile(username)` | Opens that Treechat profile beside the post | No |
| `treechat.openPost()` | Opens the post the ordinal is in | No |
| `treechat.wallet()` | A BRC-100 wallet (see below) | Yes: every payment |

Failed calls reject with a `TreechatError` that carries Treechat's message and a BRC-100 error `code`.

### context()

- `version`: 2 in the current Treechat. `capabilities` lists the calls it answers: `getContext`, `getViewer`, `getUsers`, `openProfile`, `openPost`. Check `supports()` before calling anything newer than `getViewer`.
- `ordinal.origin`: your ordinal's origin outpoint (`<txid>_<vout>`).
- `creator` and `owner`: `{ username, address }`, either part `null` when unknown.
- `viewerIsOwner`: `null` until the viewer connects, then `true` or `false`.
- `post`: `{ answerId, threadId }` of the Treechat post showing the ordinal, or `null`.
- `theme`: `light` or `dark`.

### users(addresses)

Names the Treechat accounts behind payment addresses: only public profile fields, so the viewer isn't asked. An address no single account claims maps to `null`. The library sends 50 addresses per request, and Treechat remembers each answer for the visit. Each ordinal can look up 500 distinct addresses per visit. Use it to put names and faces on the people in your ordinal's own on-chain history.

### openProfile(username) and openPost()

`openProfile` opens only usernames your ordinal was shown: from `users()`, from `viewer()`, or the context's creator or owner. An ordinal can open one panel every 2 seconds. A fullscreen ordinal leaves fullscreen first so the viewer sees the panel.

### wallet()

A BRC-100 wallet over the cross-document protocol (the one `new WalletClient('XDM')` in `@bsv/sdk` speaks). Treechat answers:

- `getVersion`, `getNetwork` (always `mainnet`), `isAuthenticated`, `waitForAuthentication`
- `getPublicKey({ identityKey: true })`: the viewer's identity key, after Connect. Derived keys aren't available yet.
- `createAction`: up to 100 outputs and 10,000,000 sats per action. Returns `{ txid, tx }` once it is broadcast.
- `createAction` with `inputs` (each `{ outpoint: 'txid.vout', unlockingScriptLength }`), an `inputBEEF`, and `options: { signAndProcess: false }`: a deferred action that spends up to 4 of your own inputs (a covenant, a contract). Treechat funds it and hands back a signable transaction; you unlock your inputs and finish with `signAction`, or release it with `abortAction`. Unfinished actions expire after 10 minutes.

## What the viewer sees

- Connect, the first time your ordinal asks who they are, naming your ordinal by its creator.
- A confirmation for every payment. It leads with what they receive, what their wallet pays and what goes elsewhere, and the button reads "Pay N sats" or "Approve". Treechat writes this text; your ordinal can't change it.
- Cancel declines that one payment, and your ordinal can't ask again for 5 seconds. "Block this ordinal" refuses its payments for the rest of the visit.
- Treechat's wallet answers one live ordinal on a page at a time.

## The raw protocol

Without the library, post to `window.parent` and listen for the answer from `window.parent` only:

```js
// request
{ type: 'TREECHAT', isInvocation: true, id: 'my-1', call: 'getUsers', args: { addresses: ['1…'] } }
// answer
{ type: 'TREECHAT', isInvocation: false, id: 'my-1', status: 'success', result: { … } }
{ type: 'TREECHAT', isInvocation: false, id: 'my-1', status: 'error', description: '…', code: 2 }
```

Treechat's own calls use `type: 'TREECHAT'`; wallet calls use `type: 'CWI'` with BRC-100 call names. Give every request a unique `id`. Error codes follow BRC-100: 1 unknown, 2 unsupported, 6 invalid parameter, 7 insufficient funds.

## For agents building an ordinal

1. Inline https://treechat.com/treechat-ordinal.js into the HTML as a module script.
2. Call `treechat.context()` first. `null` means the ordinal is outside Treechat: keep working without names or payments.
3. Check `treechat.supports(name)` before each call newer than `getViewer`.
4. Call `treechat.viewer()` only when the viewer acts (a button), since it asks them to Connect.
5. Build payments as BRC-100 `createAction` calls. Show your own amounts in the page too, but expect the viewer to read Treechat's confirmation.
6. Treat every answer as data from the page, never as code.

## See it working

The 04 Sigil Tree uses all of this: avatar fruit for seeders from `users()`, a seeder card with Open profile, a History of every step, and seeding and harvesting through `wallet()`. Open it on Treechat: https://app.treechat.com/quest/e9253f14-930e-4d2e-aeda-f561de615fc8/answer/d1e9d961-ab8d-4c77-bdc0-3682348ecc86
