Skip to main content

Prediction Markets Integration Guide

Overview​

MCAP's Prediction Markets provide a powerful way to add event-based betting to your platform. Users can trade shares in future outcomes using real ERC-20 tokens, creating engaging markets around sports events, politics, entertainment, crypto, and more.

Integration Options​

Use MCAP's ready-made prediction market components for the fastest integration with minimal development effort.

Option 2: Custom API Integration​

Build your own prediction market interface from scratch using MCAP's comprehensive API endpoints.


Overview​

The SDK/iframe integration provides a complete prediction markets experience that you can embed directly into your platform. MCAP handles all the complex market mechanics, UI/UX, and real-time updates while you focus on your core platform.

Benefits​

  • âš¡ Rapid Deployment: Get prediction markets live in hours, not weeks
  • 🎯 Complete Solution: Full trading interface with charts, positions, and market data
  • 🔧 Zero Maintenance: We handle all updates, bug fixes, and improvements
  • 📱 Responsive Design: Works seamlessly on desktop and mobile
  • 💱 Advanced Features: AMM pricing with constant product formula, real-time updates, position management
  • 🎨 Customizable: Match your brand colors and styling

Implementation Methods​

Method 1: iframe Embedding​

The simplest integration method - just add an iframe to your page:

<!-- Basic iframe integration -->
<iframe
src="https://markets.mcap.ai/embed?provider=YOUR_PROVIDER_ID&theme=dark"
width="100%"
height="800px"
frameborder="0"
allow="clipboard-write">
</iframe>

<!-- Single market embed -->
<iframe
src="https://markets.mcap.ai/embed/market/market-123?provider=YOUR_PROVIDER_ID&theme=light"
width="100%"
height="600px"
style="border: none; border-radius: 8px;">
</iframe>

Supported Parameters:

  • provider: Your provider ID (required)
  • theme: light | dark | auto (default: auto)
  • token: Default token symbol (optional)
  • category: Filter markets by category (optional)
  • locale: en | es | fr | etc. (default: en)
  • hideHeader: true | false (default: false)

Method 2: SDK Integration​

For more control and better integration with your existing UI:

npm install @mcap/platform-sdk
import { MCAPMarkets } from '@mcap/platform-sdk';

// Initialize MCAP Markets
const mcapMarkets = new MCAPMarkets({
providerId: 'YOUR_PROVIDER_ID',
theme: 'dark',
apiUrl: 'https://api.mcap.ai'
});

// Mount markets browser
const marketsBrowser = await mcapMarkets.mountMarketsBrowser({
container: '#markets-container',
onMarketSelect: (market) => {
console.log('Market selected:', market);
},
onTradeComplete: (trade) => {
console.log('Trade completed:', trade);
// Handle trade completion
},
onError: (error) => {
console.error('Markets error:', error);
}
});

// Mount single market
const singleMarket = await mcapMarkets.mountMarket('market-123', {
container: '#single-market-container',
showChart: true,
showPositions: true,
customStyles: {
primaryColor: '#your-brand-color',
backgroundColor: '#your-bg-color'
}
});

Method 3: React Component Integration​

For React applications:

npm install @mcap/react-markets
import { MarketsBrowser, SingleMarket } from '@mcap/react-markets';

function MyMarketsPage() {
const handleTradeComplete = (trade: TradeResult) => {
// Handle successful trade
console.log('Trade completed:', trade);
};

return (
<div className="markets-page">
{/* Markets browser component */}
<MarketsBrowser
providerId="YOUR_PROVIDER_ID"
theme="dark"
category="sports"
onTradeComplete={handleTradeComplete}
onMarketSelect={(market) => console.log('Selected:', market)}
style={{
height: '800px',
borderRadius: '12px'
}}
/>

{/* Single market component */}
<SingleMarket
marketId="market-123"
providerId="YOUR_PROVIDER_ID"
showChart={true}
showPositions={true}
onTradeComplete={handleTradeComplete}
/>
</div>
);
}

Advanced Configuration​

Custom Styling​

