Ufree Mini-App Quick Reference

One-page cheat sheet of methods, error codes, and modes

Ufree Mini-App Quick Reference

One-page cheat sheet. For full context see MINI_APP_DEVELOPERS.md (中文) or MINI_APP_DEVELOPERS_EN.md (English).

Install SDK

<script src="https://YOUR-UFREE-HOST/sdk/ufree.js"></script>

Exposes window.ufree, plus aliases window.ethereum (EIP-1193) and window.nostr (NIP-07) if not already claimed.

EIP-1193 methods (window.ethereum.request)

Method Params Returns Status
eth_requestAccounts [address]
eth_accounts [address]
eth_chainId "0x1"
net_version "1"
personal_sign [message, address] "0x...130-char sig"
eth_sign [address, message] sig
eth_sendTransaction [txObject] tx hash ⏳ 4900
wallet_switchEthereumChain [{chainId: "0x89"}] null ⏳ 4900
wallet_addEthereumChain ❌ 4200

NIP-07 methods (window.nostr)

Method Params Returns
getPublicKey() "hex pubkey"
signEvent(event) EventTemplate SignedEvent

Antelope (raw bridge — no global standard yet)

Method Params Returns Status
wallet.antelope.getAccount "accountname"
wallet.antelope.getChain "eos" or "eos-jungle4"
wallet.antelope.signTransaction Action[] signed tx ⏳ 4900
wallet.antelope.switchChain {chainId} null ⏳ 4900
wallet.antelope.getTableRows {code, table, scope, ...} rows ⏳ 4900

Call via window.ufree.request('wallet.antelope.X', params).

App / Wallet generic

Method Returns
app.getInfo {npub, name, about, picture, version}
app.close closes mini-app (null)
wallet.getType "evm" or "antelope"

Error codes

Code Meaning
4001 User rejected
4200 Method not supported
4900 Not yet implemented
4901 Wrong key family (EVM op on Antelope wallet, or vice versa)
4902 Wallet locked
-32601 Method not found
-32602 Invalid params
-32603 Internal error

Manifest schema

{
  name: string;          // required
  version: string;       // required, semver-ish
  bundleUrl: string;     // required — https:// or ipfs://
  about?: string;
  picture?: string;      // https / ipfs / data:image/
  bundleHash?: string;   // 64-char lowercase sha256 hex
}

Bundle modes

Mode bundleHash srcdoc? Backend API? Use when
Single-file + hash yes yes Pure-frontend (chain RPC / Nostr only)
Multi-file no hash no no Standard SPA with backend
Multi-file + hash yes yes (+<base> injected) Static entry HTML, no API

Rule of thumb: have a backend? Don’t ship bundleHash.

Sign-in with wallet (replaces cookies)

const { challenge } = await fetch('/api/auth/challenge').then(r => r.json());
const [addr] = await window.ethereum.request({ method: 'eth_requestAccounts' });
const sig = await window.ethereum.request({
  method: 'personal_sign',
  params: [challenge, addr],
});
const { token } = await fetch('/api/auth/verify', {
  method: 'POST',
  body: JSON.stringify({ address: addr, signature: sig, challenge }),
}).then(r => r.json());

Backend verifies with ethers.verifyMessage(challenge, sig) === address.

Container constraints (TL;DR)

  • ✅ Most Web APIs work (DOM, fetch, WebSocket, Canvas, WebGL, IndexedDB, Web Workers, Web Audio)
  • ✅ Browser-prompted permissions: camera, mic, clipboard, geolocation, fullscreen, sensors, payment
  • ⚠️ Third-party cookies invisible — user must re-login inside the container
  • ❌ WebUSB / WebBluetooth / WebNFC / WebSerial
  • ❌ Service Workers (use with extreme care)
  • 🚫 srcdoc mode (when bundleHash present): no backend API CORS, no cookies

Raw postMessage protocol

// Request (mini-app → host)
window.parent.postMessage({
  ufree: 1, kind: 'request', id: '1',
  method: 'wallet.evm.signMessage', params: { message: 'hi' }
}, '*');

// Response (host → mini-app, on window 'message' event)
{ ufree: 1, kind: 'response', id: '1', result: '0x...' }
// or
{ ufree: 1, kind: 'response', id: '1', error: { code: 4001, message: 'rejected' } }

Looking for comments…

Searching Nostr relays. This may take a moment the first time this article is opened.