Skip to content

Latest commit

 

History

History
212 lines (180 loc) · 8.57 KB

File metadata and controls

212 lines (180 loc) · 8.57 KB

Token Host Builder Demo

Issue #13 uses Token Host Builder in wrapper mode around the hand-written FocPlatformRegistry and platform API. The generated Token Host app is the demo scaffold for upload UI, manifest metadata, sponsored transaction UX, and upload adapter wiring. It is not the authoritative storage lifecycle.

Committed Files

  • apps/tokenhost-foc-platform/schema.json: current Token Host Schema input.
  • apps/tokenhost-foc-platform/ui-overrides/app/page.tsx: custom generated home page used by Token Host Builder.
  • tokenhost/foc-platform-wrapper.config.json: FOC Platform wrapper metadata that current Token Host Builder cannot yet emit natively.
  • artifacts/tokenhost/foc-platform-wrapper-manifest.json: deterministic wrapper manifest generated by pnpm build:tokenhost.
  • src/admin/reconciliation.mjs and src/api/platform-admin-api.mjs: read-only admin/reconciliation projection and routes exposed to wrapper metadata until Token Host Builder emits native FOC Platform admin pages.
  • src/demo/tokenhost-wrapper.mjs: small client adapter for Token Host-style request/status/object/usage screens plus createTokenHostRegistryDirectReadAdapter for direct registry read pages.
  • test/tokenhost-demo.test.mjs: schema/config, manifest, and API flow smoke tests.
  • test/tokenhost-direct-reads.test.mjs: direct registry read adapter smoke tests for object, account, dataset, coordinator, relayer, admin, and stale active-cursor restart behavior.

Builder Evidence

Set these paths for your local checkouts:

export FOC_PLATFORM_DIR=/path/to/foc-platform
export TOKENHOST_BUILDER_DIR=/path/to/tokenhost-builder

Run the builder flow with:

pnpm --dir "$TOKENHOST_BUILDER_DIR" install
pnpm --dir "$TOKENHOST_BUILDER_DIR" build
pnpm --dir "$TOKENHOST_BUILDER_DIR" th validate "$FOC_PLATFORM_DIR/apps/tokenhost-foc-platform/schema.json"
rm -rf /tmp/foc-platform-tokenhost-demo
TH_UPLOAD_RUNNER=remote \
TH_UPLOAD_PROVIDER=filecoin_onchain_cloud \
TH_UPLOAD_REMOTE_ENDPOINT_URL=/storage/tokenhost/upload \
TH_UPLOAD_REMOTE_STATUS_URL=/storage/tokenhost/upload/status \
pnpm --dir "$TOKENHOST_BUILDER_DIR" th build "$FOC_PLATFORM_DIR/apps/tokenhost-foc-platform/schema.json" \
  --chain filecoin_calibration \
  --tx-mode sponsored \
  --relay-base-url /__tokenhost/relay \
  --out /tmp/foc-platform-tokenhost-demo

th validate reported schema hash sha256:b1113f6e1338d1fd54421441ce079fa1432334c2dc2e71785c8f3f2a19d1b4c5.

Observed output included:

  • manifest.json
  • schema.json
  • contracts/App.sol
  • compiled/App.json
  • sources.tgz
  • compiled.tgz
  • ui-bundle/
  • ui-site/
  • netlify.toml
  • netlify/functions/tokenhost-upload-start.mjs
  • netlify/functions/tokenhost-upload-status.mjs
  • netlify/functions/tokenhost-upload-worker-background.mjs
  • NETLIFY-UPLOADS.md

The generated Next export included /, /UploadRequest, /StorageObject, and /tag; / came from the custom ui-overrides home page. The generated manifest exposed sponsored transaction metadata and Filecoin upload adapter metadata:

{
  "extensions": {
    "tx": {
      "mode": "sponsored",
      "sponsored": { "relayBaseUrl": "/__tokenhost/relay" }
    },
    "uploads": {
      "enabled": true,
      "endpointUrl": "/storage/tokenhost/upload",
      "statusUrl": "/storage/tokenhost/upload/status",
      "provider": "filecoin_onchain_cloud",
      "runnerMode": "remote"
    }
  },
  "ui": {
    "bundleHash": "sha256:<builder-emitted-ui-bundle-digest>"
  }
}

The build manifest still uses a placeholder local deployment until th deploy runs against a real chain and funded key. Do not treat the build-only manifest as Calibration deployment evidence.

Wrapper Mode

