Skip to main content
Logo
Explore APIsContact Us
  • Home
  1. Resources
  2. Virtual Stadium
  3. Bet Share

Bet Share

Virtual Stadium widgets can request the user's previously shared bets for users to share in chat. This is handled through the betHistory provider function that must be implemented and registered with the adapter.

#Overview

To integrate bet sharing with Virtual Stadium:

1

#Step 1

Implement a betHistory provider function (promise, callback, or return style).

2

#Step 2

Register the adapter with the betHistory option.

3

#Step 3

Handle requests for user bets, optionally filtering by events or already shared IDs.

4

#Step 4

Return bet objects in the expected format.

The widgets will call your provider function when users interact with bet sharing features.


#Implementation

The betHistory function receives arguments about the user and context, and returns a list of shared bets.

#Arguments

userId string required

The ID of the user whose bets to retrieve.

channelId string optional

Channel for which tickets are requested.

events Event[] optional

Array of event objects used to filter the returned bets. It is recommended that only bets that contain at least one individual bet related to any of the specified events should be included in the response.

alreadySharedBetIds string[] optional

Array of bet IDs that have already been shared, to avoid duplicates in the response.

#Response

bets BetSlip[] required

Array of user's placed tickets filtered by the provided arguments, containing all necessary data to enable bet reproduction through copy bet functionality.

Callback-based Provider:

js
function betHistoryCallback(args, callback) {
    // Validate required parameters
    if (!args.userId) {
        return callback(new Error('userId required'));
    }

    // Fetch user's shared bets from your backend API or tickets system
    // Implement filtering logic based on provided arguments
    fetchUserBets(args.userId, (error, allBets) => {
        if (error) {
            return callback(error);
        }

        let filteredBets = allBets;

        // Filter by events if provided
        if (args.events && args.events.length > 0) {
            const eventIds = args.events.map(event => event.id);
            filteredBets = filteredBets.filter(bet =>
                bet.bets.some(betItem => eventIds.includes(betItem.event.id))
            );
        }

        // Exclude already shared bets if provided
        if (args.alreadySharedBetIds && args.alreadySharedBetIds.length > 0) {
            filteredBets = filteredBets.filter(bet =>
                !args.alreadySharedBetIds.includes(bet.id)
            );
        }

        // Convert filteredBets to expected structure (example transformation)
        const bets = filteredBets.map(bet => ({
            id: bet.id || 'sr:bet-share-event:single',
            betSlipId: bet.betSlipId || 'sr:bet-share-event:single',
            betType: bet.betType || 'single',
            currency: bet.currency || 'USD',
            combinedOdds: bet.combinedOdds || { decimalValue: 2.55, displayValue: '2.55' },
            stake: bet.stake || { value: '50.00' },
            payout: bet.payout || { value: '127.50' },
            bets: bet.bets || [{
                id: 'xxx',
                markets: [{
                    name: 'Total',
                    outcomes: [{
                        name: 'Under 1.5',
                        odds: 13.37
                    }]
                }],
                odds: { decimalValue: 13.37 },
                event: { name: 'Match name' }
            }]
        }));

        callback(null, { bets });
    });
}

Promise-based Provider:

js
function betHistoryPromise(args) {
    return new Promise((resolve, reject) => {
        // Validate required parameters
        if (!args.userId) {
            return reject(new Error('userId required'));
        }

        // Fetch user's shared bets from your backend API or tickets system
        // Implement filtering logic based on provided arguments
        fetchUserBets(args.userId)
            .then(allBets => {
                let filteredBets = allBets;

                // Filter by events if provided
                if (args.events && args.events.length > 0) {
                    const eventIds = args.events.map(event => event.id);
                    filteredBets = filteredBets.filter(bet =>
                        bet.bets.some(betItem => eventIds.includes(betItem.event.id))
                    );
                }

                // Exclude already shared bets if provided
                if (args.alreadySharedBetIds && args.alreadySharedBetIds.length > 0) {
                    filteredBets = filteredBets.filter(bet =>
                        !args.alreadySharedBetIds.includes(bet.id)
                    );
                }

                // Convert filteredBets to expected structure (example transformation)
                const bets = filteredBets.map(bet => ({
                    id: bet.id || 'sr:bet-share-event:single',
                    betSlipId: bet.betSlipId || 'sr:bet-share-event:single',
                    betType: bet.betType || 'single',
                    currency: bet.currency || 'USD',
                    combinedOdds: bet.combinedOdds || { decimalValue: 2.55, displayValue: '2.55' },
                    stake: bet.stake || { value: '50.00' },
                    payout: bet.payout || { value: '127.50' },
                    bets: bet.bets || [{
                        id: 'xxx',
                        markets: [{
                            name: 'Total',
                            outcomes: [{
                                name: 'Under 1.5',
                                odds: 13.37
                            }]
                        }],
                        odds: { decimalValue: 13.37 },
                        event: { name: 'Match name' }
                    }]
                }));

                resolve({ bets });
            })
            .catch(error => reject(error));
    });
}

Synchronous Return Provider:

js
function betHistoryReturn(args) {
    // Validate required parameters
    if (!args.userId) {
        throw new Error('userId required');
    }

    // Fetch user's shared bets synchronously from your backend or tickets system
    let allBets = fetchUserBetsSync(args.userId);
    let filteredBets = allBets;

    // Filter by events if provided
    if (args.events && args.events.length > 0) {
        const eventIds = args.events.map(event => event.id);
        filteredBets = filteredBets.filter(bet =>
            bet.bets.some(betItem => eventIds.includes(betItem.event.id))
        );
    }

    // Exclude already shared bets if provided
    if (args.alreadySharedBetIds && args.alreadySharedBetIds.length > 0) {
        filteredBets = filteredBets.filter(bet =>
            !args.alreadySharedBetIds.includes(bet.id)
        );
    }

    // Convert filteredBets to expected structure (example transformation)
    const bets = filteredBets.map(bet => ({
        id: bet.id || 'sr:bet-share-event:single',
        betSlipId: bet.betSlipId || 'sr:bet-share-event:single',
        betType: bet.betType || 'single',
        currency: bet.currency || 'USD',
        combinedOdds: bet.combinedOdds || { decimalValue: 2.55, displayValue: '2.55' },
        stake: bet.stake || { value: '50.00' },
        payout: bet.payout || { value: '127.50' },
        bets: bet.bets || [{
            id: 'xxx',
            markets: [{
                name: 'Total',
                outcomes: [{
                    name: 'Under 1.5',
                    odds: 13.37
                }]
            }],
            odds: { decimalValue: 13.37 },
            event: { name: 'Match name' }
        }]
    }));

    return { bets };
}

For the complete Bet Data Structure reference, see Bet Data Structure.


#Registering the Adapter

Once the betHistory function is implemented, register it with the Virtual Stadium adapter.

Pass the function in the options object when calling SIR('registerAdapter').

Register Adapter with betHistory:

js
SIR('registerAdapter', 'myAdapter', {
    betHistory: betHistoryPromise  // or betHistoryCallback
});

#Complete Integration Example

Here's a complete example based on the client integration file, showing how to set up bet sharing in a real application.

This example uses a promise-based provider and includes sample bet data.

Complete HTML Integration (adapted from betInsightTest.html):

html
<!DOCTYPE html>
<html>
<head>
    <script src="https://widgets.sir.sportradar.com/.../widgetloader"></script>
</head>
<body>
    <script>
        // Sample bet data
        const sampleBet = {
            id: 'sr:bet-share-event:single',
            betSlipId: 'sr:bet-share-event:single',
            betType: 'single',
            currency: 'USD',
            combinedOdds: { decimalValue: 2.55, displayValue: '2.55' },
            stake: { value: '50.00' },
            payout: { value: '127.50' },
            bets: [{
                id: 'xxx',
                markets: [{
                    name: 'Total',
                    outcomes: [{
                        name: 'Under 1.5',
                        odds: 13.37
                    }]
                }],
                odds: { decimalValue: 13.37 },
                event: { name: 'Match name' }
            }]
        };

        // Promise-based betHistory provider
        function betHistoryPromise(args) {
            return Promise.resolve({
                bets: [sampleBet]
            });
        }

        // Register adapter
        SIR('registerAdapter', 'myAdapter', {
            betHistory: betHistoryPromise
        });

        // Add Virtual Stadium widget
        /**
         * TODO(developer): Replace 'your-jwt-token' with your actual JWT token
         * and 'your-channel' with your actual channel ID before running this code.
         */
        SIR('addWidget', '.vs-container', 'virtualStadium', {
            jwt: 'your-jwt-token',
            channelId: 'your-channel'
        });
    </script>
    <div class="vs-container"></div>
</body>
</html>

#Related Documentation

For information on implementing the copy bet functionality that works alongside bet sharing, see the Copy Bet Button documentation.

Last updated about 2 months ago
Is this site helpful?
Virtual Stadium, Moderation, Engagement Tools, BET
Getting StartedCustom Adapter
On this page
  • Overview
  • Step 1
  • Step 2
  • Step 3
  • Step 4
  • Implementation
  • Arguments
  • Response
  • Registering the Adapter
  • Complete Integration Example
  • Related Documentation