Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions examples/nextjs-kalshi-demo/.env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# Required: Your Dynamic Labs environment ID
# Get this from https://app.dynamic.xyz
NEXT_PUBLIC_DYNAMIC_ENV_ID=

NEXT_PUBLIC_SOLANA_RPC_URL=

# Optional: DFlow API key for authenticated trading requests
DFLOW_API_KEY=
45 changes: 45 additions & 0 deletions examples/nextjs-kalshi-demo/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
# Dependencies
node_modules
.pnpm-store

# Next.js
.next
out

# Production
build
dist

# Debug
npm-debug.log*
yarn-debug.log*
yarn-error.log*

# Local env files
.env
.env.local
.env.development.local
.env.test.local
.env.production.local

# Vercel
.vercel

# TypeScript
*.tsbuildinfo
next-env.d.ts

# IDE
.idea
.vscode
*.swp
*.swo

# OS
.DS_Store
Thumbs.db

# Testing
coverage
.nyc_output

159 changes: 159 additions & 0 deletions examples/nextjs-kalshi-demo/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,159 @@
# Kalshi Predictions Market Demo

A modern predictions market demo application built with Next.js, Dynamic Labs, and Solana. Users can browse Kalshi-style prediction markets, filter by categories and tags, place trades, and manage their positions using Solana wallets.

## Features

- **Market Browsing**: View prediction markets with real-time prices, trader counts, and time remaining
- **Search & Filter**: Search markets by question, filter by category (Politics, Crypto, Sports, etc.), and sort by various criteria
- **Trading**: Place market orders on prediction markets via Solana
- **Portfolio Management**: View positions and active orders
- **Wallet Integration**: Seamless Solana wallet connection powered by Dynamic Labs
- **Responsive Design**: Modern UI built with Tailwind CSS and a purple/cyan gradient theme

## Tech Stack

- **Framework**: Next.js 15
- **Language**: TypeScript
- **Styling**: Tailwind CSS
- **Wallet**: Dynamic Labs SDK with Solana support
- **Blockchain**: Solana
- **State Management**: React Query + React Hooks
- **Animations**: Motion (Framer Motion)

## Getting Started

### Prerequisites

- Node.js 18+
- pnpm (or bun)

### Installation

1. Install dependencies:

```bash
pnpm install
```

2. Set up environment variables. Create a `.env.local` file:

```bash
NEXT_PUBLIC_DYNAMIC_ENV_ID=your_dynamic_environment_id
NEXT_PUBLIC_SOLANA_RPC_URL=https://api.mainnet.solana.com
```

3. Start the development server:

```bash
pnpm dev
```

4. Open [http://localhost:3000](http://localhost:3000) in your browser.

## Available Scripts

- `pnpm dev` - Start development server
- `pnpm build` - Build for production
- `pnpm start` - Start production server
- `pnpm lint` - Run linter

## Project Structure

```text
src/
├── app/ # Next.js app router pages and API routes
│ └── api/ # API routes for Kalshi markets
│ └── kalshi/ # Market data endpoints
├── components/ # React components
│ ├── positions/ # Portfolio and positions management
│ └── ui/ # UI components (Toast, etc.)
├── lib/ # Utilities and integrations
│ ├── constants/ # Contract addresses, network config
│ ├── dynamic/ # Dynamic Labs SDK re-exports
│ ├── hooks/ # Custom React hooks
│ └── types/ # TypeScript type definitions
└── styles/ # Global styles
```

## Environment Variables

### Required

- `NEXT_PUBLIC_DYNAMIC_ENV_ID` - Your Dynamic Labs environment ID

### Optional

- `NEXT_PUBLIC_SOLANA_RPC_URL` - Custom Solana RPC endpoint (defaults to mainnet-beta)
- `DFLOW_API_KEY` - DFlow API key for authenticated requests

## How It Works

### Market Data

The demo fetches market data from a mock API that simulates Kalshi-style prediction markets. In production, you would:

1. Connect to the Kalshi API for real market data
2. Use DFlow for order execution on Solana
3. Query on-chain data for positions and balances

### Trading Flow

1. User connects a Solana wallet via Dynamic
2. User browses markets and selects Yes/No
3. User enters bet amount
4. Transaction is built and signed via Dynamic wallet
5. Order is submitted to the Solana network

### Solana Integration

The demo uses:

- **@solana/web3.js** for Solana RPC interactions
- **@solana/spl-token** for USDC balance queries
- **Dynamic Labs Solana SDK** for wallet connection and signing

## Customization

### Theming

The app uses a purple-to-cyan gradient theme. Customize colors in:

- `src/styles/globals.css` - CSS variables and Dynamic modal styling
- Component files - Tailwind classes

### Adding Real Kalshi Integration

To connect to the real Kalshi API:

1. Obtain Kalshi API credentials
2. Update `src/app/api/kalshi/route.ts` to call the Kalshi Trading API
3. Implement proper authentication and order placement

### Adding DFlow Integration

To enable real trading via DFlow:

1. Set up DFlow API access
2. Update `src/lib/hooks/useKalshiTrading.ts` to call DFlow Trade API
3. Handle order signing and confirmation

## Architecture

The demo is designed with a clean separation of concerns:

- **API Routes**: Server-side data fetching and transformation
- **Custom Hooks**: Business logic for markets and trading
- **Components**: Pure UI components with minimal logic
- **Types**: Shared TypeScript interfaces

## Security Considerations

- Never expose API keys in client-side code
- Use server-side API routes for authenticated requests
- Validate all user input before transactions
- Implement proper error handling for failed transactions

## License

MIT
15 changes: 15 additions & 0 deletions examples/nextjs-kalshi-demo/eslint.config.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { dirname } from "path";
import { fileURLToPath } from "url";
import { FlatCompat } from "@eslint/eslintrc";

const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);