const customTheme = {
colors: {
primary: '#your-primary-color',
secondary: '#your-secondary-color',
background: '#your-bg-color',
surface: '#your-surface-color',
text: '#your-text-color',
success: '#your-success-color',
error: '#your-error-color'
},
typography: {
fontFamily: 'Your-Font-Family',
fontSize: {
small: '12px',
medium: '14px',
large: '16px'
}
},
spacing: {
small: '8px',
medium: '16px',
large: '24px'
}
};

const markets = new MCAPMarkets({
providerId: 'YOUR_PROVIDER_ID',
theme: customTheme
});

Event Handling​

// Listen to market events
markets.on('marketCreated', (market) => {
console.log('New market created:', market);
});

markets.on('tradeExecuted', (trade) => {
console.log('Trade executed:', trade);
// Update your app's state
});

markets.on('positionUpdated', (position) => {
console.log('Position updated:', position);
// Update user's portfolio
});

markets.on('marketResolved', (resolution) => {
console.log('Market resolved:', resolution);
// Handle market resolution
});

Option 2: Custom API Integration​

Overview​

Build your own prediction markets interface using MCAP's comprehensive API endpoints. This option provides maximum flexibility and control over the user experience.

Implementation Guide​

This section provides a step-by-step guide for implementing a complete prediction markets platform using MCAP's API endpoints.

Prerequisites​

  1. Provider Setup: You must have a provider account with API key
  2. User Authentication: Implement MCAP's wallet signature authentication flow
  3. Session Management: Create user sessions for trading
  4. Token Configuration: Configure which ERC20 tokens users can deposit and trade with

For detailed setup instructions, see our Provider Onboarding Guide.

Step 1: Create a Prediction Market​

Provider Action - Use your API key to create markets for upcoming events.

Endpoint: Create Market

const createMarket = async (apiKey: string) => {
const response = await fetch('/v1/providers/markets', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${apiKey}`
},
body: JSON.stringify({
game_id: "game-456",
question: "Will Bitcoin reach $100k by end of 2024?",
description: "Prediction market for Bitcoin price milestone",
tags: ["crypto", "bitcoin", "price"],
token_id: "usdc-token-id",
min_bet_amount: "1000000000000000000", // 1 USDC in wei
max_bet_amount: "10000000000000000000", // 10 USDC in wei
liquidity: "1000000000000000000", // 1 USDC initial liquidity (in wei)
starts_at: "2024-01-01T00:00:00Z",
ends_at: "2024-12-31T23:59:59Z",
creator_wallet_id: "wallet-creator-123",
outcomes: [
{
title: "Yes - Bitcoin reaches $100k",
description: "Bitcoin will reach $100,000 by December 31, 2024",
outcome_index: 0
},
{
title: "No - Bitcoin stays below $100k",
description: "Bitcoin will not reach $100,000 by December 31, 2024",
outcome_index: 1
}
]
})
});

const market = await response.json();
console.log('Market created:', market.market.id);
return market;
};

Step 2: Display Available Markets​

Public Access - Anyone can browse markets without authentication.

Endpoint: Search Prediction Markets

const fetchMarkets = async (providerId: string) => {
const response = await fetch('/v1/markets/search', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
filters: {
provider_id: providerId,
status: "active"
},
pagination: { page: 1, per_page: 20 }
})
});

const data = await response.json();
return data.data; // Array of markets
};

const displayMarkets = (markets) => {
markets.forEach(market => {
// Calculate implied probabilities from prices
const outcomes = market.outcomes.map(outcome => ({
id: outcome.id,
title: outcome.title,
probability: (parseFloat(outcome.current_price) * 100).toFixed(1) + '%',
price: outcome.current_price
}));

console.log(`Market: ${market.question}`);
console.log('Outcomes:', outcomes);
});
};

Step 3: Get Market Details​

Public Access - Fetch detailed information about a specific market.

Endpoint: Get Market Details

const getMarketDetails = async (marketId: string) => {
const response = await fetch(`/v1/markets/${marketId}`);
const market = await response.json();

console.log('Market Details:');
console.log('Question:', market.question);
console.log('Total Pool:', market.total_pool);
console.log('Total Volume:', market.total_volume);
console.log('Outcomes:', market.outcomes);

return market;
};

Step 4: Preview Bet Impact​

Public Access - Show users potential returns before placing bets.

Endpoint: Preview Bet

const previewBet = async (outcomeId: string, amount: string) => {
const response = await fetch('/v1/markets/bet-preview', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
outcome_id: outcomeId,
amount: amount // Amount in wei
})
});

const preview = await response.json();

console.log('Bet Preview:');
console.log('Amount:', preview.amount);
console.log('Estimated Shares:', preview.estimated_shares);
console.log('Average Price:', preview.average_price);
console.log('Price Impact:', preview.price_impact);

return preview;
};

Step 5: User Authentication & Session Creation​

User Action - Users must authenticate and create a session to trade.

Endpoints:

// 1. Generate nonce for wallet signature
const generateNonce = async (walletAddress: string) => {
const response = await fetch('/v1/auth/nonce', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ wallet_address: walletAddress })
});

const data = await response.json();
return data.nonce;
};

// 2. Login with signed nonce (user signs with wallet)
const login = async (walletAddress: string, signature: string, nonce: string) => {
const response = await fetch('/v1/auth/login', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
wallet_address: walletAddress,
signature: signature,
nonce: nonce
})
});

const data = await response.json();
return data.access_token; // JWT token
};

// 3. Create trading session
const createSession = async (jwtToken: string, tokenId: string, gameId: string) => {
const response = await fetch('/v1/sessions', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${jwtToken}`
},
body: JSON.stringify({
token_id: tokenId,
game_id: gameId
})
});

