Got Music
Web3 music marketplace. Cross-chain payments, seller payment choice. Decentralized on Base.
Problem Statement
🎵GotMusic: Clear Project OverviewGotMusic 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:0xa4f0cc13cdd748ca464f3a68dc543c94a33662b3f4f3cc3a63246e654e98b4e6Creates immutable records of every music file upload, tracking file hashes, content types, and licensing informationLicense Receipt Resolver(0x2de43c7d4C4F5602EF538E85C0d8D78e50A41D18)Schema:0xa6bedff8a7aeff07860da391aaed576f47982f35e9119f5e3c2facbb07417728Generates blockchain-verified purchase receipts that buyers use to decrypt and access their purchased contentVendor Status Resolver(0xD64BA17E7a25E8F5b8da04AB5e64Ac7e5C0bef23)Schema:0x96c49253f6c997eca8dcf8798f22ad9e22f465b6f2e58aaf810f835c582b2164Manages producer verification and reputation scoringContent Flag Resolver(0xC994f36B9de94Fc751122b196BeBC27D7e9A90f4)Schema:0x59354c5ee8315da7dadc048be90d60ad31412284213fcb3b4c807fcbdb24b6c9Enables community-driven content moderationWallet Verification Resolver(0xd8FFCfB067F0b4EeeFC06ac74598e537b421a9A4)Schema:0x9ba441e691610a3ee33b88d78410a208dbcbaae9affed65b9eb546efaa5a497bHandles multi-type wallet attestations including KYC, social verification, and biometric authenticationThe platform's core infrastructure is powered by essential Web3 APIs and services:Lit Protocol- Decentralized access control and encryptionEncrypts music files with access control conditionsEnables secure content decryption based on blockchain ownershipProvides key management for encrypted asset accessLighthouse + IPFS- Decentralized file storageStores encrypted music files on IPFS networkProvides immutable, censorship-resistant content deliveryEnsures files remain accessible even if centralized services failAvail Nexus- Cross-chain routing and liquidityEnables multi-currency payments across different blockchainsProvides cross-chain liquidity for seamless transactionsSupports various stablecoins and cryptocurrenciesBlockscout- Blockchain explorer and analyticsTracks all transactions and attestations on Base ChainProvides transparent audit trail for all platform activitiesEnables users to verify their purchases and ownershipPYUSD Integration- PayPal's stablecoin paymentsContract:0x6c3ea9036406852006290770bedfcaba0e23a0e8(Ethereum Mainnet)Provides stable pricing and global payment accessibilityEnables traditional finance integration with Web3What sets GotMusic apart is its professional-grade audio processing pipelinethat 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.
Solution
🎯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 qualityBlockchain Integration: EAS attestations, multi-chain paymentsCross-Platform: Web, mobile, and desktop (JUCE C++)Decentralized Storage: IPFS + encryptionProfessional UI: Design system with Storybook✅ What We Actually BuiltA comprehensive Web3 music platformwith:Complete EAS Attestation System: 5 schemas deployed and workingMulti-Chain Architecture: Base + Ethereum + Avail NexusModern Tech Stack: Next.js 16, React 19, React Native, TypeScriptProfessional Audio Pipeline: LUFS normalization, quality tiersHybrid 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 StackMonorepo 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 mocksDatabase 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 IntegrationEAS 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 PipelineLUFS Normalization Engineclass 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 Managementinterface 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 ControlLit 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 ArchitectureHybrid 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 ImplementationWeb 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 InfrastructureCI/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 testTesting 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 WINS1. EAS Attestation SystemStatus: ✅ COMPLETEImpact: High - True Web3 value propositionWhy It Worked: Clear blockchain use case, well-documented2. Modern Tech StackStatus: ✅ COMPLETEImpact: High - Developer experience, performanceWhy It Worked: Latest tools, good documentation3. Comprehensive DocumentationStatus: ✅ COMPLETEImpact: High - Maintainability, onboardingWhy It Worked: Systematic approach, clear structure4. Multi-Platform ArchitectureStatus: ✅ COMPLETEImpact: High - Broader market reachWhy It Worked: Shared codebase, consistent UX🟡 PARTIAL WINS1. Audio Quality PipelineStatus: 🟡 PARTIALWhat Worked: LUFS normalization, quality tiersWhat Didn't: Full waveform visualization, desktop appWhy: Scope too ambitious for hackathon timeline2. Storage ArchitectureStatus: 🟡 PARTIALWhat Worked: R2/S3 integration, file managementWhat Didn't: Full IPFS migrationWhy: Performance vs decentralization trade-off3. Payment IntegrationStatus: 🟡 PARTIALWhat Worked: PYUSD contract integrationWhat Didn't: Full payment flow, multi-currencyWhy: Complex blockchain integration❌ MAJOR CHALLENGES1. UploadThing IntegrationStatus: ❌ REMOVEDWhat Happened: Complex integration, performance issuesRecovery: Direct IPFS integration via PinataLesson: Simpler is better for hackathons2. Desktop App (JUCE C++)Status: ❌ DEFERREDWhat Happened: Too complex for timelineRecovery: Focus on web/mobile firstLesson: Scope management critical3. Full IPFS MigrationStatus: ❌ DEFERREDWhat Happened: Performance concernsRecovery: Hybrid approach with IPFS planLesson: Gradual migration better than big bang🎯 STRATEGIC INSIGHTS1. 🏆 What Made Us SuccessfulClear Vision: "Spotify meets OpenSea" was compellingModern Tech: Latest tools gave us competitive advantageBlockchain Focus: EAS attestations provided real Web3 valueDocumentation: Comprehensive docs enabled rapid developmentAI-Assisted Development: Cursor + AI accelerated development2. 🚧 What Slowed Us DownScope Creep: Too many features for hackathon timelineComplex Integrations: UploadThing, multi-chain complexityPerfectionism: Over-engineering some componentsTechnology Learning Curve: New tools required learning time3. 🎯 What We'd Do DifferentlyStart Simpler: Basic audio player first, then add featuresFocus on Core: EAS + basic marketplace, then expandIterative Approach: Build, test, iterate rather than plan everythingUser Testing: Get feedback earlier in development🚀 GOING FORWARD✅ IMMEDIATE PRIORITIESIPFS Migration: Complete decentralization (3-week plan)Payment Flow: Finish PYUSD integrationAudio Polish: Complete waveform visualizationUser Testing: Get real user feedback🔄 MEDIUM-TERM GOALSDesktop App: JUCE C++ implementationAdvanced Audio: Professional mastering toolsMobile Polish: Enhanced mobile experienceAnalytics: Comprehensive usage tracking🎯 LONG-TERM VISIONIndustry Standard: Compete with Spotify/Apple MusicWeb3 Native: Fully decentralized music ecosystemGlobal Scale: Multi-language, multi-currencyDeveloper Platform: API for third-party integrations💡 KEY LESSONS LEARNED1. 🎯 Scope ManagementStart small, build uprather than planning everythingFocus on core valuebefore adding featuresUser feedbackis more valuable than perfect planning2. 🏗️ Architecture DecisionsModern tech stackpays off in long runDocumentationis critical for team velocityBlockchain integrationrequires careful planning3. 🚀 Development ProcessAI-assisted developmentaccelerates progressIterative approachbetter than waterfallTesting earlyprevents major issues laterThe 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.
Hackathon
ETHOnline 2025
2025