const compat = new FlatCompat({
baseDirectory: __dirname,
});

const eslintConfig = [...compat.extends("next/core-web-vitals", "next/typescript")];

export default eslintConfig;

41 changes: 41 additions & 0 deletions examples/nextjs-kalshi-demo/next.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import type { NextConfig } from "next";

const nextConfig: NextConfig = {
reactStrictMode: true,
webpack: (config, { isServer }) => {
// Add externals for server-side only modules
config.externals.push("pino-pretty", "lokijs", "encoding");

// Add fallback for node modules that might not be available in browser
if (!isServer) {
config.resolve.fallback = {
...config.resolve.fallback,
fs: false,
net: false,
tls: false,
crypto: false,
};
}

return config;
},
images: {
remotePatterns: [
{
protocol: "https",
hostname: "images.unsplash.com",
},
{
protocol: "https",
hostname: "kalshi-public.s3.amazonaws.com",
},
{
protocol: "https",
hostname: "d1u5ehmvvpp8jp.cloudfront.net",
},
],
},
};

export default nextConfig;

44 changes: 44 additions & 0 deletions examples/nextjs-kalshi-demo/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
{
"name": "nextjs-kalshi-demo",
"version": "0.1.0",
"private": true,
"scripts": {
"dev": "next dev",
"build": "next build",
"start": "next start",
"lint": "next lint"
},
"dependencies": {
"@dynamic-labs/sdk-react-core": "^4.52.2",
"@dynamic-labs/solana": "^4.52.2",
"@dynamic-labs/solana-core": "^4.52.2",
"@solana/spl-token": "^0.4.14",
"@solana/web3.js": "^1.98.4",
"@t3-oss/env-nextjs": "^0.13.10",
"@tanstack/react-query": "^5.90.12",
"@vercel/functions": "^3.3.4",
"bs58": "^6.0.0",
"clsx": "^2.1.1",
"embla-carousel-react": "^8.6.0",
"lucide-react": "^0.487.0",
"motion": "^12.23.26",
"next": "^15.5.9",
"react": "^18.3.1",
"react-dom": "^18.3.1",
"tailwind-merge": "^3.4.0",
"zod": "^4.2.1"
},
"devDependencies": {
"@eslint/eslintrc": "^3.3.3",
"@tailwindcss/postcss": "^4.1.18",
"@types/node": "^20.19.27",
"@types/react": "^18.3.27",
"@types/react-dom": "^18.3.7",
"autoprefixer": "^10.4.23",
"eslint": "^9.39.2",
"eslint-config-next": "^15.5.9",
"postcss": "^8.5.6",
"tailwindcss": "^4.1.18",
"typescript": "^5.9.3"
}
}
Loading