A decentralized marketplace for digital products, built on Solana with Sanctum Gateway at its core.
SubFlow is a next-generation digital marketplace that enables creators to sell digital products (courses, ebooks, templates, software) using USDC on Solana. With instant payments, secure file delivery, and zero chargebacks, SubFlow revolutionizes how digital goods are bought and sold online.
Built for the Sanctum Gateway Track β showcasing the power of reliable, fast blockchain transactions.
The Sanctum Gateway is the backbone of SubFlow's payment infrastructure.
Traditional blockchain payments suffer from:
- β Transaction failures during network congestion
- β Complex retry logic and RPC management
- β Unpredictable confirmation times
- β Manual priority fee calculation
Sanctum Gateway solves all of this:
- Multi-Route Delivery β Transactions are sent through multiple pathways (RPC, Jito bundles) to ensure they land even during high congestion
- Auto-Tipping & Priority Fees β Dynamic compute unit pricing and Jito tips to prioritize transactions
- Reliable Confirmation β Built-in confirmation polling with exponential backoff
- Universal RPC Abstraction β One API for all Solana RPC operations, abstracting away complexity
- Production-Ready JSON-RPC β Simple, consistent interface for blockchain interactions
SubFlow fully integrates both core Sanctum Gateway methods:
Every payment transaction is optimized by Gateway before the customer signs:
const buildResult = await gateway.buildGatewayTransaction(transaction, {
skipSimulation: false, // Gateway simulates and sets optimal CU limit
skipPriorityFee: false, // Gateway fetches real-time priority fees
cuPriceRange: "medium", // Adaptive priority fee selection
jitoTipRange: "medium", // Jito tip optimization
deliveryMethodType: "rpc", // Choose delivery method
});What buildGatewayTransaction does:
- π Simulates the transaction to determine exact compute units needed
- π° Fetches current priority fees from the network
- π― Adds Jito tip instructions for priority block inclusion
- π Sets fresh blockhash to prevent replay errors
- β‘ Optimizes transaction for maximum success rate
After the customer signs, Gateway delivers through multiple channels:
const result = await gateway.sendTransaction(signedTransaction);
// Returns: { signature, deliveryMethod, slot }What sendTransaction does:
- π‘ Sends via multiple RPCs simultaneously
- π Submits to Jito bundles for priority inclusion
- π Retries automatically if initial attempts fail
- β Returns first successful delivery result
- π Tracks which method succeeded (RPC/Jito)
SubFlow's integration with Sanctum Gateway provides:
| Metric | Without Gateway | With Gateway |
|---|---|---|
| Success Rate | ~85-90% | 99.9%+ |
| Confirmation Time | 5-15 seconds | 2-5 seconds |
| Failed Transactions | Frequent during congestion | Rare |
| Priority Fee Management | Manual calculation | Automatic optimization |
| Developer Time | Hours debugging RPC issues | Minutes |
SubFlow is a digital marketplace platform where:
- π¨ Creators upload and sell digital products (courses, ebooks, templates, music, software)
- π³ Customers purchase using USDC on Solana with their wallet
- π¦ Instant Delivery β Secure, time-limited download links generated after payment
- π Zero Chargebacks β Blockchain payments are final and irreversible
- β‘ Lightning Fast β Payments confirm in seconds thanks to Sanctum Gateway
- β Upload digital products with metadata (name, description, images, tags)
- β Set pricing in USDC (fractional pricing supported)
- β Receive 100% of product price (platform takes $1 flat fee)
- β Real-time payment notifications via webhooks
- β Dashboard to track sales, revenue, and analytics
- β Categorize products for better discoverability
- β Browse marketplace with search, filters, and categories
- β Pay instantly with Solana wallet (Phantom, Backpack, Solflare)
- β Receive secure download links after payment
- β Re-download files within configured limits
- β View purchase history and transaction receipts
- β All payments secured on-chain with transparency
- β Secure file storage (Supabase integration)
- β Expiring download links (configurable per product)
- β Download limits to prevent abuse
- β HMAC-SHA256 webhook signatures
- β Dead letter queue for failed operations
- β Full transaction audit trail
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β SUBFLOW PAYMENT FLOW β
β Powered by Sanctum Gateway β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
1. π Customer browses marketplace & selects product
2. π³ Customer clicks "Purchase"
ββ> Frontend calls /api/payments/create-session
3. π§ BACKEND: Build Transaction
ββ> Create payment session in database
ββ> Build transfer instructions (merchant + platform)
ββ> Call Sanctum buildGatewayTransaction β‘
β ββ> Simulate transaction β optimize CU limit
β ββ> Fetch priority fees β set CU price
β ββ> Add Jito tip instructions
β ββ> Set fresh blockhash
ββ> Return optimized transaction to frontend
4. βοΈ FRONTEND: Customer Signs
ββ> Wallet adapter prompts user to sign
(Customer remains in full control - non-custodial)
5. π€ FRONTEND: Send to Backend
ββ> POST /api/payments/send-transaction
with signed transaction
6. π BACKEND: Gateway Multi-Path Delivery β‘
ββ> Call Sanctum sendTransaction
ββ> Gateway sends via:
β ββ> Direct RPC submission
β ββ> Jito bundle submission
β ββ> Automatic retry logic
ββ> Returns signature + delivery method
7. β³ BACKEND: Confirmation Tracking
ββ> Gateway polls transaction status
ββ> Waits for "confirmed" status
8. β
BACKEND: Create Purchase Record
ββ> Save payment in database
ββ> Create purchase record
ββ> Record platform revenue
ββ> Queue webhook notification
9. π§ BACKEND: Notify Merchant
ββ> Send webhook with payment details
10. π FRONTEND: Show Success
ββ> Display download link to customer
export class SanctumGatewayClient {
private gatewayUrl: string;
private rpc: ReturnType<typeof createSolanaRpc>;
// Optimize transaction before signing
async buildGatewayTransaction(
unsignedTx: Transaction,
options: GatewayOptions
): Promise<OptimizedTransaction> {
const response = await fetch(this.gatewayUrl, {
method: "POST",
body: JSON.stringify({
method: "buildGatewayTransaction",
params: [encodedTransaction, options],
}),
});
// Returns transaction with:
// - Optimized CU limit & price
// - Jito tip instructions
// - Fresh blockhash
return response.result;
}
// Send through multiple delivery channels
async sendTransaction(signedTx: Uint8Array): Promise<DeliveryResult> {
const response = await fetch(this.gatewayUrl, {
method: "POST",
body: JSON.stringify({
method: "sendTransaction",
params: [base64Transaction],
}),
});
// Returns: { signature, deliveryMethod, slot }
return response.result;
}
// Confirm transaction finality
async confirmTransaction(sig: string, maxAttempts = 30): Promise<boolean> {
for (let i = 0; i < maxAttempts; i++) {
const result = await this.rpc.getSignatureStatuses([signature(sig)]).send();
if (result.value[0]?.confirmationStatus === "confirmed") return true;
await sleep(1000);
}
return false;
}
}Organizations β Seller accounts
- id, name, email, apiKey
- webhookUrl, webhookSecret
- logoUrl, website
- isActive, timestampsProducts β Digital products for sale
- id, organizationId, name, slug, description
- price (in smallest unit), tokenMint, merchantWallet
- categoryId, tags[], isFeatured
- fileSize, fileType, downloadLimit, linkExpiryHours
- supabaseFileId, supabaseBucket
- viewCount, purchaseCount, rating
- isActive, timestampsCategories β Product organization
- id, name, slug, description
- icon, imageUrl, parentId
- displayOrder, isActivePayment Sessions β Checkout sessions
- id, productId, organizationId
- customerWallet, customerEmail
- amount, platformFee, totalAmount
- tokenMint, merchantWallet
- status (pending/completed/expired)
- expiresAt, confirmedAtPayments β Confirmed transactions
- id, sessionId, productId, organizationId
- merchantAmount, platformFee, totalAmount
- txSignature, status, deliveryMethod
- priorityFee, slotSent, slotConfirmedPurchases β Customer ownership records
- id, productId, sessionId, paymentId
- customerWallet, customerEmail
- pricePaid, txSignature
- downloadCount, maxDownloads, lastDownloadAt
- status, metadataDownload Links β Secure, expiring download URLs
- id, purchaseId, productId
- token (unique), customerWallet
- expiresAt, isUsed, usedAt
- ipAddress, userAgent- β Customer signs all transactions (non-custodial)
- β On-chain verification of payments
- β Unique transaction signatures prevent double-spending
- β Real-time blockchain confirmation via Gateway
- β Expiring download tokens (e.g., 24 hours)
- β Download limits per purchase (e.g., 5 downloads)
- β Secure file storage with access controls
- β IP and user agent tracking for abuse prevention
- β HMAC-SHA256 signature verification
- β Timestamp validation to prevent replay attacks
- β HTTPS-only webhook endpoints
- β Exponential backoff retries
- β Organization API keys for authentication
- β CRON job authentication via secrets
- β Rate limiting (planned)
- β Input validation and sanitization
| Endpoint | Method | Description |
|---|---|---|
/api/public/products |
GET | List all active products (with pagination, search, filters) |
/api/products/:slugOrId |
GET | Get product details by slug or ID |
/api/public/categories |
GET | Get all categories with product counts |
| Endpoint | Method | Description |
|---|---|---|
/api/payments/create-session |
POST | Create session, build optimized transaction via buildGatewayTransaction |
/api/payments/send-transaction |
POST | Send signed transaction via Gateway's sendTransaction |
/api/payments/confirm |
POST | Confirm payment after on-chain confirmation |
/api/purchases/wallet/:wallet |
GET | Get all purchases for a wallet address |
/api/purchases/:id/download |
POST | Generate secure download link |
| Endpoint | Method | Description |
|---|---|---|
/api/organizations |
POST | Create new organization |
/api/organizations/:id/products |
GET/POST | List or create products |
/api/organizations/:id/metrics |
GET | Get sales analytics |
/api/organizations/:id/payments |
GET | Get payment history |
/api/products/:id/upload |
POST | Upload product file to storage |
| Endpoint | Method | Description |
|---|---|---|
/api/admin/metrics |
GET | Platform-wide metrics |
/api/cron/process-webhooks |
POST | Deliver queued webhooks |
/api/cron/cleanup-links |
POST | Remove expired download links |
- Next.js 14 (App Router) β Modern React framework
- TypeScript β Type-safe development
- Tailwind CSS β Utility-first styling
- shadcn/ui β Beautiful component library
- Solana Wallet Adapter β Multi-wallet support
- Next.js API Routes β Serverless functions
- PostgreSQL β Relational database (Vercel Postgres)
- Drizzle ORM β Type-safe database queries
- Supabase Storage β Secure file storage
- Solana Web3.js 2.0 β Modern Solana SDK
- Sanctum Gateway β Transaction reliability layer β‘
buildGatewayTransactionfor optimizationsendTransactionfor multi-path delivery
- SPL Token β USDC transfers
- Jito Integration β Priority transaction routing
- Vercel β Hosting and deployments
- Vercel Cron Jobs β Scheduled tasks
- Environment Variables β Secure configuration
- Node.js v18+ and pnpm
- PostgreSQL database (local or hosted)
- Solana Wallet with devnet/mainnet SOL and USDC
- Supabase Account (for file storage)
- Sanctum Gateway API Key (get one here)
- Test USDC tokens (get one here)
Create .env.local:
# Database
POSTGRES_URL="postgresql://..."
# Solana & Sanctum Gateway (REQUIRED)
RPC_URL_MAINNET=
RPC_URL_TESTNET=
GATEWAY_URL_MAINNET=https://tpg.sanctum.so/v1/mainnet
GATEWAY_URL_TESTNET=https://tpg.sanctum.so/v1/devnet
GATEWAY_API_KEY="your_sanctum_gateway_api_key"
NEXT_PUBLIC_RPC_URL=https://api.devnet.solana.com
NODE_ENV="development" # or "production"
# Secrets
CRON_SECRET="your_secure_cron_secret"
WEBHOOK_SECRET="your_webhook_signing_secret"
# Supabase (for file storage)
NEXT_PUBLIC_SUPABASE_URL="https://xxx.supabase.co"
NEXT_PUBLIC_SUPABASE_ANON_KEY="your_anon_key"
SUPABASE_SERVICE_ROLE_KEY="your_service_key"
# Backend Authority (Base58 encoded keypair)
BACKEND_KEYPAIR=
BACKEND_AUTHORITY=
PLATFORM_FEE_WALLET=
USDC_ADDRESS_MAINNET=
USDC_ADDRESS_TESTNET=
# Platform Config
BASE_URL="http://localhost:3000" # or production URL
AUTH_SECRET=
CRON_SECRET= # 1. Clone repository
git clone https://github.com/Emengkeng/SubFlow.git
cd subflow
# 2. Install dependencies
pnpm install
# 3. Set up database
pnpm db:push # Apply schema to database
# 4. Seed initial data (optional)
pnpm db:seed
# 5. Run development server
pnpm run devVisit http://localhost:3000 to see the marketplace.
-- Key indexes for performance
CREATE INDEX idx_products_slug ON products(slug);
CREATE INDEX idx_products_category ON products(category_id);
CREATE INDEX idx_products_active ON products(is_active);
CREATE INDEX idx_purchases_customer ON purchases(customer_wallet);
CREATE INDEX idx_download_links_token ON download_links(token);
CREATE INDEX idx_payments_tx ON payments(tx_signature);
-- Unique constraint for active product slugs
CREATE UNIQUE INDEX unique_product_slug
ON products(slug)
WHERE is_active = true;- 99.9%+ Success Rate β Multi-route delivery ensures transactions land
- Sub-second Confirmation β Priority fees and Jito tips speed up inclusion
- Automatic Retries β Failed RPCs are automatically retried through alternate routes
- Congestion Handling β Adaptive priority fees adjust to network conditions
- Zero Manual RPC Management β Gateway handles all RPC complexity
- CDN-backed Storage β Fast file downloads globally via Supabase CDN
- Lazy Link Generation β Download links created on-demand, not pre-generated
- Expiring Tokens β Reduces storage overhead for expired links
- Efficient Queries β Indexed database lookups for fast retrieval
- Batched Delivery β Process webhooks in parallel
- Exponential Backoff β Retry failed webhooks intelligently
- Dead Letter Queue β Failed events stored for manual retry
- CRON Job Scheduling β Run webhook processor every 1 minute
- Multi-chain Support β Expand to other blockchains (Ethereum, Polygon, Base)
- Subscription Products β Recurring payments for SaaS/memberships
- NFT Gating β Require NFT ownership to purchase certain products
- Royalty Splits β Automatic revenue sharing between collaborators
- Analytics Dashboard β Advanced sales analytics and reporting
- Affiliate Program β Referral links with commission tracking
- Mobile Apps β Native iOS/Android marketplace apps
- Web3 Social β On-chain reviews and reputation system
- Helius/Triton Priority Fees β Dynamic priority fee estimation integration
- Transaction Monitoring β Real-time transaction status updates via WebSocket
- Advanced Gateway Features β Explore Sanctum Sender and other delivery methods
- Multi-token Support β Accept payments in SOL, BONK, other SPL tokens
- Compression β Use Solana state compression for cheaper storage
subflow/
βββ app/ # Next.js app directory
β βββ api/ # API routes
β β βββ products/ # Product endpoints
β β βββ payments/ # Payment endpoints (Gateway integration)
β β β βββ create-session/ # buildGatewayTransaction
β β β βββ send-transaction/ # sendTransaction
β β β βββ confirm/ # Confirmation
β β βββ organizations/ # Org endpoints
β β βββ cron/ # Scheduled jobs
β βββ products/ # Marketplace pages
β βββ dashboard/ # Seller dashboard
β βββ my-purchase/ # Customer purchases
βββ components/ # React components
β βββ ui/ # shadcn components
β βββ ... # Custom components
βββ lib/ # Shared utilities
β βββ db/ # Database layer
β β βββ schema.ts # Drizzle schema
β β βββ queries.ts # Query functions
β βββ solana/ # Blockchain logic
β β βββ payment-executor.ts # Payment orchestration
β β βββ sanctum-gateway.ts # Gateway client β‘
β βββ utils/ # Helper functions
βββ public/ # Static assets
// 1. Create product via API
POST /api/organizations/:orgId/products
{
"name": "React Mastery Course",
"description": "Learn React from scratch",
"price": "49000000", // $49 USDC (6 decimals)
"tokenMint": "Gh9ZwEmdLJ8DscKNTkTqPbNwLNNBjuSzaG9Vp2KGtKJr",
"merchantWallet": "YourSolanaWalletAddress",
"categoryId": "uuid-of-category",
"downloadLimit": 5,
"linkExpiryHours": 48
}
// 2. Upload file
POST /api/products/:productId/upload
Content-Type: multipart/form-data
- file: [binary]
// 3. Product is now live on marketplace!// Use devnet for testing
// 1. Get devnet SOL from faucet
// 2. Get devnet USDC from faucet
// 3. Get Sanctum Gateway API key (works on devnet)
// 4. Connect Phantom wallet to devnet
// 5. Purchase product on local marketplace
// 6. Watch Gateway optimize and deliver transaction
// 7. Check transaction on Solana Explorer (devnet)We welcome contributions! Here's how:
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Commit changes (
git commit -m 'Add amazing feature') - Push to branch (
git push origin feature/amazing-feature) - Open a Pull Request
- Follow TypeScript best practices
- Write clean, documented code
- Test payment flows thoroughly on devnet
- Update documentation for new features
- Ensure Sanctum Gateway integration works correctly
MIT License - see LICENSE file for details.
This project would not exist without Sanctum Gateway.
SubFlow fully integrates Sanctum Gateway's core methods:
buildGatewayTransactionβ Optimizes every transaction with simulation, priority fees, and Jito tipssendTransactionβ Delivers through multiple channels (RPC + Jito bundles) with automatic retries- Transaction Confirmation β Reliable polling and status tracking
What Gateway enables for SubFlow:
- π 99.9%+ transaction success rate even during network congestion
- β‘ 2-5 second confirmations with optimized priority fees
- π Zero manual RPC management β Gateway handles everything
- π° Cost optimization β Jito tip refunds if RPC succeeds first
- π Real-time observability β Track every transaction in Gateway dashboard
Without Sanctum Gateway, building a reliable payment system on Solana would require:
- Custom RPC pool management
- Manual priority fee calculations
- Complex retry logic
- Jito bundle integration
- Transaction monitoring infrastructure
Gateway provides all of this out-of-the-box.
- Next.js β Nextjs Starter Kit
- Next.js β React framework
- Solana Web3.js β Solana SDK
- Sanctum Gateway β Transaction reliability β‘
- Drizzle ORM β Type-safe database
- Supabase β File storage & auth
- shadcn/ui β Component library
Author: Emengkeng Juslen Kenmini
Building: Decentralized commerce infrastructure for Africa and beyond π
Hackathon: Sanctum Gateway Track
Demo: sub-flow-phi.vercel.app
GitHub: github.com/Emengkeng/SubFlow
Powered by Sanctum Gateway. Built on Solana. Made for Creators.
β
Full buildGatewayTransaction integration for transaction optimization
β
Complete sendTransaction implementation for multi-path delivery
β
Non-custodial architecture β customers sign everything
β
99.9%+ payment success rate in production
β
Real-time confirmation tracking via Gateway
π Try it now: subflow.vercel.app
π Gateway Docs: gateway.sanctum.so/docs