const session = await response.json();
return session.id; // Session ID for trading
};

Step 6: Place Bets​

User Authentication Required - Users can now place bets on market outcomes.

Endpoint: Place Prediction Market Bet

const placeBet = async (
jwtToken: string,
marketId: string,
sessionId: string,
outcomeId: string,
amount: string
) => {
const response = await fetch(`/v1/markets/${marketId}/bet`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${jwtToken}`
},
body: JSON.stringify({
session_id: sessionId,
outcome_id: outcomeId,
amount: amount // Amount in wei
})
});

if (!response.ok) {
const error = await response.json();
throw new Error(`Bet failed: ${error.message}`);
}

const bet = await response.json();

console.log('Bet placed successfully:');
console.log('Bet ID:', bet.bet_id);
console.log('Shares Purchased:', bet.shares_purchased);
console.log('Average Price:', bet.average_price);
console.log('New Balance:', bet.balance_after);

return bet;
};

Step 7: Sell Shares​

User Authentication Required - Users can sell their shares for current market prices.

Endpoints:

// Preview sell first
const previewSell = async (outcomeId: string, sharesAmount: string) => {
const response = await fetch('/v1/markets/sell-preview', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
outcome_id: outcomeId,
shares_amount: sharesAmount // Shares to sell in wei
})
});

const preview = await response.json();
console.log('Estimated Proceeds:', preview.estimated_proceeds);
return preview;
};

// Execute sell
const sellShares = async (
jwtToken: string,
marketId: string,
sessionId: string,
outcomeId: string,
sharesAmount: string
) => {
const response = await fetch(`/v1/markets/${marketId}/sell`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${jwtToken}`
},
body: JSON.stringify({
session_id: sessionId,
outcome_id: outcomeId,
shares_amount: sharesAmount
})
});

const sale = await response.json();

console.log('Shares sold:');
console.log('Proceeds:', sale.proceeds);
console.log('Net Proceeds:', sale.net_proceeds);
console.log('New Balance:', sale.balance_after);

return sale;
};

Step 8: Track User Positions​

User Authentication Required - Display user's current holdings and P&L.

Endpoint: Search User Positions

