Keeps FA2 v5 Launch Plan #
Date: February 16, 2026 Goal: Deploy final production v5 contract on keeps.tez with revenue enabled Status: Phase 1 in progress
Current State #
- v4 staging contract live on mainnet:
KT1ER1GyoeRNhkv6E57yKbBbEKi5ynKbaH3W- Admin: staging wallet (
tz1dfoQDuxjwSgxdqJnisyKUxDHweade4Gzt) - Fee: 0 XTZ (no revenue)
- 1 token minted so far
- Admin: staging wallet (
- v5 contract source created:
tezos/keeps_fa2_v5.py- Default fee: 2.5 XTZ (
sp.mutez(2500000)) - Improved error messages (
MINTING_PAUSED,EDITING_PAUSED) - All v4 features preserved (royalties, pause, admin transfer)
- Default fee: 2.5 XTZ (
KEEPS_STAGING = truestill active inlib/keeps/constants.mjs- Old v2 reference fixed in
kidlisp-keep.mjs(was pointing toKT1Ecs...)
Client Bugs to Fix Before Launch #
These issues exist in system/public/aesthetic.computer/disks/keep.mjs and must
be resolved before v5 production deployment.
Bug 1: Rebake triggers jump() to IPFS URL #
Symptom: Clicking Rebake button causes navigation away from the piece via
jump("out:https://ipfs.io/ipfs/Qm...") instead of staying on the keep page.
Root cause: The stickyScrubbing on rebakeBtn triggers a scrub event
that interacts with openUrl() calls on overlapping buttons (htmlBtn, thumbBtn).
When the rebake button overlaps with asset link buttons, the push handler for
the link button fires during the same event cycle.
Console evidence:
UI: scrub -> Object
jump() called: out:https://ipfs.io/ipfs/Qmd7cuKDQBBE...
Jumping to web URL: https://ipfs.io/ipfs/Qmd7cuKDQBBE...
Fix needed: Either:
- Guard
openUrlcalls to not fire whilerebakingis true - Ensure rebake button handlers return early / stop event propagation
- Move button
act()registrations so they don't overlap when rebake is active
Bug 2: Paint function not updating during rebake progress #
Symptom: Progress messages show in console (REBAKE: progress Object) but
the on-screen UI in paint() doesn't reflect them.
Root cause: The rebakeProgress text rendering at line ~2081 depends on
rebaking being true AND rebakeProgress being set. The paint section at line
2081 renders the progress text AFTER the button row, but the y cursor may
already be past the visible area. Additionally, if the rebake completes very
fast (SSE events arrive in a burst), the _needsPaint?.() calls may not
trigger visible repaints between events.
Fix needed:
- Ensure
rebakeProgresstext renders in a fixed, visible location (not dependent on accumulatedyoffset) - Consider debouncing
_needsPaintcalls or ensuring the paint loop is actually running during async operations
Bug 3: keep~$berz 404 after rebake navigation #
Symptom: After the unwanted jump(), the system tries to load
keep~$berz as a piece path and gets a 404.
Root cause: This is a downstream effect of Bug 1. The jump("out:...") call
navigates away, and when the system tries to resolve the return path, it
constructs keep~$berz (the colon-separated piece + params format) which
doesn't exist as a loadable resource.
Fix needed: Fixing Bug 1 eliminates this issue.
Launch Phases #
Phase 0: Client Bug Fixes (NOW) #
| Task | File | Status |
|---|---|---|
Fix rebake button triggering jump() to IPFS |
disks/keep.mjs |
DONE |
| Fix paint not updating during rebake progress | disks/keep.mjs |
DONE |
| Test rebake flow end-to-end in staging | Manual | TODO |
| Test "Update Chain" flow after rebake | Manual | TODO |
Phase 1: v5 Contract (DONE) #
| Task | File | Status |
|---|---|---|
Create keeps_fa2_v5.py from v4 |
tezos/keeps_fa2_v5.py |
DONE |
| Set default fee to 2.5 XTZ | keeps_fa2_v5.py:95 |
DONE |
| Improve error messages | keeps_fa2_v5.py |
DONE |
| Fix stale v2 contract ref in kidlisp-keep | kidlisp-keep.mjs:16 |
DONE |
Phase 2: Ghostnet Testing #
| Task | Status |
|---|---|
| Compile v5 with SmartPy | TODO |
Deploy to Ghostnet (--wallet=aesthetic) |
TODO |
| Test admin mint (no fee) | TODO |
| Test user mint (2.5 XTZ fee) | TODO |
| Test insufficient fee rejection | TODO |
| Test royalty metadata on TzKT | TODO |
| Test content hash dedup | TODO |
| Test emergency pause/unpause | TODO |
| Test admin transfer | TODO |
| Test metadata editing | TODO |
| Test fee adjustment | TODO |
| Test fee withdrawal | TODO |
| Test Oven thumbnail generation | TODO |
| Verify on ghostnet.objkt.com | TODO |
Phase 3: Mainnet Staging #
| Task | Status |
|---|---|
Deploy v5 to mainnet (--wallet=staging) |
TODO |
| Test with real XTZ (mint 3 tokens) | TODO |
| Verify on objkt.com | TODO |
| Test secondary sale royalties | TODO |
| Test fee withdrawal (real XTZ) | TODO |
| End-to-end UI flow via aesthetic.computer | TODO |
| Go/No-Go decision | TODO |
Phase 4: Production Deploy #
| Task | Status |
|---|---|
Deploy v5 to mainnet (--wallet=kidlisp) |
TODO |
Update constants.mjs contract address |
TODO |
Set KEEPS_STAGING = false |
TODO |
| Update env vars (Netlify) | TODO |
Update keep-mint.mjs contract address |
TODO |
Update keep-update.mjs contract address |
TODO |
Update keep-update-confirm.mjs contract address |
TODO |
Update kept.mjs contract address |
TODO |
Update wallet.mjs contract address |
TODO |
| Smoke test: first production mint | TODO |
| Verify on objkt.com | TODO |
Phase 5: Communication & Revenue #
| Task | Status |
|---|---|
| Announce v5 launch | TODO |
| Monitor first week mints | TODO |
| Track fee collection | TODO |
| A/B test fee amount if needed | TODO |
Files That Need Contract Address Updates at Launch #
When v5 deploys, update the contract address in ALL of these:
Constants (single source of truth):
system/public/aesthetic.computer/lib/keeps/constants.mjs— NETWORKS.mainnet.contract
Backend functions (env var fallbacks):
system/netlify/functions/keep-mint.mjs:31system/netlify/functions/keep-update.mjs:24system/netlify/functions/keep-update-confirm.mjs:12system/netlify/functions/kidlisp-keep.mjs:16
Frontend pieces (hardcoded refs):
system/public/aesthetic.computer/disks/kept.mjs:13system/public/aesthetic.computer/disks/wallet.mjs:14
Feature flag:
system/public/aesthetic.computer/lib/keeps/constants.mjs:10—KEEPS_STAGING = false
Key Decisions #
| Decision | Choice | Rationale |
|---|---|---|
| Fee amount | 2.5 XTZ (~$2.50) | Covers IPFS + margin, adjustable via set_keep_fee |
| Royalty | 10% (1000 bps) | Industry standard, adjustable via set_default_royalty |
| Old v2 contract | Keep both (no migration) | Zero disruption to existing holders |
| Solana | Parallel track | Don't delay Tezos revenue |
| Production admin | kidlisp wallet (tz1Lc2DzTjDPyWFj1iuAVGGZWNjK67Wun2dC / keeps.tez) |
Permanent production admin |