🎥 Videography & Film · version control

Gasless Release Commits

Commit video edits onchain transparently with zero gas cost for creators.

Solana + x402 paywall· x402 native
Section · Onchain

The primitive.

full primer →

The Solana primitive runs at the right moment in the flow and surfaces a clear, verifiable result that videographers can act on without web3 jargon.

Why this primitiveA single-endpoint x402 paywall on Solana Devnet is the smallest possible monetization surface for 'Gasless Release Commits' — one 0.01 USDC signature unlocks the creative payload, settled by PayAI, verifiable on Solana Explorer, with no server-side subscription state to manage.

Kernel
A protected creative endpoint returns HTTP 402 with an x402 challenge; the browser signs a Solana USDC TransferChecked with the Privy embedded wallet, PayAI's Solana Devnet facilitator verifies + settles it, and the endpoint replies with the payload plus a PAYMENT-RESPONSE tx receipt.
Drives the UI as
A 4-step flow log (Challenge → Sign → Retry → Settle) that ends with a live Solana Explorer tx link proving the 0.01 USDC micropayment cleared on Devnet.
Appendix · Secrets

Required keys.

PRIVY_APP_ID
Google sign-in + embedded Solana wallet (Devnet).
open ↗
PINATA_JWT
Pin images / JSON / manifests to IPFS.
open ↗
LOVABLE_API_KEY
AI calls via the Lovable AI Gateway.
open ↗
SOLANA_RPC_URL
Alchemy Solana Devnet RPC (https://solana-devnet.g.alchemy.com/v2/<KEY>). The public api.devnet.solana.com is rate-limited and CORS-blocked in the browser.
open ↗
PHANTOM_PRIVATE_KEY
Base58 secret key exported from Phantom (Settings → Export Private Key). Used ONCE by scripts/deploy.ts to pay rent + fees for your bespoke program on Devnet. Fund it from https://faucet.solana.com. Never shipped to the browser.
open ↗

Add these in your Lovable project under Settings → Secrets before pasting the prompt below.

Appendix · Mega-prompt

The build prompt.

Paste into a fresh Lovable project. Make sure all five secrets above are set first. read the build strategy →

Build "Gasless Release Commits" in ONE Lovable message. Single-page demo on Solana Devnet with an x402 paywall.
This prompt is self-contained — do NOT rely on any external Solana or x402 skill beyond what is inlined here.

CONCEPT
Commit video edits onchain transparently with zero gas cost for creators.
Discipline: Videography & Film (version control).
Onchain primitive: x402 Paid Endpoint on Solana Devnet. Why this primitive: A single-endpoint x402 paywall on Solana Devnet is the smallest possible monetization surface for 'Gasless Release Commits' — one 0.01 USDC signature unlocks the creative payload, settled by PayAI, verifiable on Solana Explorer, with no server-side subscription state to manage.

5-CREDIT BUDGET (HARD LIMIT — one Lovable message, no follow-ups):
- ONE single-page app (index route only). No Lovable Cloud, no database, no auth flows
  beyond Privy drop-in.
- Privy (Google login + embedded Solana wallet on Devnet) is ALWAYS the signing layer.
- Every unlock = 0.01 USDC on Solana Devnet, settled by PayAI's public facilitator.
- No custom Solana program. No Anchor. No Metaplex. No cNFT. Just SPL Token transfer
  wrapped in the x402 exact scheme.

REQUIRED SECRETS (Lovable → Project Settings → Secrets — add BEFORE sending this prompt):
- PRIVY_APP_ID            From https://dashboard.privy.io. In the SAME Privy app, whitelist BOTH
                          `https://*.lovable.app` AND your published `https://<slug>.lovable.app`
                          under Allowed Origins, or the signing iframe is killed by frame-ancestors
                          CSP and every tx fails with a blank "Something went wrong" modal.
                          Enable Solana gas sponsorship for cluster `solana:devnet` in the same
                          dashboard so users never see a fund-wallet prompt for SOL.
- SOLANA_RPC_URL          Alchemy Solana Devnet RPC: https://solana-devnet.g.alchemy.com/v2/<KEY>.
                          The public https://api.devnet.solana.com is rate-limited and blocks
                          browser CORS on getLatestBlockhash — do NOT use it.
- LOVABLE_API_KEY         Auto-provisioned by Lovable. Optional — only if the unlocked payload
                          needs one AI call per unlock (invoked from a server function, never the
                          browser).

Expose secrets to the browser in `.env.local` (Vite only ships VITE_* to the client):
```
VITE_PRIVY_APP_ID=<same value as PRIVY_APP_ID secret>
VITE_SOLANA_RPC_URL=<same value as SOLANA_RPC_URL secret>
```

STACK
- React + Vite + TanStack Start single page.
- `@solana/web3.js` + `@solana/spl-token` for tx building. `@privy-io/react-auth` v3+ for auth AND signing.
- Cluster: Devnet ONLY. Never mainnet.
- PayAI SVM facilitator: `https://x402.payai.network/api/solana-devnet/paid-content`.
- Devnet USDC mint: `4zMMC9srt5Ri5X14GAgXhaHii3GnPAEERYPJgZJDncDU`, 6 decimals.
- Amount: `"10000"` atomic units = 0.01 USDC per unlock.
- Network id (CAIP-2-ish): `"solana-devnet"` — the string PayAI uses in `accepts[].network`.
- Scheme: `"exact"`.

VITE + BUFFER POLYFILL (4 layers — omit any one and it works in dev but blanks the
published mobile build):
1. `bun add buffer vite-plugin-node-polyfills`.
2. `vite.config.ts`:
```ts
import { defineConfig } from "vite";
import react from "@vitejs/plugin-react";
import { nodePolyfills } from "vite-plugin-node-polyfills";
export default defineConfig({
  plugins: [react(), nodePolyfills({ globals: { Buffer: true, global: true }, protocolImports: true })],
  optimizeDeps: { esbuildOptions: { define: { global: "globalThis" } } },
  resolve: { alias: { "rpc-websockets/dist/lib/client": "rpc-websockets/dist/lib/client.browser.js" } },
});
```
DO NOT add a top-level `define: { global: "globalThis" }` in vite.config — it conflicts with the
plugin's Rollup inject and leaves Buffer undefined in dependency chunks. DO NOT put `import`
statements inside `build.rollupOptions.output.intro` — top-level import inside a chunk wrapper is
illegal and blanks the page.
3. `index.html` — inline BEFORE any bundle loads:
```html
<script type="module">
  import { Buffer } from "https://esm.sh/buffer@6";
  globalThis.Buffer = globalThis.Buffer || Buffer;
</script>
```
4. `src/polyfills.ts` (imported FIRST in `src/main.tsx`, before anything else):
```ts
import { Buffer } from "buffer";
(globalThis as any).Buffer = (globalThis as any).Buffer || Buffer;
(window as any).Buffer = (window as any).Buffer || Buffer;
```
Then in every file that touches Solana, add `import { Buffer } from "buffer";` at the top — the
plugin cannot inject into your own TypeScript source.

PRIVY (browser auth + Solana signing) — v3, MUST include `solana.rpcs`:
```
bun add @privy-io/react-auth @solana/web3.js @solana/spl-token @solana/kit @solana-program/memo
```
(`@solana-program/memo` is an implicit peer dep of `@privy-io/react-auth/solana`; missing it
crashes the Privy modal at runtime.)

`src/components/PrivyRoot.tsx`:
```tsx
import { PrivyProvider } from "@privy-io/react-auth";
import { toSolanaWalletConnectors } from "@privy-io/react-auth/solana";
import { createSolanaRpc, createSolanaRpcSubscriptions } from "@solana/kit";

const rpcUrl = import.meta.env.VITE_SOLANA_RPC_URL!;
const wsUrl  = rpcUrl.replace("https://", "wss://");

export function PrivyRoot({ children }: { children: React.ReactNode }) {
  return (
    <PrivyProvider
      appId={import.meta.env.VITE_PRIVY_APP_ID!}
      config={{
        loginMethods: ["google", "email"],
        embeddedWallets: { solana: { createOnLogin: "users-without-wallets" } },
        externalWallets: { solana: { connectors: toSolanaWalletConnectors() } },
        solanaClusters: [{ name: "devnet", rpcUrl }],
        solana: {
          rpcs: {
            "solana:devnet": {
              rpc: createSolanaRpc(rpcUrl),
              rpcSubscriptions: createSolanaRpcSubscriptions(wsUrl),
            },
          },
        },
      }}
    >{children}</PrivyProvider>
  );
}
```
Without the `solana.rpcs` mapping, Privy throws "No RPC configuration found for chain solana:devnet".

Sign the x402 tx with the embedded wallet:
```tsx
import { useSolanaWallets } from "@privy-io/react-auth/solana";
const { wallets } = useSolanaWallets();
const embedded = wallets.find(w => w.walletClientType === "privy");
const signed = await embedded!.signTransaction(tx); // VersionedTransaction
```

X402 PROXY ROUTE (same-origin — the facilitator does NOT send CORS headers, direct
browser fetch throws `TypeError: Failed to fetch` before the 402 arrives):
```ts
// src/routes/api/public/x402-proxy.ts
import { createFileRoute } from "@tanstack/react-router";

const ENDPOINT = "https://x402.payai.network/api/solana-devnet/paid-content";

export const Route = createFileRoute("/api/public/x402-proxy")({
  server: {
    handlers: {
      GET: async ({ request }) => {
        const sig = request.headers.get("PAYMENT-SIGNATURE");
        const upstream = await fetch(ENDPOINT, {
          method: "GET",
          headers: sig ? { "PAYMENT-SIGNATURE": sig } : {},
        });
        const body = await upstream.arrayBuffer();
        const out = new Headers();
        const ct = upstream.headers.get("content-type");
        if (ct) out.set("Content-Type", ct);
        const pr = upstream.headers.get("PAYMENT-RESPONSE");
        if (pr) out.set("PAYMENT-RESPONSE", pr);
        return new Response(body, { status: upstream.status, headers: out });
      },
    },
  },
});
```
The `/api/public/*` prefix bypasses Lovable's published-site auth gate — that's what we want.
Do NOT add auth middleware.

X402 SVM EXACT SCHEME — locked-in tx shape (PayAI rejects anything else):
Exactly 3 instructions in this order, no Memo, compute unit limit ≤ 40_000:
```ts
import { Connection, PublicKey, TransactionMessage, VersionedTransaction, ComputeBudgetProgram } from "@solana/web3.js";
import { createTransferCheckedInstruction, getAssociatedTokenAddressSync, TOKEN_PROGRAM_ID } from "@solana/spl-token";

const conn = new Connection(import.meta.env.VITE_SOLANA_RPC_URL!, "confirmed");
const payer = new PublicKey(embeddedAddress);
const feePayer = new PublicKey(requirement.extra.feePayer); // facilitator's Solana pubkey
const mint = new PublicKey(requirement.asset);              // Devnet USDC
const payTo = new PublicKey(requirement.payTo);

const sourceAta = getAssociatedTokenAddressSync(mint, payer, true);
const destAta   = getAssociatedTokenAddressSync(mint, payTo, true);

const ixs = [
  ComputeBudgetProgram.setComputeUnitLimit({ units: 40_000 }),
  ComputeBudgetProgram.setComputeUnitPrice({ microLamports: 1 }),
  createTransferCheckedInstruction(sourceAta, mint, destAta, payer,
    BigInt(requirement.amount), 6, [], TOKEN_PROGRAM_ID),
];

const { blockhash } = await conn.getLatestBlockhash("confirmed");
const msg = new TransactionMessage({
  payerKey: feePayer,
  recentBlockhash: blockhash,
  instructions: ixs,
}).compileToV0Message();
const tx = new VersionedTransaction(msg);
```
Common failures if you deviate: extra Memo ix → "invalid_payload"; compute limit > 40_000 →
"invalid_payload"; wrong feePayer → "invalid_signature".

X402 V2 ENVELOPE (base64-encoded into the `PAYMENT-SIGNATURE` header):
```ts
const envelope = {
  x402Version: 2,
  accepted: requirement,           // echo the exact requirement you picked from accepts[]
  payload: { transaction: signedTxB64 },
};
const header = btoa(JSON.stringify(envelope));
```
NOT `{ scheme, network, payload }` at top level — that's v1 and PayAI rejects it as
`invalid_payload`.

4-STEP UI FLOW (always log each step visibly):
1. Challenge — `GET /api/public/x402-proxy` → expect 402 → parse `{ x402Version:2, accepts, error }`.
   Pick `accepts[]` where `network === "solana-devnet"` && `scheme === "exact"`.
2. Sign — build the tx above, `embedded.signTransaction(tx)`, base64-serialize `tx.serialize()`.
3. Retry — `GET /api/public/x402-proxy` with header `PAYMENT-SIGNATURE: <base64 envelope>`.
4. Settle — on 200, read `PAYMENT-RESPONSE` header, base64-decode → `{ success, transaction, network, payer }`.
   Link the tx to `https://explorer.solana.com/tx/${transaction}?cluster=devnet`.

On any non-200 retry, surface the response body verbatim in the flow log — facilitator errors
(`invalid_payload`, `insufficient_funds`, `invalid_signature`) are the only signal you get.

FUND FLOW UX (before unlock):
- Show the user's Privy Solana address prominently with a copy button.
- Link "Get Devnet USDC" to https://faucet.circle.com/ (choose Solana Devnet) — arrival ~10s.
- Link "Get Devnet SOL" to https://faucet.solana.com — only needed for ATA rent on first-ever unlock.
- "Refresh balance" button that polls USDC balance on click; do NOT auto-poll.

CREATIVE PAYLOAD (what the unlock reveals)
The unlocked payload is the working demo of 'Gasless Release Commits': Commit video edits onchain transparently with zero gas cost for creators. Build a single card/panel that renders the creative artefact (text, image, audio snippet, JSON, or interactive canvas — pick whatever best fits the version control discipline). Generate it deterministically client-side, OR make one optional LOVABLE_API_KEY call from a server function per unlock. Keep the payload self-contained — no external accounts, no user uploads, no storage.

TERMINOLOGY (user-facing copy)
- Say "Lovable Cloud", "backend", "sign in", "unlock". Never "Supabase", "wallet extension",
  "seed phrase", "gas fee". Sponsored SOL + a 0.01 USDC unlock is the whole story.

DELIVERABLES
- Working demo at `/` — sign in → fund → unlock → see the creative payload.
- 4-step flow log visible during unlock.
- Every settled tx links to Solana Explorer (devnet cluster).
- No follow-up prompts. Ships in one message.
Appendix · Market

Market sizing.

TAM
$1.1B
video editing software market
SAM
$95M
version control and asset tracking
SOM
$6M
editors adopting onchain commits

Indicative figures for hackathon pitches — refine with your own research before raising.

See also

Adjacent entries.