TypeScript SDK for the WahooPredict trading API
npm install @wahoopredict/trading-sdkTypeScript SDK for the WahooPredict trading API. Built on openapi-fetch for type-safe API calls.
``bash`
npm install @wahoopredict/trading-sdk
`typescript
import { createWahooClient } from "@wahoopredict/trading-sdk";
const client = createWahooClient({
apiKey: "your-api-key",
secretKey: "your-secret-key",
});
// Get your balance
const { data, error } = await client.GET("/user/profile", {
params: { query: { fields: ["balance", "totalBalance"] } },
});
if (error) {
console.error("Error:", error);
} else {
console.log("Balance:", data.user?.balance);
}
`
`typescript`
const client = createWahooClient({
apiKey: "your-api-key",
secretKey: "your-secret-key",
});
We recommend storing credentials in environment variables:
`typescript`
const client = createWahooClient({
apiKey: process.env.WAHOO_API_KEY!,
secretKey: process.env.WAHOO_SECRET_KEY!,
});
The SDK uses HMAC-SHA256 signature-based authentication. You need an API key and secret key from WahooPredict.
The authentication headers are automatically added to every request:
- X-API-KEY - Your API keyX-TIMESTAMP
- - Current Unix timestamp (seconds)X-SIGNATURE
- - HMAC-SHA256 signature of apiKey + timestamp + requestBody
#### Get Events List
`typescript
const { data, error } = await client.POST("/event/events-list", {
body: {
page: 1,
limit: 20,
filter: {
status: ["LIVE"],
search: "bitcoin",
},
sort: {
sortBy: "volume",
sortOrder: "desc",
},
},
});
// Access events
data?.data.forEach((event) => {
console.log(event.title, event.status);
});
`
#### Get Event Details
`typescript
const { data, error } = await client.GET("/event/event-details/{eventId}", {
params: {
path: { eventId: "cmkhbgto400rl01uqr9gn3mna" },
},
});
// data is the Event object directly
console.log(data?.title);
console.log(data?.outcomes); // Array of possible outcomes
`
#### Get Order Book
`typescript
const { data, error } = await client.GET("/event/orderbook", {
params: {
query: { outcomeOptionId: "cmkhbgw8f00t001uqprn3a2pk" },
},
});
console.log("Bids:", data?.bids);
console.log("Asks:", data?.asks);
`
#### Test Order (Simulate)
Before placing an order, you can test it to see the potential return:
`typescript
const { data, error } = await client.POST("/event/test-order", {
body: {
eventId: "cmkhbgto400rl01uqr9gn3mna",
outcomeOptionId: "cmkhbgw8f00t001uqprn3a2pk",
side: "BUY",
type: "MARKET",
amount: "10.00",
},
});
if (data) {
console.log("Potential return:", data.potentialReturn);
}
`
#### Place Market Order
`typescript
const { data, error } = await client.POST("/event/place-order", {
body: {
eventId: "cmkhbgto400rl01uqr9gn3mna",
outcomeOptionId: "cmkhbgw8f00t001uqprn3a2pk",
side: "BUY",
type: "MARKET",
amount: "10.00", // Amount to spend (for BUY)
},
});
if (data) {
console.log("Order placed! New balance:", data.newBalance);
}
`
#### Place Limit Order
`typescript`
const { data, error } = await client.POST("/event/place-order", {
body: {
eventId: "cmkhbgto400rl01uqr9gn3mna",
outcomeOptionId: "cmkhbgw8f00t001uqprn3a2pk",
side: "BUY",
type: "LIMIT",
size: "100", // Number of shares
price: "0.45", // Price per share
},
});
#### Cancel Order
`typescript
const { data, error } = await client.DELETE("/event/cancel-order", {
params: {
query: { orderId: "order-id-here" },
},
});
if (data) {
console.log("Order cancelled! New balance:", data.newBalance);
}
`
#### Get Your Orders
`typescript
const { data, error } = await client.POST("/event/orders", {
body: {
page: 1,
limit: 20,
filter: {
isOpen: true, // Only open orders
},
},
});
data?.data.forEach((order) => {
console.log(${order.side} ${order.size} @ ${order.price} - ${order.status});`
});
#### Get Your Positions
`typescript
const { data, error } = await client.POST("/event/positions", {
body: {
page: 1,
limit: 20,
},
});
data?.data.forEach((position) => {
console.log(
Position: ${position.part} shares, avg price: ${position.avgPrice},`
);
});
#### Collect Position (After Event Resolution)
`typescript
const { data, error } = await client.POST("/event/collect-position", {
body: {
positionId: "position-id-here",
},
});
if (data) {
console.log("Position collected! New balance:", data.newBalance);
}
`
`typescript
const { data, error } = await client.GET("/user/profile", {
params: {
query: {
fields: ["id", "username", "balance", "totalBalance", "bonusBalance"],
},
},
});
console.log("User:", data?.user?.username);
console.log("Balance:", data?.user?.balance);
`
The SDK returns errors in a consistent format:
`typescript
const { data, error } = await client.POST("/event/place-order", {
body: {
/ ... /
},
});
if (error) {
// error has type-safe structure based on the endpoint
console.error("Error:", error.message);
console.error("Error type:", error.error);
// Handle specific error types
if (error.error === "BetsClosed") {
console.log("Trading is closed for this outcome");
} else if (error.error === "InsufficientBalance") {
console.log("Not enough balance");
}
}
`
Common error types:
- BetsClosed - Trading is closed for this outcomeEmptyOrderBook
- - No liquidity for market ordersInternalRestriction
- - Order restrictions applyInsufficientBalance
- - Not enough balanceEventNotFound
- - Event doesn't existNotFound
- - Resource not found
The SDK provides full TypeScript support with auto-generated types from the OpenAPI specification.
For most usage, TypeScript inference handles everything:
`typescript
// Just works — no type imports needed
const { data, error } = await client.POST("/event/positions", {
body: { page: 1, limit: 20 },
});
// TypeScript knows data.data is Position[]
data?.data.forEach((position) => {
console.log(position.id, position.avgPrice); // Full autocomplete
});
`
Import types when you're writing functions that accept or return SDK data:
`typescript
import type { components } from "@wahoopredict/trading-sdk";
type Position = components["schemas"]["Position"];
type Event = components["schemas"]["Event"];
// Now you can use Position in your own function signatures
function filterProfitablePositions(positions: Position[]): Position[] {
return positions.filter((p) => parseFloat(p.part) > 100);
}
async function getEventWithPositions(client: WahooClient, eventId: string) {
const [event, positions] = await Promise.all([
client.GET("/event/event-details/{eventId}", {
params: { path: { eventId } },
}),
client.POST("/event/positions", { body: { page: 1, limit: 100 } }),
]);
return {
event: event.data as Event | undefined,
positions: positions.data?.data as Position[] | undefined,
};
}
`
`typescript
import type { components, operations } from "@wahoopredict/trading-sdk";
// Entity types
type Event = components["schemas"]["Event"];
type Position = components["schemas"]["Position"];
type Order = components["schemas"]["Order"];
type Outcome = components["schemas"]["Outcome"];
type OutcomeOption = components["schemas"]["OutcomeOption"];
// Request body types (for building params programmatically)
type PlaceOrderParams = components["schemas"]["placeOrderRequestBody"];
type EventsListParams =
operations["getEventsList"]["requestBody"]["content"]["application/json"];
// Response types (for annotating wrapper function returns)
type EventsListResponse =
operations["getEventsList"]["responses"]["200"]["content"]["application/json"];
type EventsListItem = EventsListResponse["data"][number];
`
The paths type gives you access to request/response types for any endpoint:
`typescript
import type { paths } from "@wahoopredict/trading-sdk";
// Extract request body type
type PlaceOrderBody =
paths["/event/place-order"]["post"]["requestBody"]["content"]["application/json"];
// Extract successful response type
type PlaceOrderResponse =
paths["/event/place-order"]["post"]["responses"]["200"]["content"]["application/json"];
// Extract error response type
type PlaceOrderError =
paths["/event/place-order"]["post"]["responses"]["400"]["content"]["application/json"];
``