Real on Sui, three secrets, one build.
Every mega-prompt in this repo uses the same pattern, because it's the only pattern that lets a Lovable account ship a verifiable Sui Testnet demo in one shot.
Why Sui Testnet and not mainnet?
Sui Testnet runs the same Move VM, the same Suiscan explorer, and the same wallets as mainnet — but funded by a free faucet. Every Move package you publish is publicly inspectable, but you never spend real SUI and your demo can't accidentally drain a user. Users sign in with Google (Lovable-managed OAuth) and get a server-derived custodial Sui address they fund via the faucet — no wallet extension required. Move to mainnet after the hackathon by switching the network in the SuiClient.
The recipe
# 1. In your Lovable project, add two secrets (Settings -> Secrets): SUI_DEPLOYER_KEY=... # base64 Sui keypair, funded on Testnet SUI_WALLET_SALT=... # 64-char random, generated once in Lovable Cloud secrets # Optional (only if the idea pins media): WALRUS_PUBLISHER_URL=... # 2. Fund the deployer address on Sui Testnet: open https://faucet.testnet.sui.io # 3. Copy a mega-prompt from this repo into Lovable. One paste: # - scaffolds the React app + TanStack Start server functions # - writes the Move module (with hackathon credit in doc-comments) # - publishes to Sui Testnet, writes packageId to src/data/sui-package.json # - wires Google sign-in via Lovable (managed OAuth, no console setup) # - derives a per-user custodial Sui wallet server-side via HKDF # - uploads artefacts to Walrus and stores the blobId on-chain # - exposes the packageId + Suiscan link in the UI # 4. Open the live Suiscan link. Your demo is provably on Sui.
1. The Move module — credit baked in
Every Move file published from a Creative Blockchain prompt MUST carry the hackathon credit as a doc-comment, so provenance lives on-chain alongside the bytecode.
/// move/sources/provenance.move — every module carries the hackathon credit as a doc-comment
/// Built during the Creative AI & Quantum Hackathon organised by StreetKode Fam during Indian Krump Festival 14.
module provenance::provenance {
use sui::event;
use sui::tx_context::{Self, TxContext};
public struct Logged has copy, drop {
author: address,
blob_id: vector<u8>,
at_ms: u64,
}
/// Built during the Creative AI & Quantum Hackathon organised by StreetKode Fam during Indian Krump Festival 14.
entry public fun log(blob_id: vector<u8>, ctx: &mut TxContext) {
event::emit(Logged {
author: tx_context::sender(ctx),
blob_id,
at_ms: tx_context::epoch_timestamp_ms(ctx),
});
}
}
2. Publish to Sui Testnet
Sui doesn't have Etherscan-style source verification. Instead, publish your Move source alongside the packageId and link to suiscan.xyz/testnet/object/<packageId>for on-chain inspection.
# scripts/publish.sh — publish the Move package to Sui Testnet
# Requires SUI_DEPLOYER_KEY funded via https://faucet.testnet.sui.io
set -euo pipefail
sui client switch --env testnet
cd move
sui client publish --gas-budget 100000000 --json > ../publish.json
# Extract the packageId and persist it for the frontend
node -e "
const p = require('./publish.json');
const pkg = p.objectChanges.find(c => c.type === 'published');
require('fs').writeFileSync(
'src/data/sui-package.json',
JSON.stringify({
packageId: pkg.packageId,
network: 'testnet',
module: 'provenance',
eventType: pkg.packageId + '::provenance::Logged',
publishedAt: new Date().toISOString(),
explorer: 'https://suiscan.xyz/testnet'
}, null, 2)
);
"
3. Store artefacts on Walrus
// src/lib/walrus.ts — upload a Blob to Walrus, get back a permanent blobId
const PUBLISHER = "https://publisher.walrus-testnet.walrus.space";
const AGGREGATOR = "https://aggregator.walrus-testnet.walrus.space";
export async function uploadToWalrus(file: Blob, epochs = 5) {
const r = await fetch(`${PUBLISHER}/v1/store?epochs=${epochs}`, {
method: "PUT",
body: file,
});
const json = await r.json();
const blobId = json.newlyCreated?.blobObject?.blobId ?? json.alreadyCertified?.blobId;
return { blobId, url: `${AGGREGATOR}/v1/${blobId}` };
}
4. Sign in with Google (Lovable-managed) + custodial Sui wallet
Google OAuth is managed by Lovable — no Google Cloud console setup. On sign-in, the server derives a per-user Ed25519 Sui keypair from SUI_WALLET_SALT + the verified user id via HKDF, then signs transactions inside a createServerFn. Private keys never leave the server. Custodial demo pattern — Testnet only.
// 1. Client sign-in — src/components/sign-in-button.tsx
import { lovable } from "@/integrations/lovable";
export function SignInButton() {
return (
<button
onClick={() =>
lovable.auth.signInWithOAuth("google", {
redirect_uri: window.location.origin,
})
}
>
Sign in with Google
</button>
);
}
// 2. Server-derived custodial wallet — src/lib/sui-wallet.server.ts
import { hkdfSync } from "node:crypto";
import { Ed25519Keypair } from "@mysten/sui/keypairs/ed25519";
export function deriveKeypair(userId: string) {
const salt = Buffer.from(process.env.SUI_WALLET_SALT!, "utf8");
const ikm = Buffer.from(userId, "utf8");
const secret = hkdfSync("sha256", ikm, salt, Buffer.from("sui/ed25519"), 32);
return Ed25519Keypair.fromSecretKey(new Uint8Array(secret));
}
// Use inside a createServerFn().middleware([requireSupabaseAuth]).handler(...)
// so signing only ever runs server-side with the caller's verified user id.
Hackathon rules of thumb
- · One mega-prompt = one build message. Don't iterate the architecture, iterate the UI.
- · Always show the live Suiscan link in the UI — that's your proof.
- · Use Lovable's managed Google OAuth and a server-derived custodial wallet so judges don't need a wallet extension.
- · Upload every user-generated artefact to Walrus the moment it's created and store the blobId on-chain.
- · Add a "Built during the Creative AI & Quantum Hackathon — StreetKode Fam · Indian Krump Festival 14" line to your footer.