# CloddsBot Polymarket and Kalshi Integration: Internal Architecture and Implementation

> Discover CloddsBot's modular plugin architecture integrating Polymarket and Kalshi. Learn how unified algorithmic trading is achieved through identical TypeScript interfaces for seamless prediction market interaction.

- Repository: [AL/CloddsBot](https://github.com/alsk1992/CloddsBot)
- Tags: architecture
- Published: 2026-09-11

---

**CloddsBot employs a modular plugin architecture that abstracts Polymarket and Kalshi behind identical TypeScript interfaces for authentication, market data feeds, and order execution, enabling unified algorithmic trading across both prediction market platforms.**

The CloddsBot repository (`alsk1992/CloddsBot`) demonstrates production-grade integration patterns for prediction market APIs. By treating each platform as an interchangeable plugin—supplying authentication, feed normalization, and execution layers through common interfaces—the same market-making and portfolio management code operates seamlessly on both Polymarket and Kalshi without platform-specific modifications.

## Modular Plugin Architecture Overview

CloddsBot structures each prediction market integration as a three-layer plugin supplying **authentication**, **market data feeds**, and **execution services**. All layers expose typed interfaces (`KalshiFeed`, `PolymarketFeed`, `ExecutionService`) defined in [`src/types.ts`](https://github.com/alsk1992/CloddsBot/blob/main/src/types.ts), allowing the higher-level trading engine to consume platform-agnostic data structures.

| Layer | Polymarket Implementation | Kalshi Implementation |
|-------|---------------------------|----------------------|
| **Authentication** | HMAC-SHA256 request signing ([`src/utils/polymarket-auth.ts`](https://github.com/alsk1992/CloddsBot/blob/main/src/utils/polymarket-auth.ts)) | RSA-PSS signature generation ([`src/utils/kalshi-auth.ts`](https://github.com/alsk1992/CloddsBot/blob/main/src/utils/kalshi-auth.ts)) |
| **Market Data** | REST + WebSocket client (`src/feeds/polymarket/*`) | WebSocket client with event normalization ([`src/feeds/kalshi/index.ts`](https://github.com/alsk1992/CloddsBot/blob/main/src/feeds/kalshi/index.ts)) |
| **Execution** | EIP-712 order signing + REST ([`src/execution/polymarket.ts`](https://github.com/alsk1992/CloddsBot/blob/main/src/execution/polymarket.ts)) | RSA-signed HTTP requests ([`src/execution/kalshi.ts`](https://github.com/alsk1992/CloddsBot/blob/main/src/execution/kalshi.ts)) |

This architecture ensures that components like the market-making engine in [`src/trading/market-making/index.ts`](https://github.com/alsk1992/CloddsBot/blob/main/src/trading/market-making/index.ts) and the portfolio sync skill in [`src/skills/bundled/portfolio-sync/index.ts`](https://github.com/alsk1992/CloddsBot/blob/main/src/skills/bundled/portfolio-sync/index.ts) remain platform-agnostic.

## Authentication Layer Implementation

### Polymarket HMAC-SHA256 Signing

Polymarket authentication utilizes HMAC-SHA256 signatures of the request path, method, and timestamp. The `buildPolymarketHeadersForUrl` function in [`src/utils/polymarket-auth.ts`](https://github.com/alsk1992/CloddsBot/blob/main/src/utils/polymarket-auth.ts) generates the required headers:

```typescript
// src/utils/polymarket-auth.ts
export interface PolymarketApiKeyAuth {
  apiKey: string;
  apiSecret: string;
}

export function buildPolymarketHeadersForUrl(
  auth: PolymarketApiKeyAuth,
  method: string,
  url: string,
): Record<string, string> {
  const timestamp = Math.floor(Date.now() / 1_000);
  const payload = `${timestamp}${method}${new URL(url).pathname}`;
  const signature = createHmac('sha256', auth.apiSecret).update(payload).digest('base64');
  return {
    'X-API-KEY': auth.apiKey,
    'X-API-SIGNATURE': signature.replace(/\+/g, '-').replace(/\//g, '_'),
    'X-API-TIMESTAMP': timestamp.toString(),
  };
}

```

The function Base64-URL-encodes the signature to comply with Polymarket's CLOB API requirements.

### Kalshi RSA-PSS Signing

Kalshi requires RSA-PSS signatures over the request string containing the API key ID, timestamp, method, and URL. Implemented in [`src/utils/kalshi-auth.ts`](https://github.com/alsk1992/CloddsBot/blob/main/src/utils/kalshi-auth.ts), the `buildKalshiHeadersForUrl` function constructs the authentication headers:

```typescript
// src/utils/kalshi-auth.ts
export interface KalshiApiKeyAuth {
  apiKeyId: string;
  privateKeyPem: string;
}

export function buildKalshiHeadersForUrl(
  auth: KalshiApiKeyAuth,
  method: string,
  url: string,
): Record<string, string> {
  const timestamp = Date.now();
  const toSign = `${timestamp}${method}${url}`;
  const signature = buildKalshiSignature(auth, toSign);
  return {
    'KALSHI-ACCESS-KEY': auth.apiKeyId,
    'KALSHI-ACCESS-TIMESTAMP': timestamp.toString(),
    'KALSHI-ACCESS-SIGNATURE': signature,
  };
}

```

The private key must be provided in PEM format, and the signature algorithm follows Kalshi's specific RSA-PSS requirements for API authentication.

## Market Data Feed Normalization

### Kalshi WebSocket Feed

The `createKalshiFeed` function in [`src/feeds/kalshi/index.ts`](https://github.com/alsk1992/CloddsBot/blob/main/src/feeds/kalshi/index.ts) establishes a WebSocket connection to `wss://api.elections.kalshi.com/trade-api/ws/v2` using the RSA authentication headers. It emits strongly-typed events for price updates, trades, order book deltas, and fills:

```typescript
// src/feeds/kalshi/index.ts – connection snippet
const headers = buildKalshiHeadersForUrl(apiKeyAuth, 'GET', WS_URL);
ws = new WebSocket(WS_URL, { headers });

```

The feed implements an `EventEmitter` interface that normalizes raw WebSocket messages into standard formats (`price`, `trade`, `orderbook_delta`, `fill`), enabling the trading engine to process Kalshi data identically to other platforms. When API credentials are unavailable, the feed automatically falls back to HTTP polling for public market data.

### Polymarket Feed Architecture

Polymarket follows an identical pattern through `src/feeds/polymarket/*`, combining REST API calls for market snapshots with optional WebSocket connections via the Polymarket CLOB client. Like the Kalshi implementation, it emits normalized `price` events and order book updates, ensuring the `TradingEngine` requires no platform-specific conditional logic.

## Order Construction and Execution

### Polymarket EIP-712 Order Signing

Polymarket orders require EIP-712 typed data signatures compatible with the CTF Exchange contract. The [`polymarket-order-signer.ts`](https://github.com/alsk1992/CloddsBot/blob/main/polymarket-order-signer.ts) utility constructs the domain separator and types, then calls the wallet's `_signTypedData` method:

```typescript
// src/utils/polymarket-order-signer.ts – V2 signer excerpt
const domain = {
  name: 'Polymarket CTF Exchange',
  version: '2',
  chainId: 137,
  verifyingContract: contractAddress,
};
const types = { Order: [ /* ... */ ] };
const signature = await wallet._signTypedData(domain, types, order);

```

The domain specifies **chainId 137** (Polygon mainnet) and targets the CTF Exchange contract. The resulting signature accompanies order placement via the execution service.

### Execution Service Interface

Both platforms implement the common `ExecutionService` interface defined in [`src/execution/index.ts`](https://github.com/alsk1992/CloddsBot/blob/main/src/execution/index.ts). This abstraction provides four core methods:

- **`placeOrder(order)`**: Submits signed orders to the platform (Polymarket via EIP-712 signatures, Kalshi via RSA-signed HTTP POSTs)
- **`cancelOrder(orderId)`**: Issues cancellation requests
- **`getOpenOrders()`**: Retrieves current open positions
- **`getBalance()`**: Fetches available cash (Polymarket queries on-chain USDC balances, Kalshi uses API-provided cash values)

Concrete implementations in [`src/execution/kalshi.ts`](https://github.com/alsk1992/CloddsBot/blob/main/src/execution/kalshi.ts) and [`src/execution/polymarket.ts`](https://github.com/alsk1992/CloddsBot/blob/main/src/execution/polymarket.ts) handle platform-specific API endpoints while exposing identical method signatures.

## Unified Trading Engine

### Market-Making Strategy Implementation

The market-making engine in [`src/trading/market-making/index.ts`](https://github.com/alsk1992/CloddsBot/blob/main/src/trading/market-making/index.ts) orchestrates quote placement across both platforms using the unified interfaces. It receives normalized price updates from either `KalshiFeed` or `PolymarketFeed`, calculates spreads and sizing, then dispatches orders through the `ExecutionService`.

Critical platform differences are handled at the integration layer:

- **Polymarket**: Supports **batch order placement**, allowing the engine to submit multiple orders in a single HTTP POST to minimize gas fees and latency.
- **Kalshi**: Requires **individual order placement** as the API does not support batching; the engine iterates through desired positions and places separate requests.

The engine references a unified `Market` type defined in [`src/types.ts`](https://github.com/alsk1992/CloddsBot/blob/main/src/types.ts), where each record includes a `platform` discriminator field (`'polymarket' | 'kalshi'`), enabling strategy code to remain agnostic while the execution layer handles platform specifics.

## Portfolio Synchronization

The portfolio sync skill ([`src/skills/bundled/portfolio-sync/index.ts`](https://github.com/alsk1992/CloddsBot/blob/main/src/skills/bundled/portfolio-sync/index.ts)) demonstrates the architecture's flexibility by aggregating positions and balances from both platforms into a single unified view. Using the feed services to retrieve market data and execution services to fetch account states, the skill normalizes disparate data formats into common portfolio objects.

Users trigger platform-specific synchronization via commands like `/portfolio-sync kalshi` or `/portfolio-sync polymarket`, yet the underlying implementation relies on the same abstracted service interfaces, requiring no code duplication for multi-platform portfolio tracking.

## Summary

- **CloddsBot Polymarket Kalshi integration** relies on a three-layer plugin architecture separating authentication, data feeds, and execution into interchangeable components.
- **Authentication differs by platform**: Polymarket uses HMAC-SHA256 ([`src/utils/polymarket-auth.ts`](https://github.com/alsk1992/CloddsBot/blob/main/src/utils/polymarket-auth.ts)) while Kalshi requires RSA-PSS signing ([`src/utils/kalshi-auth.ts`](https://github.com/alsk1992/CloddsBot/blob/main/src/utils/kalshi-auth.ts)).
- **Data feeds normalize** WebSocket and REST inputs into common EventEmitter interfaces, enabling the trading engine to process `price` and `orderbook` events identically regardless of source.
- **Order signing varies**: Polymarket requires EIP-712 typed data signatures on Polygon (chainId 137), while Kalshi relies on RSA-signed HTTP headers.
- **The ExecutionService interface** ([`src/execution/index.ts`](https://github.com/alsk1992/CloddsBot/blob/main/src/execution/index.ts)) abstracts placement, cancellation, and balance queries, allowing market-making strategies to work across both platforms without modification.
- **Batch optimization** is available for Polymarket but not Kalshi, handled transparently within each platform's execution implementation.

## Frequently Asked Questions

### How does CloddsBot handle authentication differences between Polymarket and Kalshi?

CloddsBot implements platform-specific authentication modules that expose identical header-generation interfaces. For Polymarket, `buildPolymarketHeadersForUrl` in [`src/utils/polymarket-auth.ts`](https://github.com/alsk1992/CloddsBot/blob/main/src/utils/polymarket-auth.ts) creates HMAC-SHA256 signatures using the API secret. For Kalshi, `buildKalshiHeadersForUrl` in [`src/utils/kalshi-auth.ts`](https://github.com/alsk1992/CloddsBot/blob/main/src/utils/kalshi-auth.ts) generates RSA-PSS signatures from a PEM-encoded private key. Both return header objects that the HTTP clients consume uniformly.

### What enables the same trading strategy to work on both Polymarket and Kalshi?

The **unified type system** in [`src/types.ts`](https://github.com/alsk1992/CloddsBot/blob/main/src/types.ts) and the **ExecutionService interface** provide the abstraction layer. Market data feeds emit normalized events (`price`, `trade`, `fill`) through a common `EventEmitter` pattern, while the execution service standardizes order placement, cancellation, and balance queries. The market-making engine interacts only with these abstractions, remaining unaware of whether it is trading on Polymarket or Kalshi.

### Why does Polymarket use EIP-712 signing while Kalshi uses RSA headers?

Polymarket operates on the Polygon blockchain through the CTF Exchange contract, requiring on-chain verifiable signatures that comply with the EIP-712 standard for typed structured data hashing. Kalshi operates as a traditional centralized exchange with a REST API, using RSA-PSS signatures over HTTP request strings to authenticate API calls without blockchain interaction. CloddsBot encapsulates these differences in [`src/utils/polymarket-order-signer.ts`](https://github.com/alsk1992/CloddsBot/blob/main/src/utils/polymarket-order-signer.ts) and [`src/utils/kalshi-auth.ts`](https://github.com/alsk1992/CloddsBot/blob/main/src/utils/kalshi-auth.ts) respectively.

### Does CloddsBot support batch order placement for both platforms?

No. According to the source code in [`src/trading/market-making/index.ts`](https://github.com/alsk1992/CloddsBot/blob/main/src/trading/market-making/index.ts), **Polymarket supports batch order placement** (submitting multiple orders in a single array), which reduces gas costs and API latency. **Kalshi does not support batching**, requiring individual HTTP POST requests for each order. The execution service implementations handle this distinction transparently, so the trading engine simply calls `placeOrder` without managing the batching logic itself.