UNPKG

betfair-sports-api

Version:

Betfair Sports API for Node

354 lines (301 loc) 10.2 kB
// (C) 2012 Anton Zemlyanov // // Emulator allows test bots for "free" using real price data // // The following API calls are intercepted in emulator mode // read-only // - getMUBets // - getCurrentBets // transactional // - placeBets // - cancelBets // - updateBets var decoder = require('./emulator_decoder'); var encoder = require('./emulator_encoder'); var EmulatorMarket = require('./emulator_market'); function Emulator() { var self = this; self.markets = {}; } // Feed market prices to emulator Emulator.prototype.onGetCompleteMarketPricesCompressed = function(result) { var self = this; if (result.errorCode !== 'OK') return false; var completePrices = result.completeMarketPrices || {}; var marketId = completePrices.marketId; if (!marketId) return false; var emulatorMarket = self.markets[marketId]; if (!emulatorMarket) { var emulatorMarket = new EmulatorMarket(marketId); self.markets[marketId] = emulatorMarket; } // dispatch call result to apropriate market return emulatorMarket.onGetCompleteMarketPricesCompressed(result); } // Feed market prices to emulator Emulator.prototype.onGetMarketPricesCompressed = function(result) { var self = this; if (result.errorCode !== 'OK') return false; var prices = result.marketPrices || {}; var marketId = prices.marketId; if (!marketId) return false; var emulatorMarket = self.markets[marketId]; if (!emulatorMarket) { var emulatorMarket = new EmulatorMarket(marketId); self.markets[marketId] = emulatorMarket; } // dispatch call result to apropriate market return emulatorMarket.onGetMarketPricesCompressed(result); } // Feed market traded volumes to emulator Emulator.prototype.onGetMarketTradedVolumeCompressed = function(result) { var self = this; if (result.errorCode !== 'OK') return false; var marketId = result.marketId; if (!marketId) return false; var emulatorMarket = self.markets[marketId]; if (!emulatorMarket) { var emulatorMarket = new EmulatorMarket(marketId); self.markets[marketId] = emulatorMarket; } // dispatch call result to apropriate market return emulatorMarket.onGetMarketTradedVolumeCompressed(result); } // Feed market traded volumes to emulator Emulator.prototype.onGetMarketTradedVolume = function(result) { var self = this; // the problem is there is no marketId and selectionId in getTradedVolume // response // it is unlikely the call would be ever supported throw new Error('Not yet implemented'); } // Process getMUBets API call Emulator.prototype.handleGetMUBets = function(req, res, cb) { var self = this; // parse incoming XML req.request = decoder.decode(req.xmlRequestBody); // default response res.response = { errorCode : 'NO_RESULT', minorErrorCode : null, bets : null }; setResponseHeader(req.request, res.response); // check marketId // Currently only getMUBets with marketId is supported, otherwise 5x weight // is applied by Betfair // Where market ID = 0 the weighting is 5. Four requests in a second would // not incur a charge, // a 5th request in the same second would be charged at 0.5p. var marketId = req.request.marketId; if (!marketId || !self.markets[marketId]) { // no market in emulator res.response.errorCode = 'INVALID_MARKET_ID'; res.xmlResponseBody = encoder.encode(res.action, res.response); cb(null, res); return; } // handle invocation var market = self.markets[marketId]; market.handleGetMUBets(req, res, function(err, res) { // serialize response res.xmlResponseBody = encoder.encode(res.action, res.response); cb(null, res); }); return; } // Process getCurrentBets API call Emulator.prototype.handleGetCurrentBets = function(req, res, cb) { var self = this; // parse incoming XML req.request = decoder.decode(req.xmlRequestBody); // default response res.response = { errorCode : 'NO_RESULT', minorErrorCode : null, bets : null }; setResponseHeader(req.request, res.response); // check marketId // Currently only getCurrentBets with marketId is supported, otherwise 5x // weight is applied by Betfair // Where market ID = 0 the weighting is 5. Four requests in a second would // not incur a charge, // a 5th request in the same second would be charged at 0.5p. var marketId = req.request.marketId; if (!marketId || !self.markets[marketId]) { // no market in emulator res.response.errorCode = 'INVALID_MARKET_ID'; res.xmlResponseBody = encoder.encode(res.action, res.response); cb(null, res); return; } // handle invocation var market = self.markets[marketId]; market.handleGetCurrentBets(req, res, function(err, res) { // serialize response res.xmlResponseBody = encoder.encode(res.action, res.response); cb(null, res); }); return; } // Process getCurrentBets API call Emulator.prototype.handleGetMarketProfitAndLoss = function(req, res, cb) { var self = this; // parse incoming XML req.request = decoder.decode(req.xmlRequestBody); // default response res.response = { errorCode : 'INVALID_MARKET', minorErrorCode : null, annotations : null, commissionApplied : 0, currencyCode : 'USD', // get from prices later, for now USD includesSettledBets : false, includesBspBets : false, marketId : req.request.marketID || '0', marketName : "Emulated Market " + (req.request.marketId || '0'), marketStatus : "INVALID", unit : "N/A" }; setResponseHeader(req.request, res.response); // check marketId var marketId = req.request.marketID; if (!marketId || !self.markets[marketId]) { // no market in emulator res.xmlResponseBody = encoder.encode(res.action, res.response); cb(null, res); return; } // handle invocation var market = self.markets[marketId]; market.handleGetMarketProfitAndLoss(req, res, function(err, res) { // serialize response res.xmlResponseBody = encoder.encode(res.action, res.response); cb(null, res); }); return; } // Process placeBets API call Emulator.prototype.handlePlaceBets = function(req, res, cb) { var self = this; // parse incoming XML req.request = decoder.decode(req.xmlRequestBody); // default response res.response = { errorCode : 'INVALID_MARKET', minorErrorCode : null, betResults : null }; setResponseHeader(req.request, res.response); // ensure all the bets have the same marketId var marketIds = req.request.bets.map(function(item) { return item.marketId; }); var marketId = marketIds.reduce(function(item1, item2) { return item1 === item2 ? item1 : null; }); if (!marketId) { // different marketIds res.response.errorCode = 'DIFFERING_MARKETS'; res.xmlResponseBody = encoder.encode(res.action, res.response); cb(null, res); return; } if (!self.markets[marketId]) { // no market in emulator res.response.errorCode = 'INVALID_MARKET'; res.xmlResponseBody = encoder.encode(res.action, res.response); cb(null, res); return; } // handle invocation var market = self.markets[marketId]; market.handlePlaceBets(req, res, function(err, res) { // serialize response res.xmlResponseBody = encoder.encode(res.action, res.response); cb(null, res); }); } // Process updateBets API call Emulator.prototype.handleUpdateBets = function(req, res, cb) { var self = this; // parse incoming XML req.request = decoder.decode(req.xmlRequestBody); // default response res.response = { errorCode : 'INVALID_MARKET', minorErrorCode : null, betResults : null }; setResponseHeader(req.request, res.response); // just SOAP Fault for now res.response.soapFault = true; res.xmlResponseBody = encoder.encode(res.action, res.response); cb(null, res); } // Process cancelBets API call Emulator.prototype.handleCancelBets = function(req, res, cb) { var self = this; // parse incoming XML req.request = decoder.decode(req.xmlRequestBody); // default response res.response = { errorCode : 'INVALID_MARKET', minorErrorCode : null, betResults : null }; setResponseHeader(req.request, res.response); // make list of bets var betIds = req.request && req.request.bets.map(function(item) { return item.betId; }); if (betIds.length < 1) { // different marketIds res.response.errorCode = 'INVALID_NUMER_OF_CANCELLATIONS'; res.xmlResponseBody = encoder.encode(res.action, res.response); cb(null, res); return; } // find marketId var marketId; for ( var markId in self.markets) { var market = self.markets[markId]; if (market.allBetsAreMine(betIds)) { marketId = markId; break; } } if (!marketId) { // different marketIds res.response.errorCode = 'INVALID_MARKET_ID'; res.xmlResponseBody = encoder.encode(res.action, res.response); cb(null, res); return; } // handle invocation var market = self.markets[marketId]; market.handleCancelBets(req, res, function(err, res) { // serialize response res.xmlResponseBody = encoder.encode(res.action, res.response); cb(null, res); }); } // handle header function setResponseHeader(req, res) { res.header = { errorCode : "OK", minorErrorCode : null, sessionToken : req.header.sessionToken, timestamp : new Date() }; return; } // Emulator is a singleton object module.exports = new Emulator();