The wrapper config maps the generated app to the platform API:

  • generated Token Host byte upload adapter: POST /storage/tokenhost/upload
  • generated Token Host upload adapter status: GET /storage/tokenhost/upload/status
  • create upload: POST /storage/upload-requests or POST /storage/upload
  • submit bytes: POST /storage/uploads/:objectId/bytes
  • status: GET /storage/uploads/:objectId/status or GET /storage/uploads/:objectId
  • object: GET /storage/objects/:objectId
  • usage: GET /storage/usage/:accountId or GET /usage
  • admin object browser: GET /admin/storage/objects and GET /admin/storage/objects/:objectId
  • admin usage: GET /admin/storage/usage
  • admin dataset/provider attribution: GET /admin/storage/datasets
  • admin coordinator status: GET /admin/storage/coordinators
  • admin reconciliation: GET /admin/storage/reconciliation

pnpm build:tokenhost also emits registry.directReads into artifacts/tokenhost/foc-platform-wrapper-manifest.json. Generated or wrapper provided admin/read UIs should use that metadata to discover the Calibration chain, registry address source, ABI artifact, max page size, list methods, detail methods, dataset key tuple shape, and bounded readBatch/multicall capability. The repo-local adapter can be passed as the admin implementation to createPlatformAdminApi when a server wrapper wants the existing admin routes backed by direct contract views instead of fixture/projection state.

FocPlatformRegistry remains authoritative for lifecycle, receipts, usage, relayer accountability, coordinator controls, and reconciliation. Generic Token Host CRUD output may help generate UI and upload scaffolding, but it must not replace section 6.7 semantics until a custom FOC module proves equivalence. The current admin routes are wrapper/read-model projections and require an explicit operator authorization hook in any server wrapper. The direct-onchain admin path must instead bind Token Host wrapper reads to the FOC-specific registry list/detail surface:

  • use bounded ID/key enumeration in the same spirit as Token Host Builder listIdsC(cursorIdExclusive, limit, includeDeleted=false) pages, while preserving the FOC registry's exact cursor model;
  • use object-id cursors for listStorageObjectIds and listAccountObjectIds;
  • use offset pagination for listAccountIds, listCoordinatorAddresses, listRelayerAddresses, and listDatasetKeys;
  • fetch details through getStorageObject, getAccountUsage, getCopyReceipts, receiptPayer, getDatasetRecord, coordinatorPolicies, and isRelayer;
  • batch bounded detail reads with registry readBatch or builder-compatible multicall helpers where available;
  • keep generated CRUD state as UI scaffolding only, not as the current-state authority for FOC Platform rows.

FOC active-object cursors intentionally differ from generic builder short-page semantics when stale tombstone traversal exceeds the scan budget: the registry reverts with ActiveCursorTraversalLimitExceeded, and wrapper/dashboard code should restart from the head cursor rather than interpreting that path as a real end-of-list.

The generated byte-upload endpoint speaks Token Host Builder's upload adapter contract: it accepts file bytes with X-TokenHost-Upload-* headers and returns { ok: true, upload: { url, size, provider, runnerMode, metadata } }. The adapter then creates a section 6.7 upload request and submits the bytes through the registry adapter. In this wrapper phase upload.url points at the platform object read endpoint, not a public CDN retrieval URL.

The generated upload adapter status endpoint GET /storage/tokenhost/upload/status returns Token Host upload-runner metadata. The separate object-status alias GET /storage/uploads/status?objectId=:objectId maps to the same registry read as the canonical section 6.7 object status route, GET /storage/uploads/:objectId/status.

Current Builder Gaps

These upstream Token Host Builder issues remain open:

  • tokenhost/tokenhost-builder#79: native app.focPlatform schema and manifest extension.
  • tokenhost/tokenhost-builder#80: registry lifecycle generation or tested wrapper mode.
  • tokenhost/tokenhost-builder#81: generated FOC Platform admin and reconciliation surfaces.
  • tokenhost/tokenhost-builder#82: receipt-aware upload runner path.

Until those land, FOC metadata lives in tokenhost/foc-platform-wrapper.config.json and the wrapper manifest. The generated upload runner is prototype/demo scaffolding, not proof of section 6.7-compatible receipts.

Local Smoke

Run:

pnpm build:tokenhost
pnpm test:tokenhost

The focused smoke test drives a Token Host-style flow through the platform API:

  1. submit a generated Token Host byte upload through /storage/tokenhost/upload,
  2. create an upload request,
  3. submit bytes through the platform upload endpoint,
  4. read upload status,
  5. read object receipt state,
  6. read account usage.