🎵 Music & Sound Design · environmental audio

Blockchain Soundscapes

Share and license unique recorded soundscapes with verified origin and ownership on blockchain.

Monad Testnet smart contract· onchain logic
Section · Onchain

The primitive.

full primer →

Environmental audio gets a tiny Solidity contract deployed to Monad Testnet; musicians see a 'verified onchain' badge with the live contract address and a one-tap MonadExplorer link.

Why this primitiveImmutable records authenticate soundscape provenance and creator rights.

Kernel
a Solidity contract deployed to Monad Testnet via MetaMask private key, then verified on Etherscan
Drives the UI as
a 'verified onchain' badge with the live contract address and an Etherscan link
Appendix · Secrets

Required keys.

METAMASK_PRIVATE_KEY
Exported from MetaMask. Fund on Monad Testnet via the Monad faucet.
open ↗
MONAD_RPC_URL
Monad Testnet HTTPS endpoint. Default: https://testnet-rpc.monad.xyz — use a provider endpoint for heavier load.
open ↗
ETHERSCAN_API_KEY
Etherscan v2 key — covers MonadScan too. Required for npx hardhat verify.
open ↗
PRIVY_APP_ID
Enables Google sign-in and a Monad-Testnet embedded wallet.
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 "Blockchain Soundscapes" in ONE Lovable message. Single-page demo.

CONCEPT
Share and license unique recorded soundscapes with verified origin and ownership on blockchain.
Discipline: Music & Sound Design (environmental audio).
Onchain primitive: Monad Testnet smart contract. Why this primitive: Immutable records authenticate soundscape provenance and creator rights.

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 Monad Testnet, verified on MonadScan.
- Privy is always the auth + sponsored-tx layer (Google login, embedded wallet). Runtime gas is sponsored by the app — users never touch MON.
- 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).
- SSR-safe Privy mount is mandatory. Never import @privy-io/react-auth at
  module scope of a route file — it crashes SSR. Use
  lazy(() => import('./privy-client-entry')) inside <ClientOnly> + <Suspense>,
  and put <PrivyProvider> only inside privy-client-entry.tsx.
- PrivyProvider config: pass a viem `defineChain` for Monad Testnet as
  `defaultChain` AND include it in `supportedChains` — Privy rejects unknown
  chains. Do NOT stub `defaultChain` as `{ id, name }`:
    import { defineChain } from 'viem';
    const monadTestnet = defineChain({
      id: 10143,
      name: 'Monad Testnet',
      nativeCurrency: { name: 'Monad', symbol: 'MON', decimals: 18 },
      rpcUrls: { default: { http: ['https://testnet-rpc.monad.xyz'] } },
      blockExplorers: { default: { name: 'MonadExplorer', url: 'https://testnet.monadexplorer.com' } },
    });
    <PrivyProvider appId={import.meta.env.VITE_PRIVY_APP_ID}
      config={{ loginMethods:['google','email'],
                embeddedWallets:{ ethereum:{ createOnLogin:'users-without-wallets' } },
                appearance:{ theme:'dark' },
                defaultChain: monadTestnet,
                supportedChains: [monadTestnet] }}>
- Read the embedded wallet from useWallets, not user.wallet:
    const embedded = wallets.find(w => w.walletClientType === 'privy');
- Every send goes through Privy `useSendTransaction` with BOTH `address`
  and `sponsor: true`, and `chainId: 10143` per-call. Wrap in a 45s
  Promise.race timeout whose reject message names the exact dashboard
  toggles so the failure mode is self-diagnosing:
    await Promise.race([
      sendTransaction(
        { to, data, chainId: 10143 },
        { address: embedded.address, sponsor: true }
      ),
      new Promise((_, r) => setTimeout(() => r(new Error(
        "Privy sendTransaction timed out after 45s. Enable Gas sponsorship -> App pays -> Monad Testnet -> Allow transactions from the client."
      )), 45_000)),
    ]);
- Do NOT pass uiOptions:{ showWalletUIs:false } — it aborts with
  "signal is aborted without reason". The approval sheet still shows on
  the embedded-EOA path; the sponsored fee reads US$0.00.
- Do NOT add ZeroDev / Pimlico / SmartWalletsProvider / a paymaster URL.
  Privy natively sponsors gas on Monad Testnet with the dashboard toggles
  below — no external paymaster stack needed.
- DASHBOARD PREREQUISITE (one-time): Privy dashboard -> Gas sponsorship
  -> App pays -> add "Monad Testnet" -> toggle "Allow transactions from
  the client" ON. Without this, sendTransaction hangs silently and the
  45s timeout above fires with the exact remediation string.
- Hardhat in /contracts (kept outside the Vite bundle). Install
  `@nomicfoundation/hardhat-toolbox` AND `@nomicfoundation/hardhat-verify@latest`
  (>=3.x — older versions still hit Etherscan v1 and fail with
  "You are using a deprecated V1 endpoint, switch to Etherscan API V2").
- hardhat.config.cjs uses the Etherscan v2 single-key shape (one key covers
  every chain, including MonadScan). Set `bytecodeHash: "ipfs"` so Sourcify
  (MonadVision) verification also works, and register `monadTestnet` under
  `etherscan.customChains`:
    require("@nomicfoundation/hardhat-toolbox");
    require("@nomicfoundation/hardhat-verify");
    module.exports = {
      solidity: { version: "0.8.24", settings: {
        optimizer: { enabled: true, runs: 200 },
        metadata: { bytecodeHash: "ipfs" },
      } },
      networks: { monadTestnet: {
        url: process.env.MONAD_RPC_URL || "https://testnet-rpc.monad.xyz",
        accounts: [process.env.METAMASK_PRIVATE_KEY.startsWith("0x")
          ? process.env.METAMASK_PRIVATE_KEY : "0x" + process.env.METAMASK_PRIVATE_KEY],
        chainId: 10143,
      } },
      etherscan: {
        apiKey: process.env.ETHERSCAN_API_KEY,
        customChains: [{
          network: "monadTestnet",
          chainId: 10143,
          urls: {
            apiURL: "https://api.etherscan.io/v2/api?chainid=10143",
            browserURL: "https://testnet.monadscan.com",
          },
        }],
      },
      sourcify: {
        enabled: true,
        apiUrl: "https://sourcify-api-monad.blockvision.org",
        browserUrl: "https://monadvision.com",
      },
    };
- Deploy: `npx hardhat run scripts/deploy.cjs --network monadTestnet`.
- Verify (run RIGHT AFTER deploy, no constructor args for these contracts):
  `npx hardhat verify --network monadTestnet <address>`
  The verify command may print a warning but usually succeeds on both
  Sourcify (MonadVision) and MonadScan — confirm at
  `https://testnet.monadscan.com/address/<address>#code`.
- Write the deployed address to `src/data/contract.json` so the UI links to
  `https://testnet.monadexplorer.com/address/<address>`.

CONTRACT (contracts/BlockchainSoundscapes.sol):
```solidity
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;
/// @title BlockchainSoundscapes
/// @notice Share and license unique recorded soundscapes with verified origin and ownership on blockchain.
/// @notice Built during the Creative AI & Quantum Hackathon organised by StreetKode Fam during Indian Krump Festival 14
contract BlockchainSoundscapes {
    event Logged(address indexed author, string cid, uint256 at);
    /// @notice Built during the Creative AI & Quantum Hackathon organised by StreetKode Fam during Indian Krump Festival 14
    function log(string calldata cid) external {
        emit Logged(msg.sender, cid, block.timestamp);
    }
}
```

USER FLOW
1. Land on page -> 'Sign in with Google' (Privy) -> embedded wallet auto-provisioned.
2. User performs a environmental audio action; the app calls `log(payload)` on the contract via Privy sponsored tx and shows the MonadExplorer link as proof.
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):
- METAMASK_PRIVATE_KEY  Monad Testnet deployer key. Fund it: https://faucet.monad.xyz
- MONAD_RPC_URL         Monad Testnet HTTPS endpoint. Default: https://testnet-rpc.monad.xyz. For heavier load use a provider endpoint (Alchemy / QuickNode / Chainstack) — public RPC throttles under hackathon traffic.
- ETHERSCAN_API_KEY     Etherscan v2 key covers MonadScan too. Get: https://etherscan.io/myapikey
- PRIVY_APP_ID          Google sign-in + embedded wallet. 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
$500M
environmental sound libraries
SAM
$120M
soundscape licensing
SOM
$15M
blockchain soundscape users

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

See also

Adjacent entries.