mirror of
https://github.com/logos-messaging/OpChan.git
synced 2026-01-05 22:33:07 +00:00
Merge pull request #9 from ashiskumarnaik/dev
feat(store): add query options and fallback for store queries to improve reliability and limit results
This commit is contained in:
commit
41351ebab1
2
.env.example
Normal file
2
.env.example
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
# Mock/bypass settings for development
|
||||||
|
VITE_OPCHAN_MOCK_ORDINAL_CHECK=false
|
||||||
130
README.md
130
README.md
@ -1,8 +1,134 @@
|
|||||||
|
# OpChan
|
||||||
|
|
||||||
|
A decentralized forum application built as a Proof of Concept for a Waku-powered discussion platform. OpChan enables users to create "cells" (discussion boards), make posts, and engage in threaded conversations using Bitcoin Ordinal verification and the Waku protocol for decentralized messaging.
|
||||||
|
|
||||||
|
## Quick Start
|
||||||
|
|
||||||
|
### Prerequisites
|
||||||
|
|
||||||
|
- Node.js 18+ and npm
|
||||||
|
- [Phantom Wallet](https://phantom.app/) browser extension
|
||||||
|
- Bitcoin Ordinals (required for posting, optional for reading)
|
||||||
|
|
||||||
|
### Installation
|
||||||
|
|
||||||
|
1. **Clone the repository**
|
||||||
|
```bash
|
||||||
|
git clone https://github.com/waku-org/OpChan.git
|
||||||
|
cd OpChan
|
||||||
|
```
|
||||||
|
|
||||||
|
2. **Install dependencies**
|
||||||
|
```bash
|
||||||
|
npm install
|
||||||
|
```
|
||||||
|
|
||||||
|
3. **Setup environment variables**
|
||||||
|
```bash
|
||||||
|
cp .env.example .env
|
||||||
|
```
|
||||||
|
|
||||||
|
Edit `.env` to configure development settings:
|
||||||
|
```env
|
||||||
|
# Set to 'true' to bypass verification in development
|
||||||
|
VITE_OPCHAN_MOCK_ORDINAL_CHECK=false
|
||||||
|
```
|
||||||
|
|
||||||
|
4. **Start development server**
|
||||||
|
```bash
|
||||||
|
npm run dev
|
||||||
|
```
|
||||||
|
|
||||||
|
### Project Structure
|
||||||
|
|
||||||
|
```
|
||||||
|
src/
|
||||||
|
├── components/ # React components
|
||||||
|
│ ├── ui/ # shadcn/ui component library
|
||||||
|
│ ├── ActivityFeed.tsx
|
||||||
|
│ ├── CellPage.tsx
|
||||||
|
│ ├── Dashboard.tsx
|
||||||
|
│ └── ...
|
||||||
|
├── contexts/ # React Context providers
|
||||||
|
│ ├── AuthContext.tsx # Wallet & authentication
|
||||||
|
│ ├── ForumContext.tsx # Forum data & state
|
||||||
|
│ └── forum/ # Forum logic modules
|
||||||
|
├── lib/ # Core libraries
|
||||||
|
│ ├── identity/ # Wallet & cryptographic operations
|
||||||
|
│ ├── waku/ # Waku protocol integration
|
||||||
|
│ └── utils.ts
|
||||||
|
├── pages/ # Route components
|
||||||
|
└── types/ # TypeScript definitions
|
||||||
|
```
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
### Getting Started
|
||||||
|
|
||||||
|
1. **Connect Wallet**: Click "Connect Wallet" and approve the Phantom wallet connection
|
||||||
|
2. **Verify Ordinals**: The app will check if your wallet contains Logos Operator Bitcoin Ordinals
|
||||||
|
3. **Browse Cells**: View existing discussion boards on the dashboard
|
||||||
|
4. **Create Content**: Create new cells, posts, or comments (requires Ordinals)
|
||||||
|
5. **Moderate**: Cell creators can moderate their boards
|
||||||
|
|
||||||
|
### Authentication Flow
|
||||||
|
|
||||||
|
OpChan uses a two-tier authentication system:
|
||||||
|
|
||||||
|
1. **Wallet Connection**: Initial connection to Phantom wallet
|
||||||
|
2. **Key Delegation**: Optional browser key generation for improved UX
|
||||||
|
- Reduces wallet signature prompts
|
||||||
|
- 24-hour validity period
|
||||||
|
- Can be regenerated anytime
|
||||||
|
|
||||||
|
### Network & Performance
|
||||||
|
|
||||||
|
- **Waku Network**: Connects to multiple bootstrap nodes for resilience
|
||||||
|
- **Message Caching**: Local caching with IndexedDB (planned)
|
||||||
|
- **Time-bounded Queries**: 24-hour query windows to prevent database overload
|
||||||
|
- **Pagination**: 50 messages per query with fallback limits
|
||||||
|
|
||||||
|
## Contributing
|
||||||
|
|
||||||
|
### Development Setup
|
||||||
|
|
||||||
|
1. Fork the repository
|
||||||
|
2. Create a feature branch: `git checkout -b feature/amazing-feature`
|
||||||
|
3. Make your changes following the existing code style
|
||||||
|
4. Test your changes thoroughly
|
||||||
|
5. Commit your changes: `git commit -m 'Add amazing feature'`
|
||||||
|
6. Push to the branch: `git push origin feature/amazing-feature`
|
||||||
|
7. Open a Pull Request
|
||||||
|
|
||||||
## TODOs
|
## TODOs
|
||||||
- [x] replace mock wallet connection/disconnection
|
- [x] replace mock wallet connection/disconnection
|
||||||
- supports Phantom
|
- supports Phantom
|
||||||
- [x] replace mock Ordinal verification (API)
|
- [x] replace mock Ordinal verification (API)
|
||||||
- [ ] figure out using actual icons for cells
|
- [ ] figure out using actual icons for cells
|
||||||
- [ ] store message cache in indexedDB -- make app local-first (update from/to Waku when available)
|
- [ ] store message cache in indexedDB -- make app local-first (update from/to Waku when available)
|
||||||
- [ ] moderation
|
- [ ] moderation
|
||||||
- [ ] admins can "moderate" comments/posts
|
- [ ] admins can "moderate" comments/posts
|
||||||
|
|
||||||
|
## Architecture
|
||||||
|
|
||||||
|
OpChan implements a decentralized architecture with these key components:
|
||||||
|
|
||||||
|
- **Waku Protocol**: Handles peer-to-peer messaging and content distribution
|
||||||
|
- **Bitcoin Ordinals**: Provides decentralized identity verification
|
||||||
|
- **Key Delegation**: Improves UX while maintaining security
|
||||||
|
- **Content Addressing**: Messages are cryptographically signed and verifiable
|
||||||
|
- **Moderation Layer**: Cell-based moderation without global censorship
|
||||||
|
|
||||||
|
|
||||||
|
## Support
|
||||||
|
|
||||||
|
For questions, issues, or contributions:
|
||||||
|
|
||||||
|
- Open an issue on GitHub for bugs or feature requests
|
||||||
|
- Check existing issues before creating new ones
|
||||||
|
- Provide detailed information for bug reports
|
||||||
|
- Include steps to reproduce issues
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Note**: This is a Proof of Concept implementation. Use at your own risk in production environments.
|
||||||
@ -9,6 +9,16 @@ export class OrdinalAPI {
|
|||||||
* @returns A promise that resolves with the API response.
|
* @returns A promise that resolves with the API response.
|
||||||
*/
|
*/
|
||||||
async getOperatorDetails(address: string): Promise<OrdinalApiResponse> {
|
async getOperatorDetails(address: string): Promise<OrdinalApiResponse> {
|
||||||
|
|
||||||
|
if (import.meta.env.VITE_OPCHAN_MOCK_ORDINAL_CHECK === 'true') {
|
||||||
|
console.log(`[DEV] Bypassing ordinal verification for address: ${address}`);
|
||||||
|
return {
|
||||||
|
has_operators: true,
|
||||||
|
error_message: '',
|
||||||
|
data: []
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
const url = `${BASE_URL}/${address}/detail/`;
|
const url = `${BASE_URL}/${address}/detail/`;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|||||||
@ -12,16 +12,56 @@ class StoreManager {
|
|||||||
|
|
||||||
public async queryStore() {
|
public async queryStore() {
|
||||||
const result: (CellMessage | PostMessage | CommentMessage | VoteMessage)[] = [];
|
const result: (CellMessage | PostMessage | CommentMessage | VoteMessage)[] = [];
|
||||||
|
|
||||||
await this.node.store.queryWithOrderedCallback(
|
|
||||||
Object.values(decoders),
|
|
||||||
(message: IDecodedMessage) => {
|
|
||||||
const { payload} = message;
|
|
||||||
const decodedMessage = decodeMessage(payload);
|
|
||||||
result.push(decodedMessage);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Add query options to prevent database overload
|
||||||
|
const queryOptions = {
|
||||||
|
paginationLimit: 50, // Correct parameter name for page size
|
||||||
|
timeStart: new Date(Date.now() - 7 * 24 * 60 * 60 * 1000), // Last 7 days
|
||||||
|
timeEnd: new Date(), // Current time
|
||||||
|
paginationForward: false, // false = newest first
|
||||||
|
includeData: true // Include full message data
|
||||||
|
};
|
||||||
|
|
||||||
|
// Try with query options first, fallback to no options if it fails
|
||||||
|
try {
|
||||||
|
await this.node.store.queryWithOrderedCallback(
|
||||||
|
Object.values(decoders),
|
||||||
|
(message: IDecodedMessage) => {
|
||||||
|
const { payload } = message;
|
||||||
|
const decodedMessage = decodeMessage(payload);
|
||||||
|
result.push(decodedMessage);
|
||||||
|
},
|
||||||
|
queryOptions
|
||||||
|
);
|
||||||
|
} catch (queryError) {
|
||||||
|
console.warn("Query with options failed, trying without options:", queryError);
|
||||||
|
// Fallback: query without options but add manual limit
|
||||||
|
let messageCount = 0;
|
||||||
|
const MAX_MESSAGES = 100;
|
||||||
|
|
||||||
|
await this.node.store.queryWithOrderedCallback(
|
||||||
|
Object.values(decoders),
|
||||||
|
(message: IDecodedMessage) => {
|
||||||
|
if (messageCount >= MAX_MESSAGES) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const { payload } = message;
|
||||||
|
const decodedMessage = decodeMessage(payload);
|
||||||
|
result.push(decodedMessage);
|
||||||
|
messageCount++;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result.length > 0) {
|
||||||
|
console.log(`Store query completed. Found ${result.length} messages`);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Store query failed:", error);
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user