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​
Option 1: SDK/iframe Integration (Recommended, Under Development)​
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.
Option 1: SDK/iframe Integration (Recommended)​
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​
- Provider Setup: You must have a provider account with API key
- User Authentication: Implement MCAP's wallet signature authentication flow
- Session Management: Create user sessions for trading
- 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​
- Frontend Integration: Build a React/Vue/Angular interface using these API calls
- Real-time Updates: Implement WebSocket connections for live AMM price updates
- Mobile App: Use these same endpoints for mobile app development
- Advanced Features: Add charting, analytics, and social features
- Testing: Use the provided endpoints to test your integration thoroughly
For complete API documentation, see the API Reference.