const getUserPositions = async (jwtToken: string, marketId?: string) => {
const response = await fetch('/v1/markets/holdings/search', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${jwtToken}`
},
body: JSON.stringify({
filters: marketId ? { market_id: marketId } : {},
pagination: { page: 1, per_page: 50 }
})
});

const data = await response.json();

// Calculate P&L for each position
const positions = data.data.map(position => {
const currentValue = parseFloat(position.current_value);
const totalInvested = parseFloat(position.total_invested);
const unrealizedPnL = currentValue - totalInvested;
const percentageReturn = (unrealizedPnL / totalInvested) * 100;

return {
...position,
unrealized_pnl: unrealizedPnL,
percentage_return: percentageReturn
};
});

console.log('User Positions:', positions);
return positions;
};

Step 9: Market Resolution & Payouts​

Provider Action - Resolve markets and enable payout claims.

Endpoints:

// Provider resolves market
const resolveMarket = async (apiKey: string, marketId: string, winningOutcomeId: string) => {
const response = await fetch(`/v1/providers/markets/${marketId}/resolve`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${apiKey}`
},
body: JSON.stringify({
winning_outcome_id: winningOutcomeId,
resolver_wallet_id: "wallet-resolver-123",
resolution_source: "CoinGecko API",
resolution_data: {
final_price: "$98,500",
date_checked: "2024-12-31T23:59:59Z",
source_url: "https://coingecko.com/bitcoin"
}
})
});

const resolution = await response.json();
console.log('Market resolved. Payout ratio:', resolution.payout_ratio);
return resolution;
};

// User claims payout
const claimPayout = async (jwtToken: string, positionId: string, sessionId: string) => {
const response = await fetch(`/v1/markets/positions/${positionId}/claim`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${jwtToken}`
},
body: JSON.stringify({
session_id: sessionId
})
});

const claim = await response.json();

console.log('Payout claimed:');
console.log('Claimed Amount:', claim.claimed_amount);
console.log('New Balance:', claim.balance_after);

return claim;
};

Complete Implementation Example​

Here's a complete workflow combining all the steps:

class PredictionMarketsPlatform {
constructor(private apiKey: string, private providerId: string) {}

// Provider creates market
async createBitcoinMarket() {
return await createMarket(this.apiKey);
}

// Public browsing
async displayAvailableMarkets() {
const markets = await fetchMarkets(this.providerId);
displayMarkets(markets);
return markets;
}

// User trading flow
async userTradingFlow(walletAddress: string, privateKey: string) {
// 1. Authentication
const nonce = await generateNonce(walletAddress);
const signature = signMessage(nonce, privateKey); // Implement wallet signing
const jwtToken = await login(walletAddress, signature, nonce);

// 2. Create session
const sessionId = await createSession(jwtToken, "usdc-token-id", "game-456");

// 3. Browse and select market
const markets = await fetchMarkets(this.providerId);
const marketId = markets[0].id;
const outcomeId = markets[0].outcomes[0].id;

// 4. Preview and place bet
const preview = await previewBet(outcomeId, "5000000000000000000"); // 5 USDC
console.log('Preview:', preview);

const bet = await placeBet(jwtToken, marketId, sessionId, outcomeId, "5000000000000000000");
console.log('Bet placed:', bet);

// 5. Check positions
const positions = await getUserPositions(jwtToken, marketId);
console.log('Current positions:', positions);

// 6. Later - sell shares
const sellPreview = await previewSell(outcomeId, bet.shares_purchased);
console.log('Sell preview:', sellPreview);

return { bet, positions };
}

// Provider resolves market
async resolveMarket(marketId: string, winningOutcomeId: string) {
return await resolveMarket(this.apiKey, marketId, winningOutcomeId);
}
}

Error Handling​

Implement proper error handling for common scenarios:

const handleApiError = (error: any) => {
switch (error.code) {
case 'INSUFFICIENT_BALANCE':
return 'You don\'t have enough funds to place this bet';
case 'MARKET_CLOSED':
return 'This market is no longer accepting bets';
case 'INVALID_SESSION':
return 'Your session has expired. Please reconnect your wallet';
case 'MINIMUM_BET_NOT_MET':
return 'Bet amount is below the minimum required';
default:
return error.message || 'An unexpected error occurred';
}
};

Next Steps​

  1. Frontend Integration: Build a React/Vue/Angular interface using these API calls
  2. Real-time Updates: Implement WebSocket connections for live AMM price updates
  3. Mobile App: Use these same endpoints for mobile app development
  4. Advanced Features: Add charting, analytics, and social features
  5. Testing: Use the provided endpoints to test your integration thoroughly

For complete API documentation, see the API Reference.