🎬 Filmmaking & Animation · loop cycles

AnimCycle Provenance

Mint NFT walk and run cycles to protect proprietary animation loops and licensing.

NFT provenance mint· onchain authorship
Section · Onchain

The primitive.

full primer →

Filmmakers mint each loop cycles as an ERC-721 token on Sepolia pointing at an IPFS CID, so authorship and timestamp are provable from a single Arbiscan link.

Why this primitiveERC-721 tokens secure unique cycle animations with creator provenance on Arbitrum Sepolia.

Kernel
an ERC-721 contract on Arbitrum Sepolia that mints a creator-owned token pointing at an IPFS CID, verified on Arbiscan
Drives the UI as
a 'mint to claim authorship' button that returns the tokenId, owner address, and Arbiscan link
Appendix · Secrets

Required keys.

METAMASK_PRIVATE_KEY
Exported from MetaMask. Fund on Arbitrum Sepolia via the Coinbase faucet.
open ↗
ARBITRUM_SEPOLIA_RPC_URL
Alchemy Arbitrum Sepolia HTTPS endpoint (or https://sepolia-rollup.arbitrum.io/rpc).
open ↗
ETHERSCAN_API_KEY
Single Etherscan v2 key — covers Arbiscan (chainId 421614) with no extra key.
open ↗
PRIVY_APP_ID
Enables Google sign-in and sponsored Arbitrum Sepolia transactions.
open ↗
PINATA_JWT
Pins images / JSON / manifests to IPFS.
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 "AnimCycle Provenance" in ONE Lovable message. Single-page demo.

CONCEPT
Mint NFT walk and run cycles to protect proprietary animation loops and licensing.
Discipline: Filmmaking & Animation (loop cycles).
Onchain primitive: NFT provenance mint. Why this primitive: ERC-721 tokens secure unique cycle animations with creator provenance on Arbitrum Sepolia.

5-CREDIT BUDGET (HARD LIMIT):
- ONE single-page app. No router, no Lovable Cloud, no database, no auth flows beyond Privy drop-in.
- ONE Solidity contract, <=80 lines, deployed to Arbitrum Sepolia (chainId 421614), verified on Arbiscan.
- Privy is always the auth + sponsored-tx layer (Google login, embedded wallet).
- Pinata/IPFS only if the idea genuinely needs to store a file or metadata.
- At most ONE AI call per user action (use Lovable AI Gateway with LOVABLE_API_KEY if AI is part of the idea).
- Skip tests, skip CI, skip docs pages. Ship the demo, nothing else.

STACK
- React + Vite single page (the index route).
- Privy embedded wallet wraps `<App />` in src/main.tsx. `defaultChain` needs
  `as never` because Privy's type is narrow:
    <PrivyProvider appId={import.meta.env.VITE_PRIVY_APP_ID}
      config={{ loginMethods:['google'],
                embeddedWallets:{ethereum:{createOnLogin:'users-without-wallets'}},
                defaultChain: { id: 421614, name:'Arbitrum Sepolia' } as never }}>
- All txs go through Privy sponsorship. BOTH flags are required:
    const { sendTransaction } = useSendTransaction();
    const { wallets } = useWallets();
    const embedded = wallets.find(w => w.walletClientType === 'privy');
    await sendTransaction(
      { to, data, chainId: 421614 },
      { sponsor: true, address: embedded.address },   // BOTH required
    );
  Without `address`, Privy can route through a non-embedded wallet and the
  user sees "Add funds on Arbitrum Sepolia" even on testnet.
- Privy dashboard (one-time): enable Arbitrum Sepolia under Chains AND add a
  Gas Sponsorship (Paymasters) policy for chainId 421614 — "Sponsor all
  transactions" is fine for a hackathon demo. Code flags alone are not enough.
- src/lib/pinata.ts uploads via `fetch('https://api.pinata.cloud/pinning/pinFileToIPFS', { method:'POST', headers:{ Authorization: `Bearer ${import.meta.env.VITE_PINATA_JWT}` }, body: fd })`.
- Hardhat in /contracts (kept outside the Vite bundle). Install
  `@nomicfoundation/hardhat-ethers` AND `@nomicfoundation/hardhat-verify` (>=2.x).
  DO NOT install `@nomicfoundation/hardhat-toolbox` — it drags Hardhat 3 peers.
- hardhat.config.cjs — Arbitrum Sepolia + Etherscan v2 single-key:
    require("@nomicfoundation/hardhat-ethers");
    require("@nomicfoundation/hardhat-verify");
    const pk = process.env.DEPLOYER_PRIVATE_KEY || process.env.METAMASK_PRIVATE_KEY;
    module.exports = {
      solidity: { version: "0.8.24", settings: { optimizer: { enabled: true, runs: 200 } } },
      networks: { arbitrumSepolia: {
        url: process.env.ARBITRUM_SEPOLIA_RPC_URL || "https://sepolia-rollup.arbitrum.io/rpc",
        accounts: pk ? [pk.startsWith("0x") ? pk : "0x" + pk] : [],
        chainId: 421614,
      } },
      etherscan: {
        apiKey: process.env.ETHERSCAN_API_KEY,          // single Etherscan v2 key covers Arbiscan
                                                        // MUST be a plain string, not { arbitrumSepolia: ... }
        customChains: [{
          network: "arbitrumSepolia", chainId: 421614,
          urls: {
            apiURL: "https://api.etherscan.io/v2/api?chainid=421614",
            browserURL: "https://sepolia.arbiscan.io",
          },
        }],
      },
      sourcify: { enabled: false },
    };
- scripts/deploy.cjs — deploy AND write src/data/contract.json so the UI wires
  up with no manual paste:
    const hre = require("hardhat");
    const fs = require("fs"); const path = require("path");
    async function main() {
      const c = await hre.ethers.deployContract("AnimCycleProvenance");
      await c.waitForDeployment();
      const address = await c.getAddress();
      const deployTx = c.deploymentTransaction().hash;
      fs.mkdirSync(path.join(__dirname, "..", "src", "data"), { recursive: true });
      fs.writeFileSync(
        path.join(__dirname, "..", "src", "data", "contract.json"),
        JSON.stringify({
          address, deployTx, chainId: 421614, network: "arbitrumSepolia",
          deployedAt: new Date().toISOString(),
          explorer: `https://sepolia.arbiscan.io/address/${address}`,
        }, null, 2) + "\n",
      );
      console.log("deployed", address);
    }
    main().catch(e => { console.error(e); process.exit(1); });
- Run order (single burst):
    bunx hardhat compile
    bunx hardhat run scripts/deploy.cjs --network arbitrumSepolia
    bunx hardhat verify --network arbitrumSepolia <address>
  On verify success it prints "Successfully verified contract … on the block
  explorer" and the source is readable at
  `https://sepolia.arbiscan.io/address/<address>#code`.
- Frontend reads: create a viem public client with the Arbitrum Sepolia RPC too —
  `createPublicClient({ chain: arbitrumSepolia, transport: http(import.meta.env.VITE_ARBITRUM_SEPOLIA_RPC_URL) })`
  (import `arbitrumSepolia` from `viem/chains`).
  Expose the RPC to the client by also setting VITE_ARBITRUM_SEPOLIA_RPC_URL to the same value.
- The UI imports `src/data/contract.json` directly — no env var, no manual paste —
  and links to `https://sepolia.arbiscan.io/address/<address>`.


CONTRACT (contracts/AnimCycleProvenance.sol):
```solidity
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;
import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
/// @title AnimCycleProvenance
/// @notice ERC-721 provenance for: Mint NFT walk and run cycles to protect proprietary animation loops and licensing.
/// @notice Built during the Creative AI & Quantum Hackathon organised by StreetKode Fam during Indian Krump Festival 14
contract AnimCycleProvenance is ERC721 {
    uint256 public nextId;
    mapping(uint256 => string) public cidOf;
    constructor() ERC721("AnimCycleProvenance", "ANIMCY") {}
    /// @notice Built during the Creative AI & Quantum Hackathon organised by StreetKode Fam during Indian Krump Festival 14
    function mint(string calldata cid) external returns (uint256 id) {
        id = ++nextId; cidOf[id] = cid; _safeMint(msg.sender, id);
    }
    function tokenURI(uint256 id) public view override returns (string memory) {
        return string(abi.encodePacked("ipfs://", cidOf[id]));
    }
}
```

USER FLOW
1. Land on page -> 'Sign in with Google' (Privy) -> embedded wallet auto-provisioned on Arbitrum Sepolia.
2. After the user creates a loop cycles artefact, pin the file to IPFS via Pinata, then call `mint(cid)` on the deployed contract through Privy's sponsored transaction. Show tokenId, IPFS preview (`https://gateway.pinata.cloud/ipfs/<cid>`), and Arbiscan mint-tx link.
3. Footer renders: "Built during the Creative AI & Quantum Hackathon organised by StreetKode Fam during Indian Krump Festival 14"

REQUIRED SECRETS (Lovable -> Project Settings -> Secrets):
- DEPLOYER_PRIVATE_KEY  Arbitrum Sepolia deployer key (alias accepted: METAMASK_PRIVATE_KEY).
                        Fund it: https://faucet.quicknode.com/arbitrum/sepolia
                        (alt: https://www.alchemy.com/faucets/arbitrum-sepolia)
- ARBITRUM_SEPOLIA_RPC_URL  Alchemy Arbitrum Sepolia HTTPS endpoint (https://arb-sepolia.g.alchemy.com/v2/<key>)
                        OR the public default https://sepolia-rollup.arbitrum.io/rpc. Create a free app: https://dashboard.alchemy.com/
- ETHERSCAN_API_KEY     Single Etherscan v2 key — verifies on Arbiscan (chainId 421614) with no extra key.
                        Get: https://etherscan.io/myapikey
- PRIVY_APP_ID          Google sign-in + sponsored tx. In the Privy dashboard you MUST:
                          (1) enable Arbitrum Sepolia (421614) under Chains, AND
                          (2) add a Gas Sponsorship (Paymasters) policy for 421614
                              ("Sponsor all transactions" is fine for a hackathon demo).
                        Code flags alone are NOT enough — both dashboard toggles are required.
                        Docs: https://docs.privy.io/llms-full.txt
- PINATA_JWT            IPFS uploads (only if app pins media). Docs: https://docs.pinata.cloud/llms-full.txt

CREDIT (must appear in UI footer AND as NatSpec on every deployed contract):
Built during the Creative AI & Quantum Hackathon organised by StreetKode Fam during Indian Krump Festival 14
Appendix · Market

Market sizing.

TAM
$400B
animation lifecycle asset market
SAM
$3B
animation loop asset marketplaces
SOM
$7M
NFT loop animation ownership platforms

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

See also

Adjacent entries.