From f182f6a07989d52b9cc35eda8dde7d114626bbc4 Mon Sep 17 00:00:00 2001 From: Zeeshan Tariq Date: Tue, 11 Nov 2025 12:02:27 +0500 Subject: [PATCH] Implement complete Sonora audio NFT marketplace functionality --- SONORA.md | 138 +++++++-- .../src/features/permasearch/utils/helpers.ts | 2 + .../src/features/pinax/constants.tsx | 3 +- .../features/pinax/hooks/useUploadAndMint.ts | 119 ++++++++ .../src/features/pinax/index.tsx | 102 +------ .../src/features/sonora/api/arweave.ts | 107 +++++++ .../sonora/api/fetchMarketAudioNFTs.ts | 215 +++++++++++++ .../sonora/api/fetchStudioAudioNFTs.ts | 206 +++++++++++++ .../features/sonora/api/fetchUserAudioNFTs.ts | 211 +++++++++++++ .../src/features/sonora/archiveSlice.ts | 131 ++++++++ .../src/features/sonora/browse/browseSlice.ts | 57 ++++ .../sonora/browse/thunks/fetchAudios.ts | 44 +++ .../features/sonora/components/AudioCard.tsx | 284 ++++++++++++++---- .../features/sonora/components/BuyButton.tsx | 113 ++++++- .../features/sonora/components/EditButton.tsx | 130 +++++++- .../features/sonora/components/MintButton.tsx | 39 ++- .../sonora/components/PlayPauseButton.tsx | 11 +- .../features/sonora/components/SellButton.tsx | 110 ++++++- .../sonora/components/UnlistButton.tsx | 110 ++++++- .../features/sonora/hooks/useArweaveAudios.ts | 50 +++ .../src/features/sonora/hooks/useBuyAudio.ts | 112 +++++++ .../sonora/hooks/useMarketAudioNFTs.ts | 29 ++ .../src/features/sonora/hooks/useSellAudio.ts | 140 +++++++++ .../sonora/hooks/useStudioAudioNFTs.ts | 23 ++ .../features/sonora/hooks/useUnlistAudio.ts | 59 ++++ .../features/sonora/hooks/useUpdateAudio.ts | 65 ++++ .../features/sonora/hooks/useUserAudioNFTs.ts | 25 ++ .../src/features/sonora/marketSlice.ts | 121 ++++++++ .../src/features/sonora/sonoraSlice.ts | 51 ++-- .../src/features/sonora/studioSlice.ts | 122 ++++++++ .../src/features/sonora/types.ts | 54 +++- .../src/features/sonora/utils/audioFilters.ts | 97 ++++++ .../src/layouts/SonoraLayout.tsx | 5 +- .../src/pages/sonora/ArchivePage.tsx | 102 +++++-- .../src/pages/sonora/MarketPage.tsx | 104 +++++-- .../src/pages/sonora/RecordPage.tsx | 265 ++++++++++------ .../src/pages/sonora/StudioPage.tsx | 114 +++++-- .../src/pages/sonora/UploadPage.tsx | 95 ++++-- src/alex_frontend/src/pages/sonora/index.tsx | 126 ++++++-- src/alex_frontend/src/store/rootReducer.ts | 6 + src/alex_frontend/src/styles/tailwind.css | 5 + src/nft_manager/nft_manager.did | 26 +- 42 files changed, 3461 insertions(+), 467 deletions(-) create mode 100644 src/alex_frontend/src/features/pinax/hooks/useUploadAndMint.ts create mode 100644 src/alex_frontend/src/features/sonora/api/arweave.ts create mode 100644 src/alex_frontend/src/features/sonora/api/fetchMarketAudioNFTs.ts create mode 100644 src/alex_frontend/src/features/sonora/api/fetchStudioAudioNFTs.ts create mode 100644 src/alex_frontend/src/features/sonora/api/fetchUserAudioNFTs.ts create mode 100644 src/alex_frontend/src/features/sonora/archiveSlice.ts create mode 100644 src/alex_frontend/src/features/sonora/browse/browseSlice.ts create mode 100644 src/alex_frontend/src/features/sonora/browse/thunks/fetchAudios.ts create mode 100644 src/alex_frontend/src/features/sonora/hooks/useArweaveAudios.ts create mode 100644 src/alex_frontend/src/features/sonora/hooks/useBuyAudio.ts create mode 100644 src/alex_frontend/src/features/sonora/hooks/useMarketAudioNFTs.ts create mode 100644 src/alex_frontend/src/features/sonora/hooks/useSellAudio.ts create mode 100644 src/alex_frontend/src/features/sonora/hooks/useStudioAudioNFTs.ts create mode 100644 src/alex_frontend/src/features/sonora/hooks/useUnlistAudio.ts create mode 100644 src/alex_frontend/src/features/sonora/hooks/useUpdateAudio.ts create mode 100644 src/alex_frontend/src/features/sonora/hooks/useUserAudioNFTs.ts create mode 100644 src/alex_frontend/src/features/sonora/marketSlice.ts create mode 100644 src/alex_frontend/src/features/sonora/studioSlice.ts create mode 100644 src/alex_frontend/src/features/sonora/utils/audioFilters.ts diff --git a/SONORA.md b/SONORA.md index f0c94f3dd..2ac8d21c6 100644 --- a/SONORA.md +++ b/SONORA.md @@ -177,24 +177,124 @@ src/layouts/ src/config/apps.ts # Add Sonora to apps list with placeholder image ``` -## Technical Decisions (TO BE MADE) -- [ ] Audio format support (.mp3, .wav, .ogg) -- [ ] Streaming vs download approach -- [ ] File size limitations -- [ ] Quality options -- [ ] Offline playback support - -## Implementation Notes -- Using TanStack Router for routing -- TanStack Query for data fetching -- Redux Toolkit with thunks for state management -- Tailwind CSS + Shadcn components -- Features pattern for organization -- Following existing permasearch/pinax patterns - -## Discussion Notes -*This section will be updated with our decisions as we discuss each feature* +## Technical Decisions (IMPLEMENTED) +- [x] Audio format support (.mp3, .wav, .ogg, .flac, .m4a, .mpeg, .webm) +- [x] Streaming approach with HTML5 audio element +- [x] File size limitations per Pinax file type configuration +- [x] Direct playback with browser audio controls +- [x] Arweave permanent storage for audio files + +## Implementation Status + +### ✅ COMPLETED FEATURES + +#### Core Marketplace Functionality +- **Archive Page**: User's owned audio NFTs (not listed for sale) +- **Studio Page**: User's audio NFTs listed for sale (with edit/unlist actions) +- **Market Page**: Other users' audio NFTs available for purchase +- **Working Action Buttons**: Buy, Sell, Edit Price, Unlist with dialog modals +- **ICRC-2 Integration**: Proper approval flow for secure NFT purchases + +#### State Management & Data Flow +- **Redux Store**: Separate slices for archive, studio, and market +- **Pagination**: Load More functionality with page size of 8 +- **Loading States**: Smart loading that preserves existing content while loading new pages +- **Error Handling**: Comprehensive error states with retry functionality + +#### User Experience +- **Audio Player**: Integrated playback with visual progress indicators +- **Price Display**: Show NFT prices in ICP format +- **Owner Information**: Display NFT owner (truncated principal) on market page only +- **Filtering**: Market page excludes current user's listings automatically + +#### Integration with Existing System +- **Emporium**: Marketplace transactions and listings +- **ICP Ledger**: ICRC-2 token approval and transfers +- **ICRC7**: NFT ownership verification and transfers +- **Arweave**: Audio metadata and content fetching via GraphQL + +#### Browse/Discovery (Main Page) +- **Arweave Integration**: Fetches audio files from Arweave network via GraphQL +- **Minting**: Full integration with existing Permasearch minting system +- **UI**: Complete card-based interface with Load More pagination +- **Audio Playback**: Integrated audio player with progress indicators + +#### Upload/Record Pages +- **Upload Flow**: Complete file selection with Pinax integration for upload and mint +- **Recording**: Full browser-based audio recording with MediaRecorder API +- **Audio Preview**: Real-time playback of recorded/uploaded content with AudioCard +- **Processing States**: Complete upload/mint workflow with error handling + +### 📋 IMPLEMENTATION DETAILS + +#### File Structure (COMPLETED) +``` +src/features/sonora/ +├── archiveSlice.ts # User's owned NFTs state +├── marketSlice.ts # Marketplace state +├── studioSlice.ts # User's listed NFTs state +├── sonoraSlice.ts # Global audio player state +├── types.ts # TypeScript interfaces +├── components/ +│ ├── AudioCard.tsx # NFT display with player controls +│ ├── BuyButton.tsx # Purchase dialog with approval flow +│ ├── SellButton.tsx # List for sale dialog +│ ├── EditButton.tsx # Edit price dialog +│ ├── UnlistButton.tsx # Remove from marketplace dialog +│ ├── MintButton.tsx # Mint from Arweave (browse page) +│ └── PlayPauseButton.tsx # Audio player controls +├── hooks/ +│ ├── useUserAudioNFTs.ts # Archive page data +│ ├── useStudioAudioNFTs.ts # Studio page data +│ ├── useMarketAudioNFTs.ts # Market page data +│ ├── useBuyAudio.ts # Purchase workflow with ICRC-2 +│ ├── useSellAudio.ts # Listing workflow +│ ├── useUpdateAudio.ts # Price editing +│ ├── useUnlistAudio.ts # Marketplace removal +│ └── useArweaveAudios.ts # Browse page data +├── api/ +│ ├── fetchUserAudioNFTs.ts # User's NFTs from multiple sources +│ ├── fetchStudioAudioNFTs.ts # User's marketplace listings +│ ├── fetchMarketAudioNFTs.ts # All marketplace listings (filtered) +│ └── fetchArweaveAudios.ts # Arweave audio discovery +└── utils/ + └── audioHelpers.ts # Audio format validation & utilities +``` + +#### Pages Structure (COMPLETED) +``` +src/pages/sonora/ +├── index.tsx # Browse page (Arweave discovery) +├── ArchivePage.tsx # User's collection +├── StudioPage.tsx # User's listings +├── MarketPage.tsx # Global marketplace +├── UploadPage.tsx # File upload + mint +└── RecordPage.tsx # Audio recording + mint +``` + +#### Navigation & Layout (COMPLETED) +- **SonoraLayout.tsx**: Horizontal tab navigation following Exchange/Emporium pattern +- **Active Route Highlighting**: Visual indication of current page +- **Responsive Design**: Works across different screen sizes + +## Technical Specifications + +### Audio Formats Supported +- MP3, WAV, OGG, FLAC, M4A, MPEG, WebM +- File size limits per Pinax configuration (100MB for media) + +### Blockchain Integration +- **ICP Ledger**: ICRC-2 token standard for payments +- **ICRC7**: NFT ownership and transfers +- **Emporium**: Marketplace contract for listings +- **Arweave**: Permanent storage via GraphQL queries + +### State Management Architecture +- **Modular Redux Slices**: Separate state management for each page type +- **Async Thunks**: Handle API calls and error states +- **Pagination**: Append mode to preserve existing content during loading +- **Loading States**: Separate loading indicators for initial load vs. load more --- -**Last Updated:** 2025-10-26 -**Status:** Detailed specification with code structure \ No newline at end of file +**Last Updated:** 2025-11-11 +**Status:** ✅ **FULLY COMPLETED** - Complete Sonora audio NFT marketplace with all 6 pages, working marketplace actions, ICRC-2 integration, pagination, and full blockchain integration \ No newline at end of file diff --git a/src/alex_frontend/src/features/permasearch/utils/helpers.ts b/src/alex_frontend/src/features/permasearch/utils/helpers.ts index 19209a755..7bc20966c 100644 --- a/src/alex_frontend/src/features/permasearch/utils/helpers.ts +++ b/src/alex_frontend/src/features/permasearch/utils/helpers.ts @@ -11,6 +11,8 @@ import type { ActorSubclass } from "@dfinity/agent"; import type { _SERVICE } from "../../../../../declarations/nft_manager/nft_manager.did"; import { estimateBlockHeight, fetchBlockHeightForTimestamp, getBlockHeightForTimestamp, getCurrentBlockHeight } from "./blocks"; +export { getCurrentBlockHeight }; + export const ARWEAVE_GRAPHQL_ENDPOINT = "https://arweave.net/graphql"; export async function filterAvailableAssets( diff --git a/src/alex_frontend/src/features/pinax/constants.tsx b/src/alex_frontend/src/features/pinax/constants.tsx index 6e44eb37e..49c8930be 100644 --- a/src/alex_frontend/src/features/pinax/constants.tsx +++ b/src/alex_frontend/src/features/pinax/constants.tsx @@ -29,7 +29,8 @@ export const FILE_TYPES = { "video/webm", "audio/mpeg", // or mp3. There is also a video/mpeg which is not included "audio/wav", - "audio/ogg" + "audio/ogg", + "audio/webm" // Support for recorded audio from MediaRecorder ], icon: