#
Backend
The QuickDapp backend is built on modern, high-performance technologies designed for Web3 applications. At its core is the ServerApp pattern - a dependency injection system that provides clean access to all backend services.
#
Technology Stack
- Bun - Primary runtime (Node.js compatible)
- ElysiaJS - High-performance web framework
- GraphQL Yoga - GraphQL server
- DrizzleORM - Type-safe database toolkit
- PostgreSQL - Relational database
- SIWE - Sign-in with Ethereum authentication
- Viem - Type-safe Ethereum client
#
Key Features
#
ServerApp Dependency Injection
The ServerApp pattern provides clean access to all backend services:
export type ServerApp = {
app: Elysia // ElysiaJS server instance
db: PostgresJsDatabase // DrizzleORM database connection
rootLogger: Logger // Root logger instance
createLogger: typeof createLogger // Logger factory
workerManager: WorkerManager // Background job processing
socketManager: ISocketManager // WebSocket manager
publicClient: PublicClient // Blockchain read client
walletClient: WalletClient // Blockchain write client
createNotification: Function // Notification system
}
#
Type-Safe Database Access
DrizzleORM provides compile-time type checking and excellent performance:
import { serverApp } from './bootstrap'
// Type-safe queries
const users = await serverApp.db
.select()
.from(userTable)
.where(eq(userTable.address, walletAddress))
// Transactions
await serverApp.db.transaction(async (tx) => {
// All operations are rolled back if any fail
})
#
GraphQL API
Schema-first GraphQL API with authentication:
type Query {
me: User @auth
tokens: [Token!]! @auth
}
type Mutation {
generateSiweMessage(address: String!): SiweMessageResult!
authenticateWithSiwe(message: String!, signature: String!): AuthResult!
markNotificationAsRead(id: PositiveInt!): Success! @auth
markAllNotificationsAsRead: Success! @auth
}
#
Real-time Communication
WebSocket support for real-time updates:
// Send notification to specific user
await serverApp.createNotification({
userId: user.id,
type: 'token_deployed',
data: { tokenAddress: '0x...' }
})
#
Background Jobs
Robust worker system for blockchain monitoring and async tasks:
// Submit a background job
await serverApp.workerManager.submitJob({
type: 'deployToken',
data: { name: 'MyToken', symbol: 'MTK' }
})
#
Documentation Sections
- Bootstrap - ServerApp pattern and dependency injection
- Database - DrizzleORM setup and usage patterns
- GraphQL - API schema and resolver implementation
- Authentication - SIWE and JWT authentication system
- WebSockets - Real-time communication implementation
#
Quick Examples
#
Creating a Simple Resolver
// src/server/graphql/resolvers.ts
export const resolvers = {
Query: {
me: async (parent, args, context) => {
const { serverApp, user } = context
if (!user) throw new Error('Authentication required')
return await serverApp.db
.select()
.from(userTable)
.where(eq(userTable.id, user.id))
.then(rows => rows[0])
}
}
}
#
Database Operations
// Insert with returning
const [user] = await serverApp.db
.insert(userTable)
.values({ address: '0x...', nonce: generateNonce() })
.returning()
// Complex queries with joins
const tokensWithOwners = await serverApp.db
.select({
token: tokenTable,
owner: userTable
})
.from(tokenTable)
.leftJoin(userTable, eq(tokenTable.ownerId, userTable.id))
#
Background Job Handler
// src/server/workers/jobs/deployToken.ts
export async function deployTokenJob(
serverApp: ServerApp,
job: Job<DeployTokenData>
) {
const { name, symbol, ownerId } = job.data
// Deploy contract using wallet client
const hash = await serverApp.walletClient.deployContract({
abi: ERC20_ABI,
bytecode: ERC20_BYTECODE,
args: [name, symbol]
})
// Wait for deployment
const receipt = await serverApp.publicClient.waitForTransactionReceipt({ hash })
// Save to database
await serverApp.db.insert(tokenTable).values({
address: receipt.contractAddress,
name,
symbol,
ownerId
})
// Notify user
await serverApp.createNotification({
userId: ownerId,
type: 'token_deployed',
data: { address: receipt.contractAddress }
})
}
The backend architecture prioritizes developer experience, type safety, and performance while maintaining clean separation of concerns through the ServerApp pattern.