UNPKG

betfair-exchange-api

Version:

A TypeScript client for the Betfair Exchange API

510 lines (509 loc) 23 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.BetfairClient = exports.HeartbeatAPI = exports.AccountsAPI = exports.BettingAPI = exports.BetfairApiBase = exports.ActionPerformed = exports.Wallet = exports.IncludeItem = exports.SubscriptionStatus = exports.TimeGranularity = exports.GroupBy = exports.BetStatus = exports.BetTargetType = exports.TimeInForce = exports.PersistenceType = exports.OrderType = exports.Side = exports.OrderProjection = exports.MatchProjection = exports.PriceData = exports.MarketSort = exports.MarketProjection = exports.OrderStatus = exports.MarketBettingType = void 0; const axios_1 = __importDefault(require("axios")); const https_1 = __importDefault(require("https")); var MarketBettingType; (function (MarketBettingType) { MarketBettingType["ODDS"] = "ODDS"; MarketBettingType["LINE"] = "LINE"; MarketBettingType["RANGE"] = "RANGE"; MarketBettingType["ASIAN_HANDICAP_DOUBLE_LINE"] = "ASIAN_HANDICAP_DOUBLE_LINE"; MarketBettingType["ASIAN_HANDICAP_SINGLE_LINE"] = "ASIAN_HANDICAP_SINGLE_LINE"; MarketBettingType["FIXED_ODDS"] = "FIXED_ODDS"; })(MarketBettingType || (exports.MarketBettingType = MarketBettingType = {})); var OrderStatus; (function (OrderStatus) { OrderStatus["PENDING"] = "PENDING"; OrderStatus["EXECUTION_COMPLETE"] = "EXECUTION_COMPLETE"; OrderStatus["EXECUTABLE"] = "EXECUTABLE"; OrderStatus["EXPIRED"] = "EXPIRED"; })(OrderStatus || (exports.OrderStatus = OrderStatus = {})); var MarketProjection; (function (MarketProjection) { MarketProjection["COMPETITION"] = "COMPETITION"; MarketProjection["EVENT"] = "EVENT"; MarketProjection["EVENT_TYPE"] = "EVENT_TYPE"; MarketProjection["MARKET_START_TIME"] = "MARKET_START_TIME"; MarketProjection["MARKET_DESCRIPTION"] = "MARKET_DESCRIPTION"; MarketProjection["RUNNER_DESCRIPTION"] = "RUNNER_DESCRIPTION"; MarketProjection["RUNNER_METADATA"] = "RUNNER_METADATA"; })(MarketProjection || (exports.MarketProjection = MarketProjection = {})); var MarketSort; (function (MarketSort) { MarketSort["MINIMUM_TRADED"] = "MINIMUM_TRADED"; MarketSort["MAXIMUM_TRADED"] = "MAXIMUM_TRADED"; MarketSort["MINIMUM_AVAILABLE"] = "MINIMUM_AVAILABLE"; MarketSort["MAXIMUM_AVAILABLE"] = "MAXIMUM_AVAILABLE"; MarketSort["FIRST_TO_START"] = "FIRST_TO_START"; MarketSort["LAST_TO_START"] = "LAST_TO_START"; })(MarketSort || (exports.MarketSort = MarketSort = {})); var PriceData; (function (PriceData) { PriceData["SP_AVAILABLE"] = "SP_AVAILABLE"; PriceData["SP_TRADED"] = "SP_TRADED"; PriceData["EX_BEST_OFFERS"] = "EX_BEST_OFFERS"; PriceData["EX_ALL_OFFERS"] = "EX_ALL_OFFERS"; PriceData["EX_TRADED"] = "EX_TRADED"; })(PriceData || (exports.PriceData = PriceData = {})); var MatchProjection; (function (MatchProjection) { MatchProjection["NO_ROLLUP"] = "NO_ROLLUP"; MatchProjection["ROLLED_UP_BY_PRICE"] = "ROLLED_UP_BY_PRICE"; MatchProjection["ROLLED_UP_BY_AVG_PRICE"] = "ROLLED_UP_BY_AVG_PRICE"; })(MatchProjection || (exports.MatchProjection = MatchProjection = {})); var OrderProjection; (function (OrderProjection) { OrderProjection["ALL"] = "ALL"; OrderProjection["EXECUTABLE"] = "EXECUTABLE"; OrderProjection["EXECUTION_COMPLETE"] = "EXECUTION_COMPLETE"; })(OrderProjection || (exports.OrderProjection = OrderProjection = {})); var Side; (function (Side) { Side["BACK"] = "BACK"; Side["LAY"] = "LAY"; })(Side || (exports.Side = Side = {})); var OrderType; (function (OrderType) { OrderType["LIMIT"] = "LIMIT"; OrderType["LIMIT_ON_CLOSE"] = "LIMIT_ON_CLOSE"; OrderType["MARKET_ON_CLOSE"] = "MARKET_ON_CLOSE"; })(OrderType || (exports.OrderType = OrderType = {})); var PersistenceType; (function (PersistenceType) { PersistenceType["LAPSE"] = "LAPSE"; PersistenceType["PERSIST"] = "PERSIST"; PersistenceType["MARKET_ON_CLOSE"] = "MARKET_ON_CLOSE"; })(PersistenceType || (exports.PersistenceType = PersistenceType = {})); var TimeInForce; (function (TimeInForce) { TimeInForce["FILL_OR_KILL"] = "FILL_OR_KILL"; })(TimeInForce || (exports.TimeInForce = TimeInForce = {})); var BetTargetType; (function (BetTargetType) { BetTargetType["BACKERS_PROFIT"] = "BACKERS_PROFIT"; BetTargetType["PAYOUT"] = "PAYOUT"; })(BetTargetType || (exports.BetTargetType = BetTargetType = {})); var BetStatus; (function (BetStatus) { BetStatus["SETTLED"] = "SETTLED"; BetStatus["VOIDED"] = "VOIDED"; BetStatus["LAPSED"] = "LAPSED"; BetStatus["CANCELLED"] = "CANCELLED"; })(BetStatus || (exports.BetStatus = BetStatus = {})); var GroupBy; (function (GroupBy) { GroupBy["EVENT_TYPE"] = "EVENT_TYPE"; GroupBy["EVENT"] = "EVENT"; GroupBy["MARKET"] = "MARKET"; GroupBy["SIDE"] = "SIDE"; GroupBy["BET"] = "BET"; })(GroupBy || (exports.GroupBy = GroupBy = {})); var TimeGranularity; (function (TimeGranularity) { TimeGranularity["DAYS"] = "DAYS"; TimeGranularity["HOURS"] = "HOURS"; TimeGranularity["MINUTES"] = "MINUTES"; })(TimeGranularity || (exports.TimeGranularity = TimeGranularity = {})); var SubscriptionStatus; (function (SubscriptionStatus) { SubscriptionStatus["ALL"] = "ALL"; SubscriptionStatus["ACTIVATED"] = "ACTIVATED"; SubscriptionStatus["UNACTIVATED"] = "UNACTIVATED"; SubscriptionStatus["CANCELLED"] = "CANCELLED"; SubscriptionStatus["EXPIRED"] = "EXPIRED"; })(SubscriptionStatus || (exports.SubscriptionStatus = SubscriptionStatus = {})); var IncludeItem; (function (IncludeItem) { IncludeItem["ALL"] = "ALL"; IncludeItem["DEPOSITS_WITHDRAWALS"] = "DEPOSITS_WITHDRAWALS"; IncludeItem["EXCHANGE"] = "EXCHANGE"; IncludeItem["POKER_ROOM"] = "POKER_ROOM"; })(IncludeItem || (exports.IncludeItem = IncludeItem = {})); var Wallet; (function (Wallet) { Wallet["UK"] = "UK"; })(Wallet || (exports.Wallet = Wallet = {})); var ActionPerformed; (function (ActionPerformed) { ActionPerformed["NONE"] = "NONE"; ActionPerformed["CANCELLATION_REQUEST_SUBMITTED"] = "CANCELLATION_REQUEST_SUBMITTED"; ActionPerformed["ALL_BETS_CANCELLED"] = "ALL_BETS_CANCELLED"; ActionPerformed["SOME_BETS_NOT_CANCELLED"] = "SOME_BETS_NOT_CANCELLED"; ActionPerformed["CANCELLATION_REQUEST_ERROR"] = "CANCELLATION_REQUEST_ERROR"; ActionPerformed["CANCELLATION_STATUS_UNKNOWN"] = "CANCELLATION_STATUS_UNKNOWN"; })(ActionPerformed || (exports.ActionPerformed = ActionPerformed = {})); // ========================================================================= // Main API Client Class // ========================================================================= // Create a base class for shared functionality class BetfairApiBase { constructor(appKey) { this.sessionToken = null; this.appKey = appKey; this.axiosInstance = axios_1.default.create({ headers: { 'Content-Type': 'application/json', }, }); } setSessionToken(token) { this.sessionToken = token; } async executeRequest(method, params) { if (!this.sessionToken) { throw new Error('Not authenticated. Call authenticate first.'); } const config = { headers: { 'X-Application': this.appKey, 'X-Authentication': this.sessionToken, }, }; const jsonRpcRequest = { jsonrpc: '2.0', method: method, params: params, id: 1, }; try { const response = await this.axiosInstance.post(method, jsonRpcRequest, config); if (response.data.error) { throw new Error(`API error: ${response.data.error.message}`); } return response.data.result; } catch (error) { throw new Error(`API execution error: ${error instanceof Error ? error.message : 'Unknown error'}`); } } } exports.BetfairApiBase = BetfairApiBase; // Update API classes to use composition instead of inheritance class BettingAPI { constructor(appKey) { this.endpoint = 'https://api.betfair.com/exchange/betting/json-rpc/v1'; this.prefix = 'SportsAPING/v1.0'; this.base = new BetfairApiBase(appKey); } setSessionToken(token) { this.base.setSessionToken(token); } async listEventTypes(filter = {}, locale) { return this.base.executeRequest(`${this.endpoint}/${this.prefix}/listEventTypes`, { filter, locale }); } async listCompetitions(filter = {}, locale) { return this.base.executeRequest(`${this.endpoint}/${this.prefix}/listCompetitions`, { filter, locale }); } async listTimeRanges(filter = {}, granularity = TimeGranularity.DAYS) { return this.base.executeRequest(`${this.endpoint}/${this.prefix}/listTimeRanges`, { filter, granularity }); } async listEvents(filter = {}, locale) { return this.base.executeRequest(`${this.endpoint}/${this.prefix}/listEvents`, { filter, locale }); } async listMarketTypes(filter = {}, locale) { return this.base.executeRequest(`${this.endpoint}/${this.prefix}/listMarketTypes`, { filter, locale }); } async listCountries(filter = {}, locale) { return this.base.executeRequest(`${this.endpoint}/${this.prefix}/listCountries`, { filter, locale }); } async listVenues(filter = {}, locale) { return this.base.executeRequest(`${this.endpoint}/${this.prefix}/listVenues`, { filter, locale }); } async listMarketCatalogue(filter = {}, marketProjection, sort, maxResults = 1, locale) { return this.base.executeRequest(`${this.endpoint}/${this.prefix}/listMarketCatalogue`, { filter, marketProjection, sort, maxResults, locale }); } async listMarketBook(marketIds, priceProjection, orderProjection, matchProjection, includeOverallPosition, partitionMatchedByStrategyRef, customerStrategyRefs, currencyCode, locale, matchedSince, betIds) { return this.base.executeRequest(`${this.endpoint}/${this.prefix}/listMarketBook`, { marketIds, priceProjection, orderProjection, matchProjection, includeOverallPosition, partitionMatchedByStrategyRef, customerStrategyRefs, currencyCode, locale, matchedSince, betIds, }); } async listRunnerBook(marketId, selectionId, handicap = 0, priceProjection, orderProjection, matchProjection, includeOverallPosition, partitionMatchedByStrategyRef, customerStrategyRefs, currencyCode, locale, matchedSince, betIds) { return this.base.executeRequest(`${this.endpoint}/${this.prefix}/listRunnerBook`, { marketId, selectionId, handicap, priceProjection, orderProjection, matchProjection, includeOverallPosition, partitionMatchedByStrategyRef, customerStrategyRefs, currencyCode, locale, matchedSince, betIds, }); } async listMarketProfitAndLoss(marketIds, includeSettledBets, includeBspBets, netOfCommission) { return this.base.executeRequest(`${this.endpoint}/${this.prefix}/listMarketProfitAndLoss`, { marketIds, includeSettledBets, includeBspBets, netOfCommission }); } async listCurrentOrders(betIds, marketIds, orderProjection, customerOrderRefs, customerStrategyRefs, dateRange, orderBy, sortDir, fromRecord, recordCount, includeItemDescription) { return this.base.executeRequest(`${this.endpoint}/${this.prefix}/listCurrentOrders`, { betIds, marketIds, orderProjection, customerOrderRefs, customerStrategyRefs, dateRange, orderBy, sortDir, fromRecord, recordCount, includeItemDescription, }); } async listClearedOrders(betStatus, eventTypeIds, eventIds, marketIds, runnerIds, betIds, customerOrderRefs, customerStrategyRefs, side, settledDateRange, groupBy, includeItemDescription, locale, fromRecord, recordCount) { return this.base.executeRequest(`${this.endpoint}/${this.prefix}/listClearedOrders`, { betStatus, eventTypeIds, eventIds, marketIds, runnerIds, betIds, customerOrderRefs, customerStrategyRefs, side, settledDateRange, groupBy, includeItemDescription, locale, fromRecord, recordCount, }); } async placeOrders(marketId, instructions, customerRef, marketVersion, customerStrategyRef, async) { return this.base.executeRequest(`${this.endpoint}/${this.prefix}/placeOrders`, { marketId, instructions, customerRef, marketVersion, customerStrategyRef, async, }); } async cancelOrders(marketId, instructions, customerRef) { return this.base.executeRequest(`${this.endpoint}/${this.prefix}/cancelOrders`, { marketId, instructions, customerRef }); } async replaceOrders(marketId, instructions, customerRef, marketVersion, async) { return this.base.executeRequest(`${this.endpoint}/${this.prefix}/replaceOrders`, { marketId, instructions, customerRef, marketVersion, async }); } async updateOrders(marketId, instructions, customerRef) { return this.base.executeRequest(`${this.endpoint}/${this.prefix}/updateOrders`, { marketId, instructions, customerRef }); } } exports.BettingAPI = BettingAPI; class AccountsAPI { constructor(appKey) { this.endpoint = 'https://api.betfair.com/exchange/account/json-rpc/v1'; this.prefix = 'AccountAPING/v1.0'; this.base = new BetfairApiBase(appKey); } setSessionToken(token) { this.base.setSessionToken(token); } async createDeveloperAppKeys(appName) { return this.base.executeRequest(`${this.endpoint}/${this.prefix}/createDeveloperAppKeys`, { appName }); } async getDeveloperAppKeys() { return this.base.executeRequest(`${this.endpoint}/${this.prefix}/getDeveloperAppKeys`, {}); } async getAccountFunds(wallet) { return this.base.executeRequest(`${this.endpoint}/${this.prefix}/getAccountFunds`, { wallet }); } async getAccountDetails() { return this.base.executeRequest(`${this.endpoint}/${this.prefix}/getAccountDetails`, {}); } async getVendorClientId() { return this.base.executeRequest(`${this.endpoint}/${this.prefix}/getVendorClientId`, {}); } async getApplicationSubscriptionToken(subscriptionLength, clientReference) { return this.base.executeRequest(`${this.endpoint}/${this.prefix}/getApplicationSubscriptionToken`, { subscriptionLength, clientReference }); } async activateApplicationSubscription(subscriptionToken) { return this.base.executeRequest(`${this.endpoint}/${this.prefix}/activateApplicationSubscription`, { subscriptionToken }); } async cancelApplicationSubscription(subscriptionToken) { return this.base.executeRequest(`${this.endpoint}/${this.prefix}/cancelApplicationSubscription`, { subscriptionToken }); } async updateApplicationSubscription(vendorClientId, subscriptionLength) { return this.base.executeRequest(`${this.endpoint}/${this.prefix}/updateApplicationSubscription`, { vendorClientId, subscriptionLength }); } async listApplicationSubscriptionTokens(subscriptionStatus) { return this.base.executeRequest(`${this.endpoint}/${this.prefix}/listApplicationSubscriptionTokens`, { subscriptionStatus }); } async listAccountSubscriptionTokens() { return this.base.executeRequest(`${this.endpoint}/${this.prefix}/listAccountSubscriptionTokens`, {}); } async getApplicationSubscriptionHistory(vendorClientId, applicationKey) { return this.base.executeRequest(`${this.endpoint}/${this.prefix}/getApplicationSubscriptionHistory`, { vendorClientId, applicationKey }); } async getAccountStatement(locale, fromRecord, recordCount, itemDateRange, includeItem, wallet) { return this.base.executeRequest(`${this.endpoint}/${this.prefix}/getAccountStatement`, { locale, fromRecord, recordCount, itemDateRange, includeItem, wallet }); } async listCurrencyRates(fromCurrency) { return this.base.executeRequest(`${this.endpoint}/${this.prefix}/listCurrencyRates`, { fromCurrency }); } async token(clientId, grantType, code, clientSecret, refreshToken) { return this.base.executeRequest(`${this.endpoint}/${this.prefix}/token`, { client_id: clientId, grant_type: grantType, code, client_secret: clientSecret, refresh_token: refreshToken }); } async getVendorDetails(vendorId) { return this.base.executeRequest(`${this.endpoint}/${this.prefix}/getVendorDetails`, { vendorId }); } async revokeAccessToWebApp(vendorId) { return this.base.executeRequest(`${this.endpoint}/${this.prefix}/revokeAccessToWebApp`, { vendorId }); } async listAuthorizedWebApps() { return this.base.executeRequest(`${this.endpoint}/${this.prefix}/listAuthorizedWebApps`, {}); } async isAccountSubscribedToWebApp(vendorId) { return this.base.executeRequest(`${this.endpoint}/${this.prefix}/isAccountSubscribedToWebApp`, { vendorId }); } async getAffiliateRelation(vendorClientIds) { return this.base.executeRequest(`${this.endpoint}/${this.prefix}/getAffiliateRelation`, { vendorClientIds }); } } exports.AccountsAPI = AccountsAPI; class HeartbeatAPI { constructor(appKey) { this.endpoint = 'https://api.betfair.com/exchange/heartbeat/json-rpc/v1'; this.prefix = 'HeartbeatAPING/v1.0'; this.base = new BetfairApiBase(appKey); } setSessionToken(token) { this.base.setSessionToken(token); } async heartbeat(preferredTimeoutSeconds) { return this.base.executeRequest(`${this.endpoint}/${this.prefix}/heartbeat`, { preferredTimeoutSeconds }); } } exports.HeartbeatAPI = HeartbeatAPI; // Main client class class BetfairClient extends BetfairApiBase { constructor(appKey, config) { super(appKey); this.exchangeApi = new BettingAPI(appKey); this.accountsApi = new AccountsAPI(appKey); this.heartbeatApi = new HeartbeatAPI(appKey); } get betting() { return this.exchangeApi; } get accounts() { return this.accountsApi; } get heartbeat() { return this.heartbeatApi; } async authenticate(username, password, certificatePath) { try { const config = { headers: { 'X-Application': this.appKey, 'Content-Type': 'application/x-www-form-urlencoded', }, }; if (certificatePath) { config.httpsAgent = new https_1.default.Agent({ cert: certificatePath }); } const response = await axios_1.default.post('https://identitysso-cert.betfair.com/api/certlogin', `username=${encodeURIComponent(username)}&password=${encodeURIComponent(password)}`, config); if (response.data.loginStatus === 'SUCCESS') { const sessionToken = response.data.sessionToken; this.sessionToken = sessionToken; // Propagate session token to API instances this.exchangeApi.setSessionToken(sessionToken); this.accountsApi.setSessionToken(sessionToken); this.heartbeatApi.setSessionToken(sessionToken); } else { throw new Error(`Authentication failed: ${response.data.loginStatus}`); } } catch (error) { throw new Error(`Authentication error: ${error instanceof Error ? error.message : 'Unknown error'}`); } } async keepAlive() { try { const response = await axios_1.default.get('https://identitysso.betfair.com/api/keepAlive', { headers: { 'Accept': 'application/json', 'X-Application': this.appKey, 'X-Authentication': this.sessionToken, }, }); return response.data.status === 'SUCCESS'; } catch (error) { throw new Error(`Keep alive error: ${error instanceof Error ? error.message : 'Unknown error'}`); } } async logout() { try { const response = await axios_1.default.get('https://identitysso.betfair.com/api/logout', { headers: { 'Accept': 'application/json', 'X-Application': this.appKey, 'X-Authentication': this.sessionToken, }, }); if (response.data.status === 'SUCCESS') { this.sessionToken = null; // Clear session token from API instances this.exchangeApi.setSessionToken(null); this.accountsApi.setSessionToken(null); this.heartbeatApi.setSessionToken(null); return true; } return false; } catch (error) { throw new Error(`Logout error: ${error instanceof Error ? error.message : 'Unknown error'}`); } } getAppKey() { return this.appKey; } getSessionToken() { return this.sessionToken; } async authenticateInteractive(username, password) { try { const response = await axios_1.default.post('https://identitysso.betfair.com/api/login', `username=${encodeURIComponent(username)}&password=${encodeURIComponent(password)}`, { headers: { 'X-Application': this.appKey, 'Content-Type': 'application/x-www-form-urlencoded', }, }); if (response.data.status === 'SUCCESS') { const sessionToken = response.data.token; this.sessionToken = sessionToken; this.exchangeApi.setSessionToken(sessionToken); this.accountsApi.setSessionToken(sessionToken); this.heartbeatApi.setSessionToken(sessionToken); } else { throw new Error(`Authentication failed: ${response.data.error}`); } } catch (error) { throw new Error(`Authentication error: ${error instanceof Error ? error.message : 'Unknown error'}`); } } } exports.BetfairClient = BetfairClient;