Skip to content

Conversation

@ToanBm
Copy link

@ToanBm ToanBm commented Jan 29, 2026

📹 Overview

This PR introduces a new example application demonstrating decentralized video streaming with content gating using the Shelby Protocol on Aptos blockchain.

✨ Key Features

  • Video Streaming: Real-time video playback with ReactPlayer integration
  • Content Gating: Pay-per-view model using Aptos Coin (APT) payments
  • Wallet Integration: Seamless connection with Aptos wallets (Petra, OKX, etc.)
  • Video Upload: Creator studio for uploading and pricing content
  • Responsive UI: Modern dark theme with gradient effects and smooth animations
  • Demo Videos: Pre-loaded sample videos for immediate testing

🛠️ Technical Implementation

  • Framework: Next.js 16 with TypeScript
  • Blockchain: Aptos integration via @aptos-labs/wallet-adapter-react
  • Storage: LocalStorage for video metadata persistence
  • Payment Flow: Direct P2P payments from viewers to content creators
  • UI Components: Custom components with Tailwind CSS styling

📁 Files Added

  • apps/streaming-video/ - Complete Next.js application
  • apps/streaming-video/components/ - Reusable UI components (Header, VideoPlayer, VideoUploader)
  • apps/streaming-video/hooks/ - Custom React hooks for video storage
  • apps/streaming-video/README.md - Comprehensive setup and usage guide

🔧 Additional Changes

  • Fixed broken dependency @aptos-labs/ace-sdk in apps/solana/token-gated/package.json
  • Updated root package.json with pnpm overrides to resolve installation issues
  • Updated root README.md with project documentation

🧪 Testing

  • ✅ Wallet connection flow (Petra, OKX)
  • ✅ Video upload and metadata storage
  • ✅ Payment transaction submission
  • ✅ Video playback after unlock
  • ✅ Responsive design on multiple screen sizes

🚀 How to Test

# Install dependencies
pnpm install

# Setup environment
cd apps/streaming-video
cp .env.example .env

# Run development server
cd ../..
pnpm dev --filter=@shelby-protocol/streaming-video

Open http://localhost:3005 to view the app.

---

**Checklist:**
- [x] Code follows project style guidelines
- [x] README documentation added
- [x] All dependencies properly declared
- [x] Build passes successfully
- [x] Manual testing completed

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Medium Risk**
> Adds a brand-new Next.js app that submits Aptos transactions and uploads blobs; while mostly isolated to an example, it introduces payment/unlock logic and new dependencies that could affect installs/builds.
> 
> **Overview**
> Adds a new `apps/streaming-video` Next.js example app that supports browsing videos, uploading new blobs to Shelby, and *Aptos wallet pay-to-unlock* playback with a gated player UI and local metadata persistence.
> 
> Updates the root `README.md` apps table to include the new example, and adjusts dependency management by adding a pnpm override to stub `@aptos-labs/ace-sdk` (and related lockfile updates) to avoid install issues.
> 
> <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit 822a4054e838fcfb56b1d7297eebbca6bb7078b6. This will update automatically on new commits. Configure [here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->

account: account.address,
blobName,
blobData: new Uint8Array(buffer),
});
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Blob upload failure after transaction leaves user with unusable content

Medium Severity

The uploadVideo function submits the blockchain transaction to register blob metadata (line 69) before uploading the actual blob data to storage (lines 72-76). If putBlob fails after the transaction succeeds, the user has paid gas fees for metadata pointing to non-existent content. The video will be registered on-chain but unplayable, with no way to recover.

Fix in Cursor Fix in Web

blobName,
expirationMicros: expirationMicros.toString(),
nowMicros: BigInt(Date.now() * 1000).toString()
});
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Debug console.log statements in production code

Low Severity

Multiple console.log statements appear to be debugging code left in production files. In useUploadVideo.tsx, there's a "Debug Upload" log with transaction details. In VideoPlayer.tsx, there are "Ready to play" and "Started playing" logs. In page.tsx, there's a "Transaction Hash" log. These pollute the browser console and may leak sensitive information.

Additional Locations (2)

Fix in Cursor Fix in Web

export const Header = () => {
const { connected, account, connect, wallets, disconnect } = useWallet();
const [isDropdownOpen, setIsDropdownOpen] = useState(false);
const dropdownRef = useRef<HTMLDivElement>(null);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Header component missing "use client" directive

Low Severity

The Header component uses React hooks (useState, useRef, useEffect) and the useWallet hook but lacks the "use client" directive that all other components in the same directory have. While it currently works because it's imported by page.tsx (a client component), this is inconsistent with the codebase patterns and fragile if the component is ever imported elsewhere.

Fix in Cursor Fix in Web

Copy link

@cursor cursor bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 2 potential issues.

Bugbot Autofix is OFF. To automatically fix reported issues with Cloud Agents, enable Autofix in the Cursor dashboard.

owner: "0x1",
url: "https://commondatastorage.googleapis.com/gtv-videos-bucket/sample/Sintel.mp4"
}
];
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Demo videos send payments to system address

High Severity

The default demo videos (big_buck_bunny and sintel) have owner: "0x1", which is the Aptos framework address. When users click "Unlock" on these videos, the handleUnlock function sends APT payments to address "0x1" via coin::transfer. This results in users losing real funds (0.1-0.2 APT per video) to a system address that no user controls. Demo content intended for testing the app shouldn't require payment to an unrecoverable address.

Additional Locations (1)

Fix in Cursor Fix in Web

className="flex overflow-x-auto gap-4 scroll-smooth no-scrollbar pb-8 pt-2 px-1"
style={{ scrollbarWidth: 'none', msOverflowStyle: 'none' }}
>
{filteredVideos.map((vid, idx) => {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unused idx variable in video map callback

Low Severity

The idx parameter is declared in the filteredVideos.map((vid, idx) => {...}) callback but is never used. The key for the rendered element uses vid.blobName instead of idx. This is dead code that can be removed.

Fix in Cursor Fix in Web

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant