# Project Overview
This project is a **BMAP API** server that processes and serves Bitcoin transactions using Bitcoin SV protocols. Key functionalities:
- Processing and storing Bitcoin transactions in MongoDB with Redis caching
- Generating dynamic charts using Chart.js with @napi-rs/canvas
- Serving social endpoints for friends, identities, and likes
- Streaming Bitcoin transactions via JungleBus
- BAP (Bitcoin Attestation Protocol) identity integration
# Identity Formats
The API deals with three distinct identity formats:
**BAP IDs**:
- Derived identity strings (e.g. "Go8vCHAa4S6AhXKTABGpANiz35J")
- 26 characters of base58-encoded data
- Unique identifier for a BAP identity
- NOT a public key or address
- Used in social features and message routing
**Bitcoin Addresses**:
- Legacy format (e.g. "1CfG7EzS1Qj8vGxKzr2ecHhYqZh2ndJT9g")
- Found in AIP protocol data as either:
- `address` field
- `algorithm_signing_component` field (these fields are synonymous)
- Used for transaction signing and verification
**Public Keys**:
- 33 or 65 byte hex strings
- Used for message encryption/decryption
- Not directly exposed in API responses
- Derived from BAP identity when needed for encryption
# Technology Stack
- **Bun**: Modern JavaScript runtime for server-side development
- **TypeScript**: For type safety and improved developer experience
- **Elysia.js**: High-performance web framework for Bun
- **MongoDB**: Primary database for transaction storage
- **Redis**: Caching layer for transactions, identities, and social data
- **bmapjs**: For parsing and processing BSV transactions
- **bpu-ts**: For Bitcoin script parsing
- **Chart.js** with **@napi-rs/canvas**: Native chart generation
- **JungleBus**: Real-time Bitcoin transaction streaming
# Project Structure
Core Files:
- **`index.ts`**: Server initialization and route setup
- **`cache.ts`**: Redis caching implementation
- **`db.ts`**: MongoDB connection and query handling
- **`process.ts`**: Transaction processing pipeline
- **`chart.ts`**: Chart generation using Chart.js/canvas
- **`bap.ts`**: BAP identity management
- **`actions.ts`**: Transaction saving and database operations
- **`social.ts`**: Social feature endpoints (friends, likes, identities)
- **`types.ts`**: Shared TypeScript types and interfaces
- **`bmap.ts`**: BMAP transaction normalization
Support Files:
- **`scripts/test-redis.ts`**: Redis connection testing
- **`public/`**: Static assets
- **`git-hooks/`**: Pre-commit and pre-push hooks
- **`biome.json`**: Code formatting and linting rules
# Development Guidelines
Code Quality:
- Use Biome for consistent code formatting and linting
- Run `bun run lint` for checks, `bun run lint:fix` for auto-fixes
- Git hooks enforce Biome rules and TypeScript checks on commit/push
- Maintain strict TypeScript types in `types.ts`
Error Handling:
- Use try-catch blocks with specific error types
- Log errors with relevant context
- Handle Redis and MongoDB connection failures gracefully
- Validate environment variables at startup
Performance:
- Leverage Redis caching for frequently accessed data
- Use MongoDB indexes for query optimization
- Implement proper connection pooling
- Consider batch processing for bulk operations
Testing:
- Add unit tests for critical functions
- Test Redis caching logic
- Verify MongoDB queries
- Test API endpoints for correct responses
# Environment Setup
Required Variables:
- `REDIS_PRIVATE_URL`: Redis connection string
- `BMAP_MONGO_URL`: MongoDB connection URL
- Additional MongoDB configuration variables
Development Tools:
- Bun for runtime and package management
- TypeScript for type checking
- Biome for code quality
- Git hooks for pre-commit/push checks
# API Design
Elysia.js Patterns:
- Use typed route parameters with `context.params`
- Handle query parameters via `context.query`
- Process request body with `context.body`
- Set response status with `set.status`
- Return errors using `error()`
Endpoints:
- Transaction queries
- Social interactions (friends, likes)
- Identity management
- Chart generation
- Real-time updates
# Data Architecture
MongoDB Collections:
- `c`: Confirmed transactions
- `u`: Unconfirmed transactions
- Indexes on:
- Transaction hashes
- Timestamps
- Block information
Redis Caching:
- Transaction data
- BAP identities
- Social graph information
- Cache invalidation strategies
# Best Practices
Code Organization:
- Keep files focused and modular
- Use TypeScript interfaces for data structures
- Document complex logic with comments
- Follow Biome formatting rules
- avoid someArray.forEach in favor of "for of" and "for in" loops
Error Management:
- Implement proper error boundaries
- Use typed error responses
- Log errors with stack traces
- Handle edge cases explicitly
Performance:
- Cache frequently accessed data
- Use appropriate indexes
- Implement connection pooling
- Monitor memory usage
Security:
- Validate input data
- Sanitize database queries
- Use proper error messages
- Implement rate limiting if needed
# Elysia Header Handling
Headers in Elysia must be handled carefully to avoid overwriting middleware headers:
- NEVER use direct assignment with `set.headers = {...}` as this overwrites ALL headers including those set by middleware
- ALWAYS use `Object.assign(set.headers, {...})` to merge new headers with existing ones
- This is especially important when using plugins like CORS that set their own headers
Example of correct header handling:
```typescript
// ❌ Wrong - overwrites CORS and other middleware headers
set.headers = {
'Cache-Control': 'public, max-age=60'
};
// ✅ Correct - preserves existing headers
Object.assign(set.headers, {
'Cache-Control': 'public, max-age=60'
});
```
Common places to check for header handling:
- SSE endpoints (Server-Sent Events)
- Cache control headers
- Content-Type headers
- Custom response headers
# Middleware Chaining
Elysia uses a middleware chain where:
- Plugins and middleware are executed in order of registration
- Each middleware can modify the context including headers
- Later middleware should not destroy earlier middleware's changes
- Use `.use()` to add middleware in the correct order
- Headers set by middleware (like CORS) must be preserved
Example of proper middleware chain:
```typescript
const app = new Elysia()
.use(cors()) // Sets CORS headers
.use(staticPlugin()) // May set content-type headers
.use(swagger()) // Adds OpenAPI documentation
.get('/endpoint', ({ set }) => {
// Preserve existing headers while adding new ones
Object.assign(set.headers, {
'Cache-Control': 'no-cache'
});
});
```
# Elysia Validation
Response validation is as strict as request validation:
- All fields defined in response schema must be present
- Optional fields must be explicitly marked as nullable using `t.Union([t.String(), t.Null()])`
- Missing required fields will cause validation errors even in production
- Always ensure response objects match schema exactly
Example of proper response schema:
```typescript
const IdentityResponse = t.Array(
t.Object({
idKey: t.String(),
paymail: t.Union([t.String(), t.Null()]), // Optional field must be explicitly nullable
displayName: t.String(),
icon: t.Union([t.String(), t.Null()]) // Optional field must be explicitly nullable
})
);
```
When processing data for response:
- Always include all required fields
- Set optional fields to null if not present
- Validate response shape matches schema
- Handle missing or undefined values explicitly
Example of proper response processing:
```typescript
return {
idKey: data.idKey,
paymail: data.paymail || null, // Convert undefined to null
displayName: data.name || "Unknown",
icon: data.icon || null // Convert undefined to null
};
```bun
css
ejs
golang
html
java
javascript
mongodb
+3 more
First Time Repository
BMAP Planaria for building B + MAP based Bitcoin apps.
TypeScript
Languages:
CSS: 0.5KB
EJS: 14.8KB
HTML: 12.6KB
JavaScript: 4.2KB
Shell: 0.5KB
TypeScript: 102.2KB
Created: 5/19/2019
Updated: 1/23/2025
All Repositories (1)
BMAP Planaria for building B + MAP based Bitcoin apps.