Monorepo for Aesthetic.Computer
aesthetic.computer
Keeps v4 Ghostnet Testing Workflow#
Status: Ready for testing Contract: v4 (royalties, pause, admin transfer) Target Network: Ghostnet → Mainnet staging → Production
Prerequisites#
1. SmartPy Installation#
# Ensure SmartPy is installed (v0.21.0+)
python --version # Should be Python 3.10+
# If not installed:
pip install smartpy-tezos
2. Wallet Setup#
Ensure you have the following wallets configured:
- kidlisp wallet -
tz1Lc2DzTjDPyWFj1iuAVGGZWNjK67Wun2dC(keeps.tez) - aesthetic wallet -
tz1gkf8EexComFBJvjtT1zdsisdah791KwBE(aesthetic.tez) - staging wallet -
tz1dfoQDuxjwSgxdqJnisyKUxDHweade4Gzt
Credentials should be in:
../aesthetic-computer-vault/tezos/kidlisp/.env../aesthetic-computer-vault/tezos/staging/.env
3. Ghostnet XTZ#
Get testnet funds from:
- https://faucet.ghostnet.teztnets.com
- Or use Temple wallet faucet
Step 1: Compile v4 Contract#
Compile the Contract#
cd /workspaces/aesthetic-computer/tezos
# Run the SmartPy compiler
python keeps_fa2_v4.py
# Expected output directory:
# KeepsFA2v4/
# ├── step_002_cont_0_contract.tz (Michelson code)
# ├── step_002_cont_0_storage.tz (Initial storage)
# └── step_002_cont_0_types.py (Type definitions)
Verify Compilation#
# Check that contract file exists
ls -lh KeepsFA2v4/step_002_cont_0_contract.tz
# Check size (should be ~20-30KB)
# Larger than v3 due to new entrypoints
Update keeps.mjs Contract Path#
The keeps.mjs script should already point to v4:
// In CONFIG.paths (line 58)
contract: path.join(__dirname, 'KeepsFA2v4/step_002_cont_0_contract.tz'),
If not, update it manually.
Step 2: Deploy to Ghostnet#
Deploy Contract#
# Deploy using kidlisp wallet (for testing)
node keeps.mjs deploy ghostnet --wallet=kidlisp
# Expected output:
# 🚀 Deploying Keeps FA2 v4 Contract
# 📡 Network: Ghostnet (Testnet)
# 👤 Administrator: tz1Lc2...
# ✓ Contract deployed: KT1...
# 📝 Saved to: contract-address-ghostnet.txt
Verify Deployment#
# Check contract status
node keeps.mjs status --wallet=kidlisp
# Should show:
# - v4 features (paused=false, default_royalty_bps=1000)
# - Next token ID: 0
# - Keep fee: 0 XTZ
View on Ghostnet Explorer#
# Get contract address
cat contract-address-ghostnet.txt
# Visit:
# https://ghostnet.tzkt.io/KT1...
# https://ghostnet.objkt.com/collection/KT1...
Step 3: Test Royalty Configuration#
3.1 Check Default Royalty#
# View current royalty (should be 10% = 1000 bps)
node keeps.mjs royalty --wallet=kidlisp
# Expected output:
# 🎨 Current Royalty Configuration
# Contract: KT1...
# Royalty: 10.0% (1000 basis points)
3.2 Change Royalty to 15%#
# Set royalty to 15%
node keeps.mjs royalty:set 15 --wallet=kidlisp
# Expected:
# ✅ Royalty set to 15%
# 🔗 https://ghostnet.tzkt.io/op...
3.3 Verify On-Chain#
# Check status again
node keeps.mjs royalty --wallet=kidlisp
# Should now show: 15.0% (1500 basis points)
3.4 Reset to 10%#
# Set back to 10% for production testing
node keeps.mjs royalty:set 10 --wallet=kidlisp
Step 4: Test Emergency Pause#
4.1 Pause Contract#
# Pause minting and metadata edits
node keeps.mjs pause --wallet=kidlisp
# Confirm when prompted
# Expected:
# 🚨 EMERGENCY PAUSE
# ⚠️ This will stop all minting and metadata edits
# Pause contract? (y/N): y
# ✅ Contract PAUSED
4.2 Verify Pause State#
# Check contract status
node keeps.mjs status --wallet=kidlisp
# Look for: paused: true
4.3 Try to Mint (Should Fail)#
# Attempt to mint while paused
node keeps.mjs keep test --wallet=kidlisp --yes
# Expected error:
# ❌ CONTRACT_PAUSED
4.4 Unpause Contract#
# Resume operations
node keeps.mjs unpause --wallet=kidlisp
# Expected:
# ✅ Contract UNPAUSED
# Minting and metadata edits are now enabled
4.5 Verify Unpause#
# Check status
node keeps.mjs status --wallet=kidlisp
# Look for: paused: false
Step 5: Test Minting with Royalties#
5.1 Mint First Test Token#
# Mint a test piece with royalty
node keeps.mjs keep test1 --wallet=kidlisp --thumbnail --yes
# Expected:
# 📤 Uploading HTML bundle to IPFS...
# 🖼️ Generating thumbnail...
# 🔗 Artifact URI: ipfs://Qm...
# ✓ Token minted: #0
5.2 Check Token on TzKT#
# Get contract address
CONTRACT=$(cat contract-address-ghostnet.txt)
# Fetch token metadata via TzKT API
curl "https://api.ghostnet.tzkt.io/v1/tokens?contract=${CONTRACT}&tokenId=0"
# Look for royalties field in metadata:
# "royalties": {
# "decimals": 4,
# "shares": {
# "tz1Lc2...": "1000"
# }
# }
5.3 View on Ghostnet objkt.com#
# Visit:
# https://ghostnet.objkt.com/asset/KT1.../0
# Verify:
# ✓ Token displays correctly
# ✓ "Created by" shows kidlisp wallet
# ✓ Royalty section shows 10%
# ✓ Artifact loads in iframe
5.4 Mint Additional Tokens#
# Mint 3-5 more test tokens
node keeps.mjs keep test2 --wallet=kidlisp --yes
node keeps.mjs keep test3 --wallet=kidlisp --yes
node keeps.mjs keep test4 --wallet=kidlisp --yes
Step 6: Test Admin Transfer#
6.1 Transfer Token to Test Wallet#
# Transfer token #0 from kidlisp to aesthetic wallet
node keeps.mjs transfer:admin 0 \
tz1Lc2DzTjDPyWFj1iuAVGGZWNjK67Wun2dC \
tz1gkf8EexComFBJvjtT1zdsisdah791KwBE \
--wallet=kidlisp
# Confirm when prompted
# Expected:
# 🔄 Admin Emergency Transfer
# Token ID: #0
# From: tz1Lc2...
# To: tz1gkf8...
# Transfer token? (y/N): y
# ✅ Token transferred
6.2 Verify Transfer on TzKT#
# Check token balance
curl "https://api.ghostnet.tzkt.io/v1/tokens/balances?token.contract=${CONTRACT}&token.tokenId=0"
# Should show:
# account.address: tz1gkf8... (aesthetic wallet)
# balance: 1
6.3 Verify on objkt.com#
# Visit token page
# https://ghostnet.objkt.com/asset/KT1.../0
# Check:
# ✓ Owner shows aesthetic wallet
# ✓ "Created by" still shows kidlisp wallet (preserved!)
6.4 Transfer Back#
# Transfer back to kidlisp
node keeps.mjs transfer:admin 0 \
tz1gkf8EexComFBJvjtT1zdsisdah791KwBE \
tz1Lc2DzTjDPyWFj1iuAVGGZWNjK67Wun2dC \
--wallet=kidlisp
Step 7: Test Metadata Updates (with Royalty Preservation)#
7.1 Rebake a Token (Simulated)#
This would normally be done through the web UI (/api/keep-update), but we can verify the royalty preservation logic manually.
7.2 Check keep-update.mjs Royalty Code#
# Verify royalty preservation in keep-update.mjs (lines 355-363)
grep -A 10 "v4: Preserve 10% royalty" \
/workspaces/aesthetic-computer/system/netlify/functions/keep-update.mjs
# Should show:
# const royalties = {
# decimals: 4,
# shares: {
# [originalMinter]: "1000"
# }
# };
7.3 Manual Metadata Update Test (Optional)#
If you want to test metadata updates directly via CLI:
# Update token #0 metadata (re-upload bundle)
node keeps.mjs update 0 test1 --wallet=kidlisp --thumbnail
# Verify royalty preserved in updated metadata via TzKT
Step 8: Integration Testing#
8.1 Full Web UI Flow#
- Visit: https://aesthetic.computer/prompt
- Login with test account
- Link Tezos wallet (Temple/Kukai on Ghostnet)
- Create a KidLisp piece:
prompt keep $ghosttest - Mint via Web UI:
- Should see 10-step timeline
- Wallet signature request appears
- Confirm mint in wallet (pay gas only, 0 XTZ fee)
- Verify on objkt:
- Token appears on ghostnet.objkt.com
- 10% royalty shown
- Correct attribution
8.2 Test Rebake Flow#
- Edit piece source in aesthetic.computer
- Click "Rebake" button in keep UI
- Regenerate bundle (same token ID)
- Click "Update Chain"
- Sign with creator wallet (preserves attribution)
- Verify on objkt:
- Artwork updated
- Royalty still 10%
- Attribution preserved
Step 9: Performance & Gas Testing#
9.1 Measure Gas Costs#
# Mint and record gas cost
node keeps.mjs keep gastest --wallet=kidlisp --yes
# Check operation on TzKT:
# - Gas used should be < 10,000 units
# - Storage cost should be < 0.05 XTZ
# - Total cost: ~0.01-0.05 XTZ
9.2 Test with Different Content#
# Small piece
node keeps.mjs keep tiny --wallet=kidlisp --yes
# Large piece (complex code)
node keeps.mjs keep complex --wallet=kidlisp --yes
# Compare gas costs on TzKT
Step 10: Security Testing#
10.1 Non-Admin Pause (Should Fail)#
# Try to pause with non-admin wallet
# (Would need to manually call contract with different wallet)
# Expected: FA2_NOT_ADMIN error
10.2 Invalid Royalty (Should Fail)#
# Try to set royalty > 25%
node keeps.mjs royalty:set 30 --wallet=kidlisp
# Expected error:
# Royalty must be between 0% and 25%
10.3 Invalid Transfer (Should Fail)#
# Try to transfer with wrong current owner
node keeps.mjs transfer:admin 0 \
tz1WRONG_ADDRESS \
tz1gkf8EexComFBJvjtT1zdsisdah791KwBE \
--wallet=kidlisp
# Expected: INVALID_CURRENT_OWNER error
Step 11: Cleanup & Documentation#
11.1 Burn Test Tokens#
# Burn all test tokens to free piece names
node keeps.mjs burn 0 --wallet=kidlisp
node keeps.mjs burn 1 --wallet=kidlisp
node keeps.mjs burn 2 --wallet=kidlisp
node keeps.mjs burn 3 --wallet=kidlisp
11.2 Final Status Check#
# Verify contract is clean
node keeps.mjs status --wallet=kidlisp
# Should show:
# - Keeps: 0 total
# - Next ID: 4 (burned tokens don't reset counter)
# - Paused: false
# - Royalty: 10%
11.3 Document Results#
Create a test report:
# Create test report
cat > /workspaces/aesthetic-computer/tezos/KEEPS-V4-TEST-REPORT.md << 'EOF'
# Keeps v4 Ghostnet Test Report
**Date:** $(date)
**Tester:** [Your Name]
**Contract:** $(cat contract-address-ghostnet.txt)
## Test Results
### Royalty System
- [x] Default royalty 10%
- [x] Set royalty to 15%
- [x] Royalty in token metadata
- [x] objkt.com displays royalty
### Pause Functionality
- [x] Pause stops minting
- [x] Pause stops metadata edits
- [x] Unpause resumes operations
- [x] Non-admin cannot pause
### Admin Transfer
- [x] Transfer token between wallets
- [x] Attribution preserved after transfer
- [x] objkt.com shows correct owner
- [x] Invalid transfer rejected
### Minting with Royalties
- [x] Tokens mint with 10% royalty
- [x] TzKT shows royalty metadata
- [x] objkt.com displays correctly
- [x] Gas costs reasonable (<0.05 XTZ)
### Integration
- [x] Web UI mint flow works
- [x] Rebake preserves royalties
- [x] Attribution system working
- [x] Wallet signing functional
## Issues Found
[List any issues discovered during testing]
## Recommendations
- [ ] Ready for mainnet staging
- [ ] Needs fixes (specify below)
## Next Steps
1. Deploy to mainnet staging
2. Test with 5-10 canonical pieces
3. Verify first secondary sale royalty
4. Production launch
---
**Signed off by:** [Your Name]
**Approved by:** [Reviewer]
EOF
Troubleshooting#
Contract Won't Compile#
# Check SmartPy version
python -c "import smartpy; print(smartpy.__version__)"
# Should be 0.21.0+
# If old version, upgrade:
pip install --upgrade smartpy-tezos
Deployment Fails#
# Check wallet balance
node keeps.mjs balance --wallet=kidlisp
# Need at least 1 XTZ for deployment
# Get more from faucet if needed
Royalty Not Showing on objkt#
# Verify royalty in token metadata via TzKT
curl "https://api.ghostnet.tzkt.io/v1/tokens?contract=${CONTRACT}&tokenId=0" | jq '.royalties'
# If missing, check keep-mint.mjs has royalty code (lines 892-903)
Pause Not Working#
# Verify contract has pause entrypoints
curl "https://api.ghostnet.tzkt.io/v1/contracts/${CONTRACT}/entrypoints" | grep pause
# Should see: pause, unpause
Success Criteria#
Before moving to mainnet staging, ensure ALL of these pass:
- Contract compiles without errors
- Deploys successfully to Ghostnet
- Royalty defaults to 10%
- Can change royalty (0-25%)
- Pause stops minting
- Unpause resumes operations
- Admin transfer works
- Attribution preserved after transfer
- Tokens mint with royalty metadata
- TzKT indexes royalty correctly
- objkt.com displays royalty percentage
- Gas costs < 0.05 XTZ per mint
- Web UI integration functional
- Rebake preserves royalties
- Security: non-admin operations blocked
Next: Mainnet Staging#
Once Ghostnet testing is complete, proceed to:
- Deploy to mainnet with staging wallet
- Test with real XTZ (small amounts)
- Mint 5-10 canonical pieces
- Transfer test token and verify secondary sale royalty
- Monitor for 1 week
- Production launch with kidlisp wallet
See: KEEPS-V4-PLAN.md for full production roadmap.