Got Music

Web3 music marketplace. Cross-chain payments, seller payment choice. Decentralized on Base.

Got Music

Created At

ETHOnline 2025

Project Description

🎵 GotMusic: Clear Project Overview

GotMusic is a decentralized music marketplace that revolutionizes how music producers monetize their work and how fans discover new music. Built for ETHOnline 2025, it combines cutting-edge blockchain technology with professional audio quality to create a Web3-native platform that bridges the gap between traditional music streaming and decentralized ownership.

At its core, GotMusic functions like "Spotify meets OpenSea for music producers."

Producers upload their beats, samples, and tracks as high-quality WAV or AIFF files, which are then encrypted and stored on IPFS (InterPlanetary File System) for true decentralization. Each upload creates an immutable blockchain attestation using Ethereum's Attestation Service (EAS), providing verifiable provenance and ownership records.

Buyers can browse the catalog, listen to 30-second previews without needing a wallet, and purchase full tracks using various cryptocurrencies including PYUSD (PayPal's stablecoin), USDC, or ETH across multiple blockchain networks.

The platform's blockchain infrastructure is built on a comprehensive EAS attestation system with five deployed resolver contracts on Base Mainnet:

Content Upload Resolver (0x166782ffD3D0Cf4A48b2bf4FC9929ED5374e2052)

  • Schema: 0xa4f0cc13cdd748ca464f3a68dc543c94a33662b3f4f3cc3a63246e654e98b4e6
  • Creates immutable records of every music file upload, tracking file hashes, content types, and licensing information

License Receipt Resolver (0x2de43c7d4C4F5602EF538E85C0d8D78e50A41D18)

  • Schema: 0xa6bedff8a7aeff07860da391aaed576f47982f35e9119f5e3c2facbb07417728
  • Generates blockchain-verified purchase receipts that buyers use to decrypt and access their purchased content

Vendor Status Resolver (0xD64BA17E7a25E8F5b8da04AB5e64Ac7e5C0bef23)

  • Schema: 0x96c49253f6c997eca8dcf8798f22ad9e22f465b6f2e58aaf810f835c582b2164
  • Manages producer verification and reputation scoring

Content Flag Resolver (0xC994f36B9de94Fc751122b196BeBC27D7e9A90f4)

  • Schema: 0x59354c5ee8315da7dadc048be90d60ad31412284213fcb3b4c807fcbdb24b6c9
  • Enables community-driven content moderation

Wallet Verification Resolver (0xd8FFCfB067F0b4EeeFC06ac74598e537b421a9A4)

  • Schema: 0x9ba441e691610a3ee33b88d78410a208dbcbaae9affed65b9eb546efaa5a497b
  • Handles multi-type wallet attestations including KYC, social verification, and biometric authentication

The platform's core infrastructure is powered by essential Web3 APIs and services:

Lit Protocol - Decentralized access control and encryption

  • Encrypts music files with access control conditions
  • Enables secure content decryption based on blockchain ownership
  • Provides key management for encrypted asset access

Lighthouse + IPFS - Decentralized file storage

  • Stores encrypted music files on IPFS network
  • Provides immutable, censorship-resistant content delivery
  • Ensures files remain accessible even if centralized services fail

Avail Nexus - Cross-chain routing and liquidity

  • Enables multi-currency payments across different blockchains
  • Provides cross-chain liquidity for seamless transactions
  • Supports various stablecoins and cryptocurrencies

Blockscout - Blockchain explorer and analytics

  • Tracks all transactions and attestations on Base Chain
  • Provides transparent audit trail for all platform activities
  • Enables users to verify their purchases and ownership

PYUSD Integration - PayPal's stablecoin payments

  • Contract: 0x6c3ea9036406852006290770bedfcaba0e23a0e8 (Ethereum Mainnet)
  • Provides stable pricing and global payment accessibility
  • Enables traditional finance integration with Web3

What sets GotMusic apart is its professional-grade audio processing pipeline that includes LUFS normalization (following Spotify's -14 dB standard), multiple quality tiers for different use cases, and real-time waveform visualization.

The platform supports both web and mobile applications, with a React Native mobile app that includes biometric authentication, passkey integration, and secure local storage. Every aspect of the platform is designed with decentralization in mind, from the IPFS storage for music files to the EAS attestations for licensing and provenance, creating a truly Web3-native music ecosystem that gives artists more control over their work and fans true ownership of their purchases.

How it's Made

🎯 GotMusic: What We Built & Why - Strategic Analysis

🎯 GotMusic: What We Went For & Why - Strategic Analysis

🚀 ORIGINAL VISION vs REALITY

🎵 What We Set Out To Build

"Spotify meets OpenSea for music producers" - A Web3 music marketplace with:

  • Professional Audio Quality: LUFS normalization, multi-tier quality
  • Blockchain Integration: EAS attestations, multi-chain payments
  • Cross-Platform: Web, mobile, and desktop (JUCE C++)
  • Decentralized Storage: IPFS + encryption
  • Professional UI: Design system with Storybook

✅ What We Actually Built

A comprehensive Web3 music platform with:

  • Complete EAS Attestation System: 5 schemas deployed and working
  • Multi-Chain Architecture: Base + Ethereum + Avail Nexus
  • Modern Tech Stack: Next.js 16, React 19, React Native, TypeScript
  • Professional Audio Pipeline: LUFS normalization, quality tiers
  • Hybrid Storage: R2/S3 + IPFS (with plans for full IPFS migration)
  • Comprehensive Documentation: 1,400+ lines of architecture docs

🔧 HOW IT'S MADE - TECHNICAL IMPLEMENTATION

🏗️ Core Architecture Stack

Monorepo Structure (Turbo + Yarn 4.3.1)

apps/
  web/          # Next.js 16 + React 19 + TypeScript
  mobile/       # React Native + Expo 53 + NativeWind
  worker/       # Background processing worker
packages/
  ui/           # Shared Radix UI components + Design tokens
  api/          # TypeScript API client + Zod validation
  tokens/       # Design system tokens (Style Dictionary)
  fixtures/     # Test data and mocks

Database Layer (Drizzle ORM + PostgreSQL)

// Schema Definition
export const assetsPg = pgTable("assets", {
  id: pgText("id").primaryKey(),
  title: pgText("title").notNull(),
  description: pgText("description"),
  price: pgDecimal("price", { precision: 18, scale: 6 }),
  currency: pgText("currency").notNull().default("PYUSD"),
  status: assetStatusEnum("status").notNull().default("draft"),
  createdAt: pgTimestamp("created_at").notNull().defaultNow(),
});

export const assetFilesPg = pgTable("asset_files", {
  id: pgText("id").primaryKey(),
  assetId: pgText("asset_id").notNull(),
  kind: assetFileKindEnum("kind").notNull(), // original, preview, artwork, waveform
  storageKey: pgText("storage_key").notNull(),
  ipfsCid: pgText("ipfs_cid"),
  ipfsGatewayUrl: pgText("ipfs_gateway_url"),
  bytes: pgInteger("bytes"),
  mime: pgText("mime"),
  checksum: pgText("checksum"),
});

🔐 Blockchain Integration

EAS Attestation System (Base Mainnet)

// ContentUploadResolver.sol
contract ContentUploadResolver {
    function onAttest(
        IEASLike.Attestation calldata att,
        uint256 value
    ) external payable onlyEAS returns (bool) {
        (
            string memory assetId,
            string memory fileHash,
            string memory contentType,
            uint256 fileSize,
            string memory title,
            string memory license_,
            bool original
        ) = abi.decode(att.data, (string, string, string, uint256, string, string, bool));
        
        // Validation and state management
        bytes32 assetKey = keccak256(bytes(assetId));
        require(!_uploadedAssets[assetKey], "Asset already uploaded");
        _uploadedAssets[assetKey] = true;
        _uploaderCount[att.attester] += 1;
        
        emit ContentUploaded(att.attester, assetId, fileHash, block.timestamp);
        return true;
    }
}

Multi-Chain Payment Architecture

// PYUSD Integration (Ethereum Mainnet)
const PYUSD_CONTRACT_ADDRESS = "0x6c3ea9036406852006290770bedfcaba0e23a0e8";
const PYUSD_ABI = [
  "function balanceOf(address owner) view returns (uint256)",
  "function transfer(address to, uint256 amount) returns (bool)",
  "function approve(address spender, uint256 amount) returns (bool)"
];

// Avail Nexus Cross-Chain Routing
import { NexusClient } from "@avail-project/nexus-core";
const nexusClient = new NexusClient({
  network: "mainnet",
  rpcUrl: process.env.AVAIL_RPC_URL
});

🎵 Audio Processing Pipeline

LUFS Normalization Engine

class LUFSNormalizer {
  private targetLUFS = -14.0; // Spotify standard
  
  async normalizeAudio(audioBuffer: AudioBuffer): Promise<AudioBuffer> {
    const lufs = await this.measureLUFS(audioBuffer);
    const gainReduction = this.targetLUFS - lufs;
    const gainMultiplier = Math.pow(10, gainReduction / 20);
    
    return this.applyGain(audioBuffer, gainMultiplier);
  }
  
  private async measureLUFS(buffer: AudioBuffer): Promise<number> {
    // Implement EBU R128 loudness measurement
    const samples = buffer.getChannelData(0);
    const rms = this.calculateRMS(samples);
    return 20 * Math.log10(rms) - 0.691; // Convert to LUFS
  }
}

Quality Tier Management

interface QualityTier {
  name: 'preview' | 'streaming' | 'download' | 'master';
  bitrate: number;
  format: 'AAC' | 'FLAC' | 'WAV';
  lufs: number;
  useCase: string;
}

const QUALITY_TIERS: QualityTier[] = [
  { name: 'preview', bitrate: 128, format: 'AAC', lufs: -14, useCase: '30s previews' },
  { name: 'streaming', bitrate: 320, format: 'AAC', lufs: -14, useCase: 'Full playback' },
  { name: 'download', bitrate: 1411, format: 'FLAC', lufs: -14, useCase: 'Licensed content' },
  { name: 'master', bitrate: 2304, format: 'WAV', lufs: -14, useCase: 'Studio quality' }
];

🔒 Encryption & Access Control

Lit Protocol Integration

// Lit Protocol Service
export class LitProtocolService {
  private litNodeClient: LitNodeClient;
  
  async encryptAsset(
    file: File,
    accessControlConditions: AccessControlConditions
  ): Promise<EncryptionResult> {
    const authSig = await this.getAuthSig();
    const { ciphertext, dataToEncryptHash } = await encryptString({
      authSig,
      accessControlConditions,
      chain: "base",
      dataToEncrypt: await file.text(),
    });
    
    return {
      ciphertext,
      dataToEncryptHash,
      accessControlConditions,
    };
  }
  
  async decryptAsset(
    ciphertext: string,
    dataToEncryptHash: string,
    accessControlConditions: AccessControlConditions
  ): Promise<string> {
    const authSig = await this.getAuthSig();
    return await decryptToString({
      authSig,
      accessControlConditions,
      chain: "base",
      ciphertext,
      dataToEncryptHash,
    });
  }
}

🌐 Storage Architecture

Hybrid IPFS + CDN Strategy

// Storage Service
export class StorageService {
  private pinata: PinataSDK;
  private r2: R2Client;
  
  async uploadFile(file: File): Promise<StorageResult> {
    // 1. Upload to IPFS via Pinata
    const ipfsResult = await this.pinata.uploadFile(file);
    
    // 2. Cache on R2 for performance
    const r2Key = `cache/${ipfsResult.IpfsHash}`;
    await this.r2.putObject(r2Key, file);
    
    return {
      ipfsHash: ipfsResult.IpfsHash,
      ipfsUrl: `https://ipfs.io/ipfs/${ipfsResult.IpfsHash}`,
      cacheUrl: `https://cdn.gotmusic.com/${r2Key}`,
      gatewayUrl: `https://gateway.pinata.cloud/ipfs/${ipfsResult.IpfsHash}`
    };
  }
  
  async getFile(hash: string): Promise<File> {
    // Try cache first, fallback to IPFS
    try {
      return await this.r2.getObject(`cache/${hash}`);
    } catch {
      return await this.pinata.getFile(hash);
    }
  }
}

📱 Cross-Platform Implementation

Web Player (Next.js 16 + Web Audio API)

// Web Audio Player
export class WebAudioPlayer {
  private audioContext: AudioContext;
  private audioBuffer: AudioBuffer | null = null;
  private sourceNode: AudioBufferSourceNode | null = null;
  
  async loadAudio(file: File): Promise<void> {
    const arrayBuffer = await file.arrayBuffer();
    this.audioBuffer = await this.audioContext.decodeAudioData(arrayBuffer);
    this.renderWaveform();
  }
  
  private renderWaveform(): void {
    if (!this.audioBuffer) return;
    
    const canvas = document.getElementById('waveform') as HTMLCanvasElement;
    const ctx = canvas.getContext('2d')!;
    const data = this.audioBuffer.getChannelData(0);
    
    // Render waveform visualization
    ctx.clearRect(0, 0, canvas.width, canvas.height);
    ctx.strokeStyle = '#00ff88';
    ctx.lineWidth = 2;
    ctx.beginPath();
    
    for (let i = 0; i < data.length; i += 100) {
      const x = (i / data.length) * canvas.width;
      const y = (data[i] * canvas.height / 2) + canvas.height / 2;
      ctx.lineTo(x, y);
    }
    ctx.stroke();
  }
}

Mobile Player (React Native + Expo Audio)

// Mobile Audio Player
export class MobileAudioPlayer {
  private sound: Audio.Sound | null = null;
  
  async loadAudio(uri: string): Promise<void> {
    const { sound } = await Audio.Sound.createAsync(
      { uri },
      { shouldPlay: false, isLooping: false }
    );
    this.sound = sound;
  }
  
  async play(): Promise<void> {
    if (this.sound) {
      await this.sound.playAsync();
    }
  }
  
  async seekTo(positionMillis: number): Promise<void> {
    if (this.sound) {
      await this.sound.setPositionAsync(positionMillis);
    }
  }
}

🔧 Development Infrastructure

CI/CD Pipeline (GitHub Actions)

name: Build and Deploy
on: [push, pull_request]

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: '20'
          cache: 'yarn'
      - run: corepack enable
      - run: yarn install --immutable
      - run: yarn tokens:build
      - run: yarn build
      - run: yarn typecheck
      - run: yarn lint
      - run: yarn test

Testing Strategy

// E2E Tests (Playwright)
test('user can browse and purchase music', async ({ page }) => {
  await page.goto('/catalog');
  await page.click('[data-testid="asset-card"]');
  await page.click('[data-testid="purchase-button"]');
  await page.fill('[data-testid="wallet-address"]', '0x...');
  await page.click('[data-testid="confirm-purchase"]');
  await expect(page.locator('[data-testid="success-message"]')).toBeVisible();
});

// Unit Tests (Jest)
describe('LUFSNormalizer', () => {
  it('should normalize audio to -14 LUFS', async () => {
    const normalizer = new LUFSNormalizer();
    const audioBuffer = createTestAudioBuffer();
    const normalized = await normalizer.normalizeAudio(audioBuffer);
    const lufs = await normalizer.measureLUFS(normalized);
    expect(lufs).toBeCloseTo(-14, 1);
  });
});

📊 WHAT WORKED vs WHAT DIDN'T

✅ MAJOR WINS

1. EAS Attestation System

  • Status: ✅ COMPLETE
  • Impact: High - True Web3 value proposition
  • Why It Worked: Clear blockchain use case, well-documented

2. Modern Tech Stack

  • Status: ✅ COMPLETE
  • Impact: High - Developer experience, performance
  • Why It Worked: Latest tools, good documentation

3. Comprehensive Documentation

  • Status: ✅ COMPLETE
  • Impact: High - Maintainability, onboarding
  • Why It Worked: Systematic approach, clear structure

4. Multi-Platform Architecture

  • Status: ✅ COMPLETE
  • Impact: High - Broader market reach
  • Why It Worked: Shared codebase, consistent UX

🟡 PARTIAL WINS

1. Audio Quality Pipeline

  • Status: 🟡 PARTIAL
  • What Worked: LUFS normalization, quality tiers
  • What Didn't: Full waveform visualization, desktop app
  • Why: Scope too ambitious for hackathon timeline

2. Storage Architecture

  • Status: 🟡 PARTIAL
  • What Worked: R2/S3 integration, file management
  • What Didn't: Full IPFS migration
  • Why: Performance vs decentralization trade-off

3. Payment Integration

  • Status: 🟡 PARTIAL
  • What Worked: PYUSD contract integration
  • What Didn't: Full payment flow, multi-currency
  • Why: Complex blockchain integration

❌ MAJOR CHALLENGES

1. UploadThing Integration

  • Status: ❌ REMOVED
  • What Happened: Complex integration, performance issues
  • Recovery: Direct IPFS integration via Pinata
  • Lesson: Simpler is better for hackathons

2. Desktop App (JUCE C++)

  • Status: ❌ DEFERRED
  • What Happened: Too complex for timeline
  • Recovery: Focus on web/mobile first
  • Lesson: Scope management critical

3. Full IPFS Migration

  • Status: ❌ DEFERRED
  • What Happened: Performance concerns
  • Recovery: Hybrid approach with IPFS plan
  • Lesson: Gradual migration better than big bang

🎯 STRATEGIC INSIGHTS

1. 🏆 What Made Us Successful

  • Clear Vision: "Spotify meets OpenSea" was compelling
  • Modern Tech: Latest tools gave us competitive advantage
  • Blockchain Focus: EAS attestations provided real Web3 value
  • Documentation: Comprehensive docs enabled rapid development
  • AI-Assisted Development: Cursor + AI accelerated development

2. 🚧 What Slowed Us Down

  • Scope Creep: Too many features for hackathon timeline
  • Complex Integrations: UploadThing, multi-chain complexity
  • Perfectionism: Over-engineering some components
  • Technology Learning Curve: New tools required learning time

3. 🎯 What We'd Do Differently

  • Start Simpler: Basic audio player first, then add features
  • Focus on Core: EAS + basic marketplace, then expand
  • Iterative Approach: Build, test, iterate rather than plan everything
  • User Testing: Get feedback earlier in development

🚀 GOING FORWARD

✅ IMMEDIATE PRIORITIES

  1. IPFS Migration: Complete decentralization (3-week plan)
  2. Payment Flow: Finish PYUSD integration
  3. Audio Polish: Complete waveform visualization
  4. User Testing: Get real user feedback

🔄 MEDIUM-TERM GOALS

  1. Desktop App: JUCE C++ implementation
  2. Advanced Audio: Professional mastering tools
  3. Mobile Polish: Enhanced mobile experience
  4. Analytics: Comprehensive usage tracking

🎯 LONG-TERM VISION

  1. Industry Standard: Compete with Spotify/Apple Music
  2. Web3 Native: Fully decentralized music ecosystem
  3. Global Scale: Multi-language, multi-currency
  4. Developer Platform: API for third-party integrations

💡 KEY LESSONS LEARNED

1. 🎯 Scope Management

  • Start small, build up rather than planning everything
  • Focus on core value before adding features
  • User feedback is more valuable than perfect planning

2. 🏗️ Architecture Decisions

  • Modern tech stack pays off in long run
  • Documentation is critical for team velocity
  • Blockchain integration requires careful planning

3. 🚀 Development Process

  • AI-assisted development accelerates progress
  • Iterative approach better than waterfall
  • Testing early prevents major issues later

The bottom line: We built a solid foundation for a Web3 music marketplace, with some scope adjustments needed for the hackathon timeline. The core vision remains strong, and we have a clear path forward.

background image mobile

Join the mailing list

Get the latest